3 Copyright (C) 2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000-2002 Guus Sliepen <guus@sliepen.warande.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: route.c,v 1.1.2.27 2002/03/01 14:25:10 guus Exp $
25 #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD)
26 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD)
32 #define ETHER_ADDR_LEN 6
34 #include <net/ethernet.h>
36 #include <netinet/if_ether.h>
45 #include "connection.h"
53 int routing_mode = RMODE_ROUTER;
54 int priorityinheritance = 0;
58 void learn_mac(mac_t *address)
64 subnet = lookup_subnet_mac(address);
66 /* If we don't know this MAC address yet, store it */
68 if(!subnet || subnet->owner!=myself)
70 if(debug_lvl >= DEBUG_TRAFFIC)
71 syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
72 address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]);
74 subnet = new_subnet();
75 subnet->type = SUBNET_MAC;
76 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
77 subnet_add(myself, subnet);
79 /* And tell all other tinc daemons it's our MAC */
81 for(node = connection_tree->head; node; node = node->next)
83 c = (connection_t *)node->data;
85 send_add_subnet(c, subnet);
89 subnet->net.mac.lastseen = now;
96 avl_node_t *node, *next, *node2;
98 for(node = myself->subnet_tree->head; node; node = next)
100 s = (subnet_t *)node->data;
101 if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now)
103 if(debug_lvl >= DEBUG_TRAFFIC)
104 syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
105 s->net.mac.address.x[0], s->net.mac.address.x[1], s->net.mac.address.x[2], s->net.mac.address.x[3], s->net.mac.address.x[4], s->net.mac.address.x[5]);
106 for(node2 = connection_tree->head; node2; node2 = node2->next)
108 c = (connection_t *)node2->data;
110 send_del_subnet(c, s);
112 subnet_del(myself, s);
118 node_t *route_mac(vpn_packet_t *packet)
122 /* Learn source address */
124 learn_mac((mac_t *)(&packet->data[6]));
126 /* Lookup destination address */
128 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
131 return subnet->owner;
136 node_t *route_ipv4(vpn_packet_t *packet)
140 if(priorityinheritance)
141 packet->priority = packet->data[15];
143 subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
147 if(debug_lvl >= DEBUG_TRAFFIC)
149 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
150 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
156 return subnet->owner;
159 node_t *route_ipv6(vpn_packet_t *packet)
163 subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
167 if(debug_lvl >= DEBUG_TRAFFIC)
169 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
170 ntohs(*(short unsigned int *)&packet->data[38]),
171 ntohs(*(short unsigned int *)&packet->data[40]),
172 ntohs(*(short unsigned int *)&packet->data[42]),
173 ntohs(*(short unsigned int *)&packet->data[44]),
174 ntohs(*(short unsigned int *)&packet->data[46]),
175 ntohs(*(short unsigned int *)&packet->data[48]),
176 ntohs(*(short unsigned int *)&packet->data[50]),
177 ntohs(*(short unsigned int *)&packet->data[52]));
183 return subnet->owner;
186 void route_arp(vpn_packet_t *packet)
188 struct ether_arp *arp;
190 unsigned char ipbuf[4];
192 /* First, snatch the source address from the ARP packet */
194 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
196 /* This routine generates replies to ARP requests.
197 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
198 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
201 arp = (struct ether_arp *)(packet->data + 14);
203 /* Check if this is a valid ARP request */
205 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
206 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
207 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
208 (int) (arp->arp_pln) != 4 ||
209 ntohs(arp->arp_op) != ARPOP_REQUEST )
211 if(debug_lvl > DEBUG_TRAFFIC)
213 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
218 /* Check if the IP address exists on the VPN */
220 subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
224 if(debug_lvl >= DEBUG_TRAFFIC)
226 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
227 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
233 /* Check if it is for our own subnet */
235 if(subnet->owner == myself)
236 return; /* silently ignore */
238 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
239 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
241 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
242 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
243 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
245 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
246 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
247 arp->arp_op = htons(ARPOP_REPLY);
249 write_packet(packet);
253 void route_outgoing(vpn_packet_t *packet)
255 unsigned short int type;
258 /* FIXME: multicast? */
263 type = ntohs(*((unsigned short*)(&packet->data[12])));
267 n = route_ipv4(packet);
270 n = route_ipv6(packet);
276 if(debug_lvl >= DEBUG_TRAFFIC)
278 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
283 send_packet(n, packet);
287 n = route_mac(packet);
289 send_packet(n, packet);
291 broadcast_packet(myself, packet);
295 broadcast_packet(myself, packet);
300 void route_incoming(node_t *source, vpn_packet_t *packet)
308 n = route_ipv4(packet);
314 memcpy(packet->data, mymac.net.mac.address.x, 6);
315 write_packet(packet);
318 send_packet(n, packet);
326 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
330 if(subnet->owner == myself)
331 write_packet(packet);
333 send_packet(subnet->owner, packet);
337 broadcast_packet(source, packet);
338 write_packet(packet);
343 broadcast_packet(source, packet); /* Spread it on */
344 write_packet(packet);