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.52 2003/07/06 17:15:25 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 #include <netinet/ip6.h>
42 #include <netinet/icmp6.h>
43 #include <netinet/if_ether.h>
48 #ifdef HAVE_INTTYPES_H
55 #include "connection.h"
63 /* Missing definitions */
65 #ifndef ETHER_ADDR_LEN
66 #define ETHER_ADDR_LEN 6
69 #ifndef ICMP_DEST_UNREACH
70 #define ICMP_DEST_UNREACH 3
73 #ifndef ICMP_NET_UNKNOWN
74 #define ICMP_NET_UNKNOWN 6
77 #ifndef ICMP_NET_UNREACH
78 #define ICMP_NET_UNREACH 0
81 int routing_mode = RMODE_ROUTER;
82 int priorityinheritance = 0;
84 int overwrite_mac = 0;
85 mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
89 uint16_t inet_checksum(void *data, int len, uint16_t prevsum)
92 uint32_t checksum = prevsum ^ 0xFFFF;
100 checksum += *(unsigned char *)p;
102 while(checksum >> 16)
103 checksum = (checksum & 0xFFFF) + (checksum >> 16);
108 int ratelimit(void) {
109 static time_t lasttime = 0;
118 void learn_mac(mac_t *address)
126 subnet = lookup_subnet_mac(address);
128 /* If we don't know this MAC address yet, store it */
130 if(!subnet || subnet->owner != myself) {
131 if(debug_lvl >= DEBUG_TRAFFIC)
132 syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
133 address->x[0], address->x[1], address->x[2], address->x[3],
134 address->x[4], address->x[5]);
136 subnet = new_subnet();
137 subnet->type = SUBNET_MAC;
138 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
139 subnet_add(myself, subnet);
141 /* And tell all other tinc daemons it's our MAC */
143 for(node = connection_tree->head; node; node = node->next) {
144 c = (connection_t *) node->data;
146 send_add_subnet(c, subnet);
150 subnet->net.mac.lastseen = now;
157 avl_node_t *node, *next, *node2;
161 for(node = myself->subnet_tree->head; node; node = next) {
163 s = (subnet_t *) node->data;
164 if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) {
165 if(debug_lvl >= DEBUG_TRAFFIC)
166 syslog(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 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 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 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 if(debug_lvl >= DEBUG_TRAFFIC) {
276 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
277 packet->data[30], packet->data[31], packet->data[32],
281 route_ipv4_unreachable(packet, ICMP_NET_UNKNOWN);
285 if(!subnet->owner->status.reachable)
286 route_ipv4_unreachable(packet, ICMP_NET_UNREACH);
288 return subnet->owner;
293 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);
359 node_t *route_ipv6(vpn_packet_t *packet)
365 subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
368 if(debug_lvl >= DEBUG_TRAFFIC) {
369 syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
370 ntohs(*(uint16_t *) & packet->data[38]),
371 ntohs(*(uint16_t *) & packet->data[40]),
372 ntohs(*(uint16_t *) & packet->data[42]),
373 ntohs(*(uint16_t *) & packet->data[44]),
374 ntohs(*(uint16_t *) & packet->data[46]),
375 ntohs(*(uint16_t *) & packet->data[48]),
376 ntohs(*(uint16_t *) & packet->data[50]),
377 ntohs(*(uint16_t *) & packet->data[52]));
379 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_ADDR);
384 if(!subnet->owner->status.reachable)
385 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_NOROUTE);
387 return subnet->owner;
392 void route_neighborsol(vpn_packet_t *packet)
395 struct nd_neighbor_solicit *ns;
396 struct nd_opt_hdr *opt;
401 struct in6_addr ip6_src; /* source address */
402 struct in6_addr ip6_dst; /* destination address */
409 hdr = (struct ip6_hdr *)(packet->data + 14);
410 ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr));
411 opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
413 /* First, snatch the source address from the neighbor solicitation packet */
416 memcpy(mymac.x, packet->data + 6, 6);
418 /* Check if this is a valid neighbor solicitation request */
420 if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
421 opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
422 if(debug_lvl > DEBUG_TRAFFIC) {
423 syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
428 /* Create pseudo header */
430 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
431 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
432 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
433 pseudo.next = htonl(IPPROTO_ICMPV6);
435 /* Generate checksum */
437 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
438 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
441 if(debug_lvl >= DEBUG_TRAFFIC)
442 syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
446 /* Check if the IPv6 address exists on the VPN */
448 subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
451 if(debug_lvl >= DEBUG_TRAFFIC) {
452 syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
453 ntohs(((uint16_t *) & ns->nd_ns_target)[0]),
454 ntohs(((uint16_t *) & ns->nd_ns_target)[1]),
455 ntohs(((uint16_t *) & ns->nd_ns_target)[2]),
456 ntohs(((uint16_t *) & ns->nd_ns_target)[3]),
457 ntohs(((uint16_t *) & ns->nd_ns_target)[4]),
458 ntohs(((uint16_t *) & ns->nd_ns_target)[5]),
459 ntohs(((uint16_t *) & ns->nd_ns_target)[6]),
460 ntohs(((uint16_t *) & ns->nd_ns_target)[7]));
466 /* Check if it is for our own subnet */
468 if(subnet->owner == myself)
469 return; /* silently ignore */
471 /* Create neighbor advertation reply */
473 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
474 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
476 memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */
477 memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */
479 memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */
481 ns->nd_ns_hdr.icmp6_cksum = 0;
482 ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
483 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */
484 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] =
485 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] =
486 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
487 opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
489 /* Create pseudo header */
491 memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
492 memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
493 pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
494 pseudo.next = htonl(IPPROTO_ICMPV6);
496 /* Generate checksum */
498 checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
499 checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
501 ns->nd_ns_hdr.icmp6_cksum = checksum;
503 write_packet(packet);
508 void route_arp(vpn_packet_t *packet)
510 struct ether_arp *arp;
516 /* First, snatch the source address from the ARP packet */
519 memcpy(mymac.x, packet->data + 6, 6);
521 /* This routine generates replies to ARP requests.
522 You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
523 Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
526 arp = (struct ether_arp *)(packet->data + 14);
528 /* Check if this is a valid ARP request */
530 if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP ||
531 arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) {
532 if(debug_lvl > DEBUG_TRAFFIC) {
533 syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
538 /* Check if the IPv4 address exists on the VPN */
540 subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
543 if(debug_lvl >= DEBUG_TRAFFIC) {
544 syslog(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],
552 /* Check if it is for our own subnet */
554 if(subnet->owner == myself)
555 return; /* silently ignore */
557 memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */
558 packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */
560 memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */
561 memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */
562 memcpy(arp->arp_spa, ipbuf, 4); /* ... */
564 memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */
565 memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */
566 arp->arp_op = htons(ARPOP_REPLY);
568 write_packet(packet);
571 void route_outgoing(vpn_packet_t *packet)
578 /* FIXME: multicast? */
580 switch (routing_mode) {
582 type = ntohs(*((uint16_t *)(&packet->data[12])));
585 n = route_ipv4(packet);
589 if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
590 route_neighborsol(packet);
593 n = route_ipv6(packet);
601 if(debug_lvl >= DEBUG_TRAFFIC)
602 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
606 send_packet(n, packet);
610 n = route_mac(packet);
612 send_packet(n, packet);
614 broadcast_packet(myself, packet);
618 broadcast_packet(myself, packet);
623 void route_incoming(node_t *source, vpn_packet_t *packet)
625 switch (routing_mode) {
631 type = ntohs(*((uint16_t *)(&packet->data[12])));
634 n = route_ipv4(packet);
638 n = route_ipv6(packet);
649 memcpy(packet->data, mymac.x, 6);
650 write_packet(packet);
652 send_packet(n, packet);
661 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
664 if(subnet->owner == myself)
665 write_packet(packet);
667 send_packet(subnet->owner, packet);
669 broadcast_packet(source, packet);
670 write_packet(packet);
676 broadcast_packet(source, packet); /* Spread it on */
677 write_packet(packet);