Simplify logging, update copyrights and some minor cleanups.
[oweals/tinc.git] / src / route.c
1 /*
2     route.c -- routing
3     Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>,
4                   2000-2003 Guus Sliepen <guus@sliepen.eu.org>
5
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.
10
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.
15
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.
19
20     $Id: route.c,v 1.1.2.57 2003/07/12 17:41:47 guus Exp $
21 */
22
23 #include "config.h"
24
25 #ifdef HAVE_SYS_PARAM_H
26 #include <sys/param.h>
27 #endif
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #ifdef HAVE_NET_IF_H
31 #include <net/if.h>
32 #endif
33 #ifdef HAVE_NET_ETHERNET_H
34 #include <net/ethernet.h>
35 #endif
36 #ifdef HAVE_NETINET_IN_SYSTM_H
37 #include <netinet/in_systm.h>
38 #endif
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>
44 #endif
45 #include <netinet/if_ether.h>
46 #include <utils.h>
47 #include <xalloc.h>
48 #include <string.h>
49 #ifdef HAVE_INTTYPES_H
50 #include <inttypes.h>
51 #endif
52
53 #include <avl_tree.h>
54
55 #include "net.h"
56 #include "connection.h"
57 #include "subnet.h"
58 #include "route.h"
59 #include "protocol.h"
60 #include "device.h"
61 #include "logger.h"
62
63 #include "system.h"
64
65 /* Missing definitions */
66
67 #ifndef ETHER_ADDR_LEN
68 #define ETHER_ADDR_LEN 6
69 #endif
70
71 #ifndef ICMP_DEST_UNREACH
72 #define ICMP_DEST_UNREACH 3
73 #endif
74
75 #ifndef ICMP_NET_UNKNOWN
76 #define ICMP_NET_UNKNOWN 6
77 #endif
78
79 #ifndef ICMP_NET_UNREACH
80 #define ICMP_NET_UNREACH 0
81 #endif
82
83 int routing_mode = RMODE_ROUTER;
84 int priorityinheritance = 0;
85 int macexpire = 600;
86 int overwrite_mac = 0;
87 static mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
88
89 /* RFC 1071 */
90
91 static uint16_t inet_checksum(void *data, int len, uint16_t prevsum)
92 {
93         uint16_t *p = data;
94         uint32_t checksum = prevsum ^ 0xFFFF;
95
96         while(len >= 2) {
97                 checksum += *p++;
98                 len -= 2;
99         }
100         
101         if(len)
102                 checksum += *(unsigned char *)p;
103
104         while(checksum >> 16)
105                 checksum = (checksum & 0xFFFF) + (checksum >> 16);
106
107         return ~checksum;
108 }
109
110 static int ratelimit(void) {
111         static time_t lasttime = 0;
112         
113         if(lasttime == now)
114                 return 1;
115
116         lasttime = now;
117         return 0;
118 }
119         
120 static void learn_mac(mac_t *address)
121 {
122         subnet_t *subnet;
123         avl_node_t *node;
124         connection_t *c;
125
126         cp();
127
128         subnet = lookup_subnet_mac(address);
129
130         /* If we don't know this MAC address yet, store it */
131
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]);
136
137                 subnet = new_subnet();
138                 subnet->type = SUBNET_MAC;
139                 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
140                 subnet_add(myself, subnet);
141
142                 /* And tell all other tinc daemons it's our MAC */
143
144                 for(node = connection_tree->head; node; node = node->next) {
145                         c = (connection_t *) node->data;
146                         if(c->status.active)
147                                 send_add_subnet(c, subnet);
148                 }
149         }
150
151         subnet->net.mac.lastseen = now;
152 }
153
154 void age_mac(void)
155 {
156         subnet_t *s;
157         connection_t *c;
158         avl_node_t *node, *next, *node2;
159
160         cp();
161
162         for(node = myself->subnet_tree->head; node; node = next) {
163                 next = 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]);
170
171                         for(node2 = connection_tree->head; node2; node2 = node2->next) {
172                                 c = (connection_t *) node2->data;
173                                 if(c->status.active)
174                                         send_del_subnet(c, s);
175                         }
176
177                         subnet_del(myself, s);
178                 }
179         }
180 }
181
182 static node_t *route_mac(vpn_packet_t *packet)
183 {
184         subnet_t *subnet;
185
186         cp();
187
188         /* Learn source address */
189
190         learn_mac((mac_t *)(&packet->data[6]));
191
192         /* Lookup destination address */
193
194         subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
195
196         if(subnet)
197                 return subnet->owner;
198         else
199                 return NULL;
200 }
201
202 /* RFC 792 */
203
204 static void route_ipv4_unreachable(vpn_packet_t *packet, uint8_t code)
205 {
206         struct ip *hdr;
207         struct icmp *icmp;
208         
209         struct in_addr ip_src;
210         struct in_addr ip_dst;
211         uint32_t oldlen;
212
213         if(ratelimit())
214                 return;
215         
216         cp();
217
218         hdr = (struct ip *)(packet->data + 14);
219         icmp = (struct icmp *)(packet->data + 14 + 20);
220
221         /* Remember original source and destination */
222                 
223         memcpy(&ip_src, &hdr->ip_src, 4);
224         memcpy(&ip_dst, &hdr->ip_dst, 4);
225         oldlen = packet->len - 14;
226         
227         if(oldlen >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
228                 oldlen = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
229         
230         /* Copy first part of original contents to ICMP message */
231         
232         memmove(&icmp->icmp_ip, hdr, oldlen);
233
234         /* Fill in IPv4 header */
235         
236         hdr->ip_v = 4;
237         hdr->ip_hl = sizeof(*hdr) / 4;
238         hdr->ip_tos = 0;
239         hdr->ip_len = htons(20 + 8 + oldlen);
240         hdr->ip_id = 0;
241         hdr->ip_off = 0;
242         hdr->ip_ttl = 255;
243         hdr->ip_p = IPPROTO_ICMP;
244         hdr->ip_sum = 0;
245         memcpy(&hdr->ip_src, &ip_dst, 4);
246         memcpy(&hdr->ip_dst, &ip_src, 4);
247
248         hdr->ip_sum = inet_checksum(hdr, 20, ~0);
249         
250         /* Fill in ICMP header */
251         
252         icmp->icmp_type = ICMP_DEST_UNREACH;
253         icmp->icmp_code = code;
254         icmp->icmp_cksum = 0;
255         
256         icmp->icmp_cksum = inet_checksum(icmp, 8 + oldlen, ~0);
257         
258         packet->len = 14 + 20 + 8 + oldlen;
259         
260         write_packet(packet);
261 }
262
263 static node_t *route_ipv4(vpn_packet_t *packet)
264 {
265         subnet_t *subnet;
266
267         cp();
268
269         if(priorityinheritance)
270                 packet->priority = packet->data[15];
271
272         subnet = lookup_subnet_ipv4((ipv4_t *) & packet->data[30]);
273
274         if(!subnet) {
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],
277                                    packet->data[33]);
278
279                 route_ipv4_unreachable(packet, ICMP_NET_UNKNOWN);
280                 return NULL;
281         }
282         
283         if(!subnet->owner->status.reachable)
284                 route_ipv4_unreachable(packet, ICMP_NET_UNREACH);
285
286         return subnet->owner;
287 }
288
289 /* RFC 2463 */
290
291 static void route_ipv6_unreachable(vpn_packet_t *packet, uint8_t code)
292 {
293         struct ip6_hdr *hdr;
294         struct icmp6_hdr *icmp;
295         uint16_t checksum;      
296
297         struct {
298                 struct in6_addr ip6_src;        /* source address */
299                 struct in6_addr ip6_dst;        /* destination address */
300                 uint32_t length;
301                 uint32_t next;
302         } pseudo;
303
304         if(ratelimit())
305                 return;
306         
307         cp();
308
309         hdr = (struct ip6_hdr *)(packet->data + 14);
310         icmp = (struct icmp6_hdr *)(packet->data + 14 + sizeof(*hdr));
311
312         /* Remember original source and destination */
313                 
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);
317         
318         if(pseudo.length >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
319                 pseudo.length = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
320         
321         /* Copy first part of original contents to ICMP message */
322         
323         memmove(((char *)icmp) + sizeof(*icmp), hdr, pseudo.length);
324
325         /* Fill in IPv6 header */
326         
327         hdr->ip6_flow = htonl(0x60000000UL);
328         hdr->ip6_plen = htons(sizeof(*icmp) + pseudo.length);
329         hdr->ip6_nxt = IPPROTO_ICMPV6;
330         hdr->ip6_hlim = 255;
331         memcpy(&hdr->ip6_dst, &pseudo.ip6_dst, 16);
332         memcpy(&hdr->ip6_src, &pseudo.ip6_src, 16);
333
334         /* Fill in ICMP header */
335         
336         icmp->icmp6_type = ICMP6_DST_UNREACH;
337         icmp->icmp6_code = code;
338         icmp->icmp6_cksum = 0;
339
340         /* Create pseudo header */
341                 
342         pseudo.length = htonl(sizeof(*icmp) + pseudo.length);
343         pseudo.next = htonl(IPPROTO_ICMPV6);
344
345         /* Generate checksum */
346         
347         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
348         checksum = inet_checksum(icmp, ntohl(pseudo.length), checksum);
349
350         icmp->icmp6_cksum = checksum;
351         
352         packet->len = 14 + sizeof(*hdr) + ntohl(pseudo.length);
353         
354         write_packet(packet);
355 }
356
357 static node_t *route_ipv6(vpn_packet_t *packet)
358 {
359         subnet_t *subnet;
360
361         cp();
362
363         subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
364
365         if(!subnet) {
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);
376
377                 return NULL;
378         }
379
380         if(!subnet->owner->status.reachable)
381                 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_NOROUTE);
382         
383         return subnet->owner;
384 }
385
386 /* RFC 2461 */
387
388 static void route_neighborsol(vpn_packet_t *packet)
389 {
390         struct ip6_hdr *hdr;
391         struct nd_neighbor_solicit *ns;
392         struct nd_opt_hdr *opt;
393         subnet_t *subnet;
394         uint16_t checksum;
395
396         struct {
397                 struct in6_addr ip6_src;        /* source address */
398                 struct in6_addr ip6_dst;        /* destination address */
399                 uint32_t length;
400                 uint32_t next;
401         } pseudo;
402
403         cp();
404
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));
408
409         /* First, snatch the source address from the neighbor solicitation packet */
410
411         if(overwrite_mac)
412                 memcpy(mymac.x, packet->data + 6, 6);
413
414         /* Check if this is a valid neighbor solicitation request */
415
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"));
419                 return;
420         }
421
422         /* Create pseudo header */
423
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);
428
429         /* Generate checksum */
430
431         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
432         checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
433
434         if(checksum) {
435                 ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
436                 return;
437         }
438
439         /* Check if the IPv6 address exists on the VPN */
440
441         subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
442
443         if(!subnet) {
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]));
453
454                 return;
455         }
456
457         /* Check if it is for our own subnet */
458
459         if(subnet->owner == myself)
460                 return;                                 /* silently ignore */
461
462         /* Create neighbor advertation reply */
463
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 */
466
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);   /* ... */
469
470         memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6);  /* add fake source hard addr */
471
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;
479
480         /* Create pseudo header */
481
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);
486
487         /* Generate checksum */
488
489         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
490         checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
491
492         ns->nd_ns_hdr.icmp6_cksum = checksum;
493
494         write_packet(packet);
495 }
496
497 /* RFC 826 */
498
499 static void route_arp(vpn_packet_t *packet)
500 {
501         struct ether_arp *arp;
502         subnet_t *subnet;
503         uint8_t ipbuf[4];
504
505         cp();
506
507         /* First, snatch the source address from the ARP packet */
508
509         if(overwrite_mac)
510                 memcpy(mymac.x, packet->data + 6, 6);
511
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)
515          */
516
517         arp = (struct ether_arp *)(packet->data + 14);
518
519         /* Check if this is a valid ARP request */
520
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"));
524                 return;
525         }
526
527         /* Check if the IPv4 address exists on the VPN */
528
529         subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
530
531         if(!subnet) {
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],
534                                    arp->arp_tpa[3]);
535                 return;
536         }
537
538         /* Check if it is for our own subnet */
539
540         if(subnet->owner == myself)
541                 return;                                 /* silently ignore */
542
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 */
545
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); /* ... */
549
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);
553
554         write_packet(packet);
555 }
556
557 void route_outgoing(vpn_packet_t *packet)
558 {
559         uint16_t type;
560         node_t *n = NULL;
561
562         cp();
563
564         /* FIXME: multicast? */
565
566         switch (routing_mode) {
567                 case RMODE_ROUTER:
568                         type = ntohs(*((uint16_t *)(&packet->data[12])));
569                         switch (type) {
570                                 case 0x0800:
571                                         n = route_ipv4(packet);
572                                         break;
573
574                                 case 0x86DD:
575                                         if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) {
576                                                 route_neighborsol(packet);
577                                                 return;
578                                         }
579                                         n = route_ipv6(packet);
580                                         break;
581
582                                 case 0x0806:
583                                         route_arp(packet);
584                                         return;
585
586                                 default:
587                                         ifdebug(TRAFFIC) logger(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
588                                         return;
589                         }
590                         if(n)
591                                 send_packet(n, packet);
592                         break;
593
594                 case RMODE_SWITCH:
595                         n = route_mac(packet);
596                         if(n)
597                                 send_packet(n, packet);
598                         else
599                                 broadcast_packet(myself, packet);
600                         break;
601
602                 case RMODE_HUB:
603                         broadcast_packet(myself, packet);
604                         break;
605         }
606 }
607
608 void route_incoming(node_t *source, vpn_packet_t *packet)
609 {
610         switch (routing_mode) {
611                 case RMODE_ROUTER:
612                         {
613                                 node_t *n = NULL;
614                                 uint16_t type;
615
616                                 type = ntohs(*((uint16_t *)(&packet->data[12])));
617                                 switch (type) {
618                                         case 0x0800:
619                                                 n = route_ipv4(packet);
620                                                 break;
621
622                                         case 0x86DD:
623                                                 n = route_ipv6(packet);
624                                                 break;
625
626                                         default:
627                                                 n = myself;
628                                                 break;
629                                 }
630
631                                 if(n) {
632                                         if(n == myself) {
633                                                 if(overwrite_mac)
634                                                         memcpy(packet->data, mymac.x, 6);
635                                                 write_packet(packet);
636                                         } else
637                                                 send_packet(n, packet);
638                                 }
639                         }
640                         break;
641
642                 case RMODE_SWITCH:
643                         {
644                                 subnet_t *subnet;
645
646                                 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
647
648                                 if(subnet) {
649                                         if(subnet->owner == myself)
650                                                 write_packet(packet);
651                                         else
652                                                 send_packet(subnet->owner, packet);
653                                 } else {
654                                         broadcast_packet(source, packet);
655                                         write_packet(packet);
656                                 }
657                         }
658                         break;
659
660                 case RMODE_HUB:
661                         broadcast_packet(source, packet);       /* Spread it on */
662                         write_packet(packet);
663                         break;
664         }
665 }