3 Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>,
4 2000-2003 Guus Sliepen <guus@sliepen.eu.org>
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.58 2003/07/15 16:26:18 guus Exp $
25 #ifdef HAVE_SYS_PARAM_H
26 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
33 #ifdef HAVE_NET_ETHERNET_H
34 #include <net/ethernet.h>
36 #ifdef HAVE_NETINET_IN_SYSTM_H
37 #include <netinet/in_systm.h>
39 #include <netinet/ip.h>
40 #include <netinet/ip_icmp.h>
41 #ifdef HAVE_NETINET_IP6_H
42 #include <netinet/ip6.h>
43 #include <netinet/icmp6.h>
45 #include <netinet/if_ether.h>
49 #ifdef HAVE_INTTYPES_H
56 #include "connection.h"
65 /* Missing definitions */
67 #ifndef ETHER_ADDR_LEN
68 #define ETHER_ADDR_LEN 6
71 #ifndef ICMP_DEST_UNREACH
72 #define ICMP_DEST_UNREACH 3
75 #ifndef ICMP_NET_UNKNOWN
76 #define ICMP_NET_UNKNOWN 6
79 #ifndef ICMP_NET_UNREACH
80 #define ICMP_NET_UNREACH 0
83 int routing_mode = RMODE_ROUTER;
84 int priorityinheritance = 0;
86 int overwrite_mac = 0;
87 mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
91 static uint16_t inet_checksum(void *data, int len, uint16_t prevsum)
94 uint32_t checksum = prevsum ^ 0xFFFF;
102 checksum += *(unsigned char *)p;
104 while(checksum >> 16)
105 checksum = (checksum & 0xFFFF) + (checksum >> 16);
110 static int ratelimit(void) {
111 static time_t lasttime = 0;
120 static void learn_mac(mac_t *address)
128 subnet = lookup_subnet_mac(address);
130 /* If we don't know this MAC address yet, store it */
132 if(!subnet || subnet->owner != myself) {
133 ifdebug(TRAFFIC) logger(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
134 address->x[0], address->x[1], address->x[2], address->x[3],
135 address->x[4], address->x[5]);
137 subnet = new_subnet();
138 subnet->type = SUBNET_MAC;
139 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
140 subnet_add(myself, subnet);
142 /* And tell all other tinc daemons it's our MAC */
144 for(node = connection_tree->head; node; node = node->next) {
145 c = (connection_t *) node->data;
147 send_add_subnet(c, subnet);
151 subnet->net.mac.lastseen = now;
158 avl_node_t *node, *next, *node2;
162 for(node = myself->subnet_tree->head; node; node = next) {
164 s = (subnet_t *) node->data;
165 if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) {
166 ifdebug(TRAFFIC) logger(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
167 s->net.mac.address.x[0], s->net.mac.address.x[1],
168 s->net.mac.address.x[2], s->net.mac.address.x[3],
169 s->net.mac.address.x[4], s->net.mac.address.x[5]);
171 for(node2 = connection_tree->head; node2; node2 = node2->next) {
172 c = (connection_t *) node2->data;
174 send_del_subnet(c, s);
177 subnet_del(myself, s);
182 static node_t *route_mac(vpn_packet_t *packet)
188 /* Learn source address */
190 learn_mac((mac_t *)(&packet->data[6]));
192 /* Lookup destination address */
194 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
197 return subnet->owner;
204 static void route_ipv4_unreachable(vpn_packet_t *packet, uint8_t code)
209 struct in_addr ip_src;
210 struct in_addr ip_dst;
218 hdr = (struct ip *)(packet->data + 14);
219 icmp = (struct icmp *)(packet->data + 14 + 20);
221 /* Remember original source and destination */
223 memcpy(&ip_src, &hdr->ip_src, 4);
224 memcpy(&ip_dst, &hdr->ip_dst, 4);
225 oldlen = packet->len - 14;
227 if(oldlen >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
228 oldlen = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
230 /* Copy first part of original contents to ICMP message */
232 memmove(&icmp->icmp_ip, hdr, oldlen);
234 /* Fill in IPv4 header */
237 hdr->ip_hl = sizeof(*hdr) / 4;
239 hdr->ip_len = htons(20 + 8 + oldlen);
243 hdr->ip_p = IPPROTO_ICMP;
245 memcpy(&hdr->ip_src, &ip_dst, 4);
246 memcpy(&hdr->ip_dst, &ip_src, 4);
248 hdr->ip_sum = inet_checksum(hdr, 20, ~0);
250 /* Fill in ICMP header */
252 icmp->icmp_type = ICMP_DEST_UNREACH;
253 icmp->icmp_code = code;
254 icmp->icmp_cksum = 0;
256 icmp->icmp_cksum = inet_checksum(icmp, 8 + oldlen, ~0);
258 packet->len = 14 + 20 + 8 + oldlen;
260 write_packet(packet);
263 static node_t *route_ipv4(vpn_packet_t *packet)
269 if(priorityinheritance)
270 packet->priority = packet->data[15];
272 subnet = lookup_subnet_ipv4((ipv4_t *) & packet->data[30]);
275 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
276 packet->data[30], packet->data[31], packet->data[32],
279 route_ipv4_unreachable(packet, ICMP_NET_UNKNOWN);
283 if(!subnet->owner->status.reachable)
284 route_ipv4_unreachable(packet, ICMP_NET_UNREACH);
286 return subnet->owner;
291 static void route_ipv6_unreachable(vpn_packet_t *packet, uint8_t code)
294 struct icmp6_hdr *icmp;
298 struct in6_addr ip6_src; /* source address */
299 struct in6_addr ip6_dst; /* destination address */
309 hdr = (struct ip6_hdr *)(packet->data + 14);
310 icmp = (struct icmp6_hdr *)(packet->data + 14 + sizeof(*hdr));
312 /* Remember original source and destination */
314 memcpy(&pseudo.ip6_src, &hdr->ip6_dst, 16);
315 memcpy(&pseudo.ip6_dst, &hdr->ip6_src, 16);
316 pseudo.length = ntohs(hdr->ip6_plen) + sizeof(*hdr);
318 if(pseudo.length >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
319 pseudo.length = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
321 /* Copy first part of original contents to ICMP message */
323 memmove(((char *)icmp) + sizeof(*icmp), hdr, pseudo.length);
325 /* Fill in IPv6 header */
327 hdr->ip6_flow = htonl(0x60000000UL);
328 hdr->ip6_plen = htons(sizeof(*icmp) + pseudo.length);
329 hdr->ip6_nxt = IPPROTO_ICMPV6;
331 memcpy(&hdr->ip6_dst, &pseudo.ip6_dst, 16);
332 memcpy(&hdr->ip6_src, &pseudo.ip6_src, 16);
334 /* Fill in ICMP header */
336 icmp->icmp6_type = ICMP6_DST_UNREACH;
337 icmp->icmp6_code = code;
338 icmp->icmp6_cksum = 0;
340 /* Create pseudo header */
342 pseudo.length = htonl(sizeof(*icmp) + pseudo.length);
343 pseudo.next = htonl(IPPROTO_ICMPV6);
345 /* Generate checksum */
347 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
348 checksum = inet_checksum(icmp, ntohl(pseudo.length), checksum);
350 icmp->icmp6_cksum = checksum;
352 packet->len = 14 + sizeof(*hdr) + ntohl(pseudo.length);
354 write_packet(packet);
357 static node_t *route_ipv6(vpn_packet_t *packet)
363 subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
366 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
367 ntohs(*(uint16_t *) & packet->data[38]),
368 ntohs(*(uint16_t *) & packet->data[40]),
369 ntohs(*(uint16_t *) & packet->data[42]),
370 ntohs(*(uint16_t *) & packet->data[44]),
371 ntohs(*(uint16_t *) & packet->data[46]),
372 ntohs(*(uint16_t *) & packet->data[48]),
373 ntohs(*(uint16_t *) & packet->data[50]),
374 ntohs(*(uint16_t *) & packet->data[52]));
375 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_ADDR);
380 if(!subnet->owner->status.reachable)
381 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_NOROUTE);
383 return subnet->owner;
388 static void route_neighborsol(vpn_packet_t *packet)
391 struct nd_neighbor_solicit *ns;
392 struct nd_opt_hdr *opt;
397 struct in6_addr ip6_src; /* source address */
398 struct in6_addr ip6_dst; /* destination address */
405 hdr = (struct ip6_hdr *)(packet->data + 14);
406 ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr));
407 opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
409 /* First, snatch the source address from the neighbor solicitation packet */
412 memcpy(mymac.x, packet->data + 6, 6);
414 /* Check if this is a valid neighbor solicitation request */
416 if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
417 opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
418 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
422 /* Create pseudo header */
424 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
425 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
426 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
427 pseudo.next = htonl(IPPROTO_ICMPV6);
429 /* Generate checksum */
431 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
432 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
435 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
439 /* Check if the IPv6 address exists on the VPN */
441 subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
444 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
445 ntohs(((uint16_t *) & ns->nd_ns_target)[0]),
446 ntohs(((uint16_t *) & ns->nd_ns_target)[1]),
447 ntohs(((uint16_t *) & ns->nd_ns_target)[2]),
448 ntohs(((uint16_t *) & ns->nd_ns_target)[3]),
449 ntohs(((uint16_t *) & ns->nd_ns_target)[4]),
450 ntohs(((uint16_t *) & ns->nd_ns_target)[5]),
451 ntohs(((uint16_t *) & ns->nd_ns_target)[6]),
452 ntohs(((uint16_t *) & ns->nd_ns_target)[7]));
457 /* Check if it is for our own subnet */
459 if(subnet->owner == myself)
460 return; /* silently ignore */
462 /* Create neighbor advertation reply */
464 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
465 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
467 memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */
468 memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */
470 memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */
472 ns->nd_ns_hdr.icmp6_cksum = 0;
473 ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
474 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */
475 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] =
476 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] =
477 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
478 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
480 /* Create pseudo header */
482 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
483 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
484 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
485 pseudo.next = htonl(IPPROTO_ICMPV6);
487 /* Generate checksum */
489 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
490 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
492 ns->nd_ns_hdr.icmp6_cksum = checksum;
494 write_packet(packet);
499 static void route_arp(vpn_packet_t *packet)
501 struct ether_arp *arp;
507 /* First, snatch the source address from the ARP packet */
510 memcpy(mymac.x, packet->data + 6, 6);
512 /* This routine generates replies to ARP requests.
513 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
514 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
517 arp = (struct ether_arp *)(packet->data + 14);
519 /* Check if this is a valid ARP request */
521 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP ||
522 arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) {
523 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
527 /* Check if the IPv4 address exists on the VPN */
529 subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
532 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
533 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2],
538 /* Check if it is for our own subnet */
540 if(subnet->owner == myself)
541 return; /* silently ignore */
543 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
544 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
546 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
547 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
548 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
550 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
551 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
552 arp->arp_op = htons(ARPOP_REPLY);
554 write_packet(packet);
557 void route_outgoing(vpn_packet_t *packet)
564 /* FIXME: multicast? */
566 switch (routing_mode) {
568 type = ntohs(*((uint16_t *)(&packet->data[12])));
571 n = route_ipv4(packet);
575 if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
576 route_neighborsol(packet);
579 n = route_ipv6(packet);
587 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
591 send_packet(n, packet);
595 n = route_mac(packet);
597 send_packet(n, packet);
599 broadcast_packet(myself, packet);
603 broadcast_packet(myself, packet);
608 void route_incoming(node_t *source, vpn_packet_t *packet)
610 switch (routing_mode) {
616 type = ntohs(*((uint16_t *)(&packet->data[12])));
619 n = route_ipv4(packet);
623 n = route_ipv6(packet);
634 memcpy(packet->data, mymac.x, 6);
635 write_packet(packet);
637 send_packet(n, packet);
646 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
649 if(subnet->owner == myself)
650 write_packet(packet);
652 send_packet(subnet->owner, packet);
654 broadcast_packet(source, packet);
655 write_packet(packet);
661 broadcast_packet(source, packet); /* Spread it on */
662 write_packet(packet);