3 Copyright (C) 2000-2002 Ivo Timmermans <ivo@o2w.nl>,
4 2000-2002 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.55 2003/07/06 23:16:29 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 static 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 logger(DEBUG_TRAFFIC, 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 logger(DEBUG_TRAFFIC, 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 logger(DEBUG_TRAFFIC, 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;
289 #ifdef HAVE_NETINET_IP6_H
293 static void route_ipv6_unreachable(vpn_packet_t *packet, uint8_t code)
296 struct icmp6_hdr *icmp;
300 struct in6_addr ip6_src; /* source address */
301 struct in6_addr ip6_dst; /* destination address */
311 hdr = (struct ip6_hdr *)(packet->data + 14);
312 icmp = (struct icmp6_hdr *)(packet->data + 14 + sizeof(*hdr));
314 /* Remember original source and destination */
316 memcpy(&pseudo.ip6_src, &hdr->ip6_dst, 16);
317 memcpy(&pseudo.ip6_dst, &hdr->ip6_src, 16);
318 pseudo.length = ntohs(hdr->ip6_plen) + sizeof(*hdr);
320 if(pseudo.length >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
321 pseudo.length = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
323 /* Copy first part of original contents to ICMP message */
325 memmove(((char *)icmp) + sizeof(*icmp), hdr, pseudo.length);
327 /* Fill in IPv6 header */
329 hdr->ip6_flow = htonl(0x60000000UL);
330 hdr->ip6_plen = htons(sizeof(*icmp) + pseudo.length);
331 hdr->ip6_nxt = IPPROTO_ICMPV6;
333 memcpy(&hdr->ip6_dst, &pseudo.ip6_dst, 16);
334 memcpy(&hdr->ip6_src, &pseudo.ip6_src, 16);
336 /* Fill in ICMP header */
338 icmp->icmp6_type = ICMP6_DST_UNREACH;
339 icmp->icmp6_code = code;
340 icmp->icmp6_cksum = 0;
342 /* Create pseudo header */
344 pseudo.length = htonl(sizeof(*icmp) + pseudo.length);
345 pseudo.next = htonl(IPPROTO_ICMPV6);
347 /* Generate checksum */
349 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
350 checksum = inet_checksum(icmp, ntohl(pseudo.length), checksum);
352 icmp->icmp6_cksum = checksum;
354 packet->len = 14 + sizeof(*hdr) + ntohl(pseudo.length);
356 write_packet(packet);
361 static node_t *route_ipv6(vpn_packet_t *packet)
367 subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
370 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
371 ntohs(*(uint16_t *) & packet->data[38]),
372 ntohs(*(uint16_t *) & packet->data[40]),
373 ntohs(*(uint16_t *) & packet->data[42]),
374 ntohs(*(uint16_t *) & packet->data[44]),
375 ntohs(*(uint16_t *) & packet->data[46]),
376 ntohs(*(uint16_t *) & packet->data[48]),
377 ntohs(*(uint16_t *) & packet->data[50]),
378 ntohs(*(uint16_t *) & packet->data[52]));
379 #ifdef HAVE_NETINET_IP6_H
380 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_ADDR);
386 #ifdef HAVE_NETINET_IP6_H
387 if(!subnet->owner->status.reachable)
388 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_NOROUTE);
391 return subnet->owner;
394 #ifdef HAVE_NETINET_IP6_H
398 static void route_neighborsol(vpn_packet_t *packet)
401 struct nd_neighbor_solicit *ns;
402 struct nd_opt_hdr *opt;
407 struct in6_addr ip6_src; /* source address */
408 struct in6_addr ip6_dst; /* destination address */
415 hdr = (struct ip6_hdr *)(packet->data + 14);
416 ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr));
417 opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
419 /* First, snatch the source address from the neighbor solicitation packet */
422 memcpy(mymac.x, packet->data + 6, 6);
424 /* Check if this is a valid neighbor solicitation request */
426 if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
427 opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
428 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
432 /* Create pseudo header */
434 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
435 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
436 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
437 pseudo.next = htonl(IPPROTO_ICMPV6);
439 /* Generate checksum */
441 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
442 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
445 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
449 /* Check if the IPv6 address exists on the VPN */
451 subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
454 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
455 ntohs(((uint16_t *) & ns->nd_ns_target)[0]),
456 ntohs(((uint16_t *) & ns->nd_ns_target)[1]),
457 ntohs(((uint16_t *) & ns->nd_ns_target)[2]),
458 ntohs(((uint16_t *) & ns->nd_ns_target)[3]),
459 ntohs(((uint16_t *) & ns->nd_ns_target)[4]),
460 ntohs(((uint16_t *) & ns->nd_ns_target)[5]),
461 ntohs(((uint16_t *) & ns->nd_ns_target)[6]),
462 ntohs(((uint16_t *) & ns->nd_ns_target)[7]));
467 /* Check if it is for our own subnet */
469 if(subnet->owner == myself)
470 return; /* silently ignore */
472 /* Create neighbor advertation reply */
474 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
475 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
477 memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */
478 memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */
480 memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */
482 ns->nd_ns_hdr.icmp6_cksum = 0;
483 ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
484 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */
485 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] =
486 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] =
487 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
488 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
490 /* Create pseudo header */
492 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
493 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
494 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
495 pseudo.next = htonl(IPPROTO_ICMPV6);
497 /* Generate checksum */
499 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
500 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
502 ns->nd_ns_hdr.icmp6_cksum = checksum;
504 write_packet(packet);
511 static void route_arp(vpn_packet_t *packet)
513 struct ether_arp *arp;
519 /* First, snatch the source address from the ARP packet */
522 memcpy(mymac.x, packet->data + 6, 6);
524 /* This routine generates replies to ARP requests.
525 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
526 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
529 arp = (struct ether_arp *)(packet->data + 14);
531 /* Check if this is a valid ARP request */
533 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP ||
534 arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) {
535 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
539 /* Check if the IPv4 address exists on the VPN */
541 subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
544 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
545 arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2],
550 /* Check if it is for our own subnet */
552 if(subnet->owner == myself)
553 return; /* silently ignore */
555 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
556 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
558 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
559 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
560 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
562 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
563 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
564 arp->arp_op = htons(ARPOP_REPLY);
566 write_packet(packet);
569 void route_outgoing(vpn_packet_t *packet)
576 /* FIXME: multicast? */
578 switch (routing_mode) {
580 type = ntohs(*((uint16_t *)(&packet->data[12])));
583 n = route_ipv4(packet);
587 #ifdef HAVE_NETINET_IP6_H
588 if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
589 route_neighborsol(packet);
593 n = route_ipv6(packet);
601 logger(DEBUG_TRAFFIC, LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
605 send_packet(n, packet);
609 n = route_mac(packet);
611 send_packet(n, packet);
613 broadcast_packet(myself, packet);
617 broadcast_packet(myself, packet);
622 void route_incoming(node_t *source, vpn_packet_t *packet)
624 switch (routing_mode) {
630 type = ntohs(*((uint16_t *)(&packet->data[12])));
633 n = route_ipv4(packet);
637 n = route_ipv6(packet);
648 memcpy(packet->data, mymac.x, 6);
649 write_packet(packet);
651 send_packet(n, packet);
660 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
663 if(subnet->owner == myself)
664 write_packet(packet);
666 send_packet(subnet->owner, packet);
668 broadcast_packet(source, packet);
669 write_packet(packet);
675 broadcast_packet(source, packet); /* Spread it on */
676 write_packet(packet);