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.29 2002/03/10 14:04:48 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)
101 s = (subnet_t *)node->data;
102 if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now)
104 if(debug_lvl >= DEBUG_TRAFFIC)
105 syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
106 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]);
107 for(node2 = connection_tree->head; node2; node2 = node2->next)
109 c = (connection_t *)node2->data;
111 send_del_subnet(c, s);
113 subnet_del(myself, s);
119 node_t *route_mac(vpn_packet_t *packet)
123 /* Learn source address */
125 learn_mac((mac_t *)(&packet->data[6]));
127 /* Lookup destination address */
129 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
132 return subnet->owner;
137 node_t *route_ipv4(vpn_packet_t *packet)
141 if(priorityinheritance)
142 packet->priority = packet->data[15];
144 subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]);
148 if(debug_lvl >= DEBUG_TRAFFIC)
150 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
151 packet->data[30], packet->data[31], packet->data[32], packet->data[33]);
157 return subnet->owner;
160 node_t *route_ipv6(vpn_packet_t *packet)
164 subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]);
168 if(debug_lvl >= DEBUG_TRAFFIC)
170 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
171 ntohs(*(short unsigned int *)&packet->data[38]),
172 ntohs(*(short unsigned int *)&packet->data[40]),
173 ntohs(*(short unsigned int *)&packet->data[42]),
174 ntohs(*(short unsigned int *)&packet->data[44]),
175 ntohs(*(short unsigned int *)&packet->data[46]),
176 ntohs(*(short unsigned int *)&packet->data[48]),
177 ntohs(*(short unsigned int *)&packet->data[50]),
178 ntohs(*(short unsigned int *)&packet->data[52]));
184 return subnet->owner;
187 void route_arp(vpn_packet_t *packet)
189 struct ether_arp *arp;
191 unsigned char ipbuf[4];
193 /* First, snatch the source address from the ARP packet */
195 memcpy(mymac.net.mac.address.x, packet->data + 6, 6);
197 /* This routine generates replies to ARP requests.
198 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
199 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
202 arp = (struct ether_arp *)(packet->data + 14);
204 /* Check if this is a valid ARP request */
206 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER ||
207 ntohs(arp->arp_pro) != ETHERTYPE_IP ||
208 (int) (arp->arp_hln) != ETHER_ADDR_LEN ||
209 (int) (arp->arp_pln) != 4 ||
210 ntohs(arp->arp_op) != ARPOP_REQUEST )
212 if(debug_lvl > DEBUG_TRAFFIC)
214 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
219 /* Check if the IP address exists on the VPN */
221 subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa);
225 if(debug_lvl >= DEBUG_TRAFFIC)
227 syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
228 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]);
234 /* Check if it is for our own subnet */
236 if(subnet->owner == myself)
237 return; /* silently ignore */
239 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
240 packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
242 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
243 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
244 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
246 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
247 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
248 arp->arp_op = htons(ARPOP_REPLY);
250 write_packet(packet);
254 void route_outgoing(vpn_packet_t *packet)
256 unsigned short int type;
259 /* FIXME: multicast? */
264 type = ntohs(*((unsigned short*)(&packet->data[12])));
268 n = route_ipv4(packet);
271 n = route_ipv6(packet);
277 if(debug_lvl >= DEBUG_TRAFFIC)
279 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
284 send_packet(n, packet);
288 n = route_mac(packet);
290 send_packet(n, packet);
292 broadcast_packet(myself, packet);
296 broadcast_packet(myself, packet);
301 void route_incoming(node_t *source, vpn_packet_t *packet)
308 unsigned short int type;
310 type = ntohs(*((unsigned short*)(&packet->data[12])));
314 n = route_ipv4(packet);
317 n = route_ipv6(packet);
328 memcpy(packet->data, mymac.net.mac.address.x, 6);
329 write_packet(packet);
332 send_packet(n, packet);
340 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
344 if(subnet->owner == myself)
345 write_packet(packet);
347 send_packet(subnet->owner, packet);
351 broadcast_packet(source, packet);
352 write_packet(packet);
357 broadcast_packet(source, packet); /* Spread it on */
358 write_packet(packet);