More braces to make gcc happy.
[oweals/tinc.git] / src / route.c
1 /*
2     route.c -- routing
3     Copyright (C) 2000-2002 Ivo Timmermans <ivo@o2w.nl>,
4                   2000-2002 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.51 2003/06/11 19:40:43 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 #include <netinet/ip6.h>
42 #include <netinet/icmp6.h>
43 #include <netinet/if_ether.h>
44 #include <utils.h>
45 #include <xalloc.h>
46 #include <syslog.h>
47 #include <string.h>
48 #ifdef HAVE_INTTYPES_H
49 #include <inttypes.h>
50 #endif
51
52 #include <avl_tree.h>
53
54 #include "net.h"
55 #include "connection.h"
56 #include "subnet.h"
57 #include "route.h"
58 #include "protocol.h"
59 #include "device.h"
60
61 #include "system.h"
62
63 #ifndef ETHER_ADDR_LEN
64 #define ETHER_ADDR_LEN 6
65 #endif
66
67 int routing_mode = RMODE_ROUTER;
68 int priorityinheritance = 0;
69 int macexpire = 600;
70 int overwrite_mac = 0;
71 mac_t mymac = {{0xFE, 0xFD, 0, 0, 0, 0}};
72
73 /* RFC 1071 */
74
75 uint16_t inet_checksum(void *data, int len, uint16_t prevsum)
76 {
77         uint16_t *p = data;
78         uint32_t checksum = prevsum ^ 0xFFFF;
79
80         while(len >= 2) {
81                 checksum += *p++;
82                 len -= 2;
83         }
84         
85         if(len)
86                 checksum += *(unsigned char *)p;
87
88         while(checksum >> 16)
89                 checksum = (checksum & 0xFFFF) + (checksum >> 16);
90
91         return ~checksum;
92 }
93
94 int ratelimit(void) {
95         static time_t lasttime = 0;
96         
97         if(lasttime == now)
98                 return 1;
99
100         lasttime = now;
101         return 0;
102 }
103         
104 void learn_mac(mac_t *address)
105 {
106         subnet_t *subnet;
107         avl_node_t *node;
108         connection_t *c;
109
110         cp();
111
112         subnet = lookup_subnet_mac(address);
113
114         /* If we don't know this MAC address yet, store it */
115
116         if(!subnet || subnet->owner != myself) {
117                 if(debug_lvl >= DEBUG_TRAFFIC)
118                         syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"),
119                                    address->x[0], address->x[1], address->x[2], address->x[3],
120                                    address->x[4], address->x[5]);
121
122                 subnet = new_subnet();
123                 subnet->type = SUBNET_MAC;
124                 memcpy(&subnet->net.mac.address, address, sizeof(mac_t));
125                 subnet_add(myself, subnet);
126
127                 /* And tell all other tinc daemons it's our MAC */
128
129                 for(node = connection_tree->head; node; node = node->next) {
130                         c = (connection_t *) node->data;
131                         if(c->status.active)
132                                 send_add_subnet(c, subnet);
133                 }
134         }
135
136         subnet->net.mac.lastseen = now;
137 }
138
139 void age_mac(void)
140 {
141         subnet_t *s;
142         connection_t *c;
143         avl_node_t *node, *next, *node2;
144
145         cp();
146
147         for(node = myself->subnet_tree->head; node; node = next) {
148                 next = node->next;
149                 s = (subnet_t *) node->data;
150                 if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) {
151                         if(debug_lvl >= DEBUG_TRAFFIC)
152                                 syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"),
153                                            s->net.mac.address.x[0], s->net.mac.address.x[1],
154                                            s->net.mac.address.x[2], s->net.mac.address.x[3],
155                                            s->net.mac.address.x[4], s->net.mac.address.x[5]);
156
157                         for(node2 = connection_tree->head; node2; node2 = node2->next) {
158                                 c = (connection_t *) node2->data;
159                                 if(c->status.active)
160                                         send_del_subnet(c, s);
161                         }
162
163                         subnet_del(myself, s);
164                 }
165         }
166 }
167
168 node_t *route_mac(vpn_packet_t *packet)
169 {
170         subnet_t *subnet;
171
172         cp();
173
174         /* Learn source address */
175
176         learn_mac((mac_t *)(&packet->data[6]));
177
178         /* Lookup destination address */
179
180         subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
181
182         if(subnet)
183                 return subnet->owner;
184         else
185                 return NULL;
186 }
187
188 /* RFC 792 */
189
190 void route_ipv4_unreachable(vpn_packet_t *packet, uint8_t code)
191 {
192         struct ip *hdr;
193         struct icmp *icmp;
194         
195         struct in_addr ip_src;
196         struct in_addr ip_dst;
197         uint32_t oldlen;
198
199         if(ratelimit())
200                 return;
201         
202         cp();
203
204         hdr = (struct ip *)(packet->data + 14);
205         icmp = (struct icmp *)(packet->data + 14 + 20);
206
207         /* Remember original source and destination */
208                 
209         memcpy(&ip_src, &hdr->ip_src, 4);
210         memcpy(&ip_dst, &hdr->ip_dst, 4);
211         oldlen = packet->len - 14;
212         
213         if(oldlen >= IP_MSS - sizeof(*hdr) - sizeof(struct icmphdr))
214                 oldlen = IP_MSS - sizeof(*hdr) - sizeof(struct icmphdr);
215         
216         /* Copy first part of original contents to ICMP message */
217         
218         memmove(&icmp->icmp_ip, hdr, oldlen);
219
220         /* Fill in IPv4 header */
221         
222         hdr->ip_v = 4;
223         hdr->ip_hl = sizeof(*hdr) / 4;
224         hdr->ip_tos = 0;
225         hdr->ip_len = htons(20 + 8 + oldlen);
226         hdr->ip_id = 0;
227         hdr->ip_off = 0;
228         hdr->ip_ttl = 255;
229         hdr->ip_p = IPPROTO_ICMP;
230         hdr->ip_sum = 0;
231         memcpy(&hdr->ip_src, &ip_dst, 4);
232         memcpy(&hdr->ip_dst, &ip_src, 4);
233
234         hdr->ip_sum = inet_checksum(hdr, 20, ~0);
235         
236         /* Fill in ICMP header */
237         
238         icmp->icmp_type = ICMP_DEST_UNREACH;
239         icmp->icmp_code = code;
240         icmp->icmp_cksum = 0;
241         
242         icmp->icmp_cksum = inet_checksum(icmp, 8 + oldlen, ~0);
243         
244         packet->len = 14 + 20 + 8 + oldlen;
245         
246         write_packet(packet);
247 }
248
249 node_t *route_ipv4(vpn_packet_t *packet)
250 {
251         subnet_t *subnet;
252
253         cp();
254
255         if(priorityinheritance)
256                 packet->priority = packet->data[15];
257
258         subnet = lookup_subnet_ipv4((ipv4_t *) & packet->data[30]);
259
260         if(!subnet) {
261                 if(debug_lvl >= DEBUG_TRAFFIC) {
262                         syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"),
263                                    packet->data[30], packet->data[31], packet->data[32],
264                                    packet->data[33]);
265                 }
266
267                 route_ipv4_unreachable(packet, ICMP_NET_UNKNOWN);
268                 return NULL;
269         }
270         
271         if(!subnet->owner->status.reachable)
272                 route_ipv4_unreachable(packet, ICMP_NET_UNREACH);
273
274         return subnet->owner;
275 }
276
277 /* RFC 2463 */
278
279 void route_ipv6_unreachable(vpn_packet_t *packet, uint8_t code)
280 {
281         struct ip6_hdr *hdr;
282         struct icmp6_hdr *icmp;
283         uint16_t checksum;      
284
285         struct {
286                 struct in6_addr ip6_src;        /* source address */
287                 struct in6_addr ip6_dst;        /* destination address */
288                 uint32_t length;
289                 uint32_t next;
290         } pseudo;
291
292         if(ratelimit())
293                 return;
294         
295         cp();
296
297         hdr = (struct ip6_hdr *)(packet->data + 14);
298         icmp = (struct icmp6_hdr *)(packet->data + 14 + sizeof(*hdr));
299
300         /* Remember original source and destination */
301                 
302         memcpy(&pseudo.ip6_src, &hdr->ip6_dst, 16);
303         memcpy(&pseudo.ip6_dst, &hdr->ip6_src, 16);
304         pseudo.length = ntohs(hdr->ip6_plen) + sizeof(*hdr);
305         
306         if(pseudo.length >= IP_MSS - sizeof(*hdr) - sizeof(*icmp))
307                 pseudo.length = IP_MSS - sizeof(*hdr) - sizeof(*icmp);
308         
309         /* Copy first part of original contents to ICMP message */
310         
311         memmove(((char *)icmp) + sizeof(*icmp), hdr, pseudo.length);
312
313         /* Fill in IPv6 header */
314         
315         hdr->ip6_flow = htonl(0x60000000UL);
316         hdr->ip6_plen = htons(sizeof(*icmp) + pseudo.length);
317         hdr->ip6_nxt = IPPROTO_ICMPV6;
318         hdr->ip6_hlim = 255;
319         memcpy(&hdr->ip6_dst, &pseudo.ip6_dst, 16);
320         memcpy(&hdr->ip6_src, &pseudo.ip6_src, 16);
321
322         /* Fill in ICMP header */
323         
324         icmp->icmp6_type = ICMP6_DST_UNREACH;
325         icmp->icmp6_code = code;
326         icmp->icmp6_cksum = 0;
327
328         /* Create pseudo header */
329                 
330         pseudo.length = htonl(sizeof(*icmp) + pseudo.length);
331         pseudo.next = htonl(IPPROTO_ICMPV6);
332
333         /* Generate checksum */
334         
335         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
336         checksum = inet_checksum(icmp, ntohl(pseudo.length), checksum);
337
338         icmp->icmp6_cksum = checksum;
339         
340         packet->len = 14 + sizeof(*hdr) + ntohl(pseudo.length);
341         
342         write_packet(packet);
343 }
344
345 node_t *route_ipv6(vpn_packet_t *packet)
346 {
347         subnet_t *subnet;
348
349         cp();
350
351         subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]);
352
353         if(!subnet) {
354                 if(debug_lvl >= DEBUG_TRAFFIC) {
355                         syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
356                                    ntohs(*(uint16_t *) & packet->data[38]),
357                                    ntohs(*(uint16_t *) & packet->data[40]),
358                                    ntohs(*(uint16_t *) & packet->data[42]),
359                                    ntohs(*(uint16_t *) & packet->data[44]),
360                                    ntohs(*(uint16_t *) & packet->data[46]),
361                                    ntohs(*(uint16_t *) & packet->data[48]),
362                                    ntohs(*(uint16_t *) & packet->data[50]),
363                                    ntohs(*(uint16_t *) & packet->data[52]));
364                 }
365                 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_ADDR);
366
367                 return NULL;
368         }
369
370         if(!subnet->owner->status.reachable)
371                 route_ipv6_unreachable(packet, ICMP6_DST_UNREACH_NOROUTE);
372
373         return subnet->owner;
374 }
375
376 /* RFC 2461 */
377
378 void route_neighborsol(vpn_packet_t *packet)
379 {
380         struct ip6_hdr *hdr;
381         struct nd_neighbor_solicit *ns;
382         struct nd_opt_hdr *opt;
383         subnet_t *subnet;
384         uint16_t checksum;
385
386         struct {
387                 struct in6_addr ip6_src;        /* source address */
388                 struct in6_addr ip6_dst;        /* destination address */
389                 uint32_t length;
390                 uint32_t next;
391         } pseudo;
392
393         cp();
394
395         hdr = (struct ip6_hdr *)(packet->data + 14);
396         ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr));
397         opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns));
398
399         /* First, snatch the source address from the neighbor solicitation packet */
400
401         if(overwrite_mac)
402                 memcpy(mymac.x, packet->data + 6, 6);
403
404         /* Check if this is a valid neighbor solicitation request */
405
406         if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT ||
407            opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
408                 if(debug_lvl > DEBUG_TRAFFIC) {
409                         syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request"));
410                 }
411                 return;
412         }
413
414         /* Create pseudo header */
415
416         memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
417         memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
418         pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
419         pseudo.next = htonl(IPPROTO_ICMPV6);
420
421         /* Generate checksum */
422
423         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
424         checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
425
426         if(checksum) {
427                 if(debug_lvl >= DEBUG_TRAFFIC)
428                         syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request"));
429                 return;
430         }
431
432         /* Check if the IPv6 address exists on the VPN */
433
434         subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target);
435
436         if(!subnet) {
437                 if(debug_lvl >= DEBUG_TRAFFIC) {
438                         syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"),
439                                    ntohs(((uint16_t *) & ns->nd_ns_target)[0]),
440                                    ntohs(((uint16_t *) & ns->nd_ns_target)[1]),
441                                    ntohs(((uint16_t *) & ns->nd_ns_target)[2]),
442                                    ntohs(((uint16_t *) & ns->nd_ns_target)[3]),
443                                    ntohs(((uint16_t *) & ns->nd_ns_target)[4]),
444                                    ntohs(((uint16_t *) & ns->nd_ns_target)[5]),
445                                    ntohs(((uint16_t *) & ns->nd_ns_target)[6]),
446                                    ntohs(((uint16_t *) & ns->nd_ns_target)[7]));
447                 }
448
449                 return;
450         }
451
452         /* Check if it is for our own subnet */
453
454         if(subnet->owner == myself)
455                 return;                                 /* silently ignore */
456
457         /* Create neighbor advertation reply */
458
459         memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN);    /* copy destination address */
460         packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF;   /* mangle source address so it looks like it's not from us */
461
462         memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16);       /* swap destination and source protocol address */
463         memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16);   /* ... */
464
465         memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6);  /* add fake source hard addr */
466
467         ns->nd_ns_hdr.icmp6_cksum = 0;
468         ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;
469         ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40;    /* Set solicited flag */
470         ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] =
471                 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] =
472                 ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0;
473         opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
474
475         /* Create pseudo header */
476
477         memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16);
478         memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16);
479         pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6);
480         pseudo.next = htonl(IPPROTO_ICMPV6);
481
482         /* Generate checksum */
483
484         checksum = inet_checksum(&pseudo, sizeof(pseudo), ~0);
485         checksum = inet_checksum(ns, sizeof(*ns) + 8, checksum);
486
487         ns->nd_ns_hdr.icmp6_cksum = checksum;
488
489         write_packet(packet);
490 }
491
492 /* RFC 826 */
493
494 void route_arp(vpn_packet_t *packet)
495 {
496         struct ether_arp *arp;
497         subnet_t *subnet;
498         uint8_t ipbuf[4];
499
500         cp();
501
502         /* First, snatch the source address from the ARP packet */
503
504         if(overwrite_mac)
505                 memcpy(mymac.x, packet->data + 6, 6);
506
507         /* This routine generates replies to ARP requests.
508            You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD).
509            Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp)
510          */
511
512         arp = (struct ether_arp *)(packet->data + 14);
513
514         /* Check if this is a valid ARP request */
515
516         if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP ||
517            arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) {
518                 if(debug_lvl > DEBUG_TRAFFIC) {
519                         syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request"));
520                 }
521                 return;
522         }
523
524         /* Check if the IPv4 address exists on the VPN */
525
526         subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa);
527
528         if(!subnet) {
529                 if(debug_lvl >= DEBUG_TRAFFIC) {
530                         syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"),
531                                    arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2],
532                                    arp->arp_tpa[3]);
533                 }
534
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                                         if(debug_lvl >= DEBUG_TRAFFIC)
588                                                 syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type);
589                                         return;
590                         }
591                         if(n)
592                                 send_packet(n, packet);
593                         break;
594
595                 case RMODE_SWITCH:
596                         n = route_mac(packet);
597                         if(n)
598                                 send_packet(n, packet);
599                         else
600                                 broadcast_packet(myself, packet);
601                         break;
602
603                 case RMODE_HUB:
604                         broadcast_packet(myself, packet);
605                         break;
606         }
607 }
608
609 void route_incoming(node_t *source, vpn_packet_t *packet)
610 {
611         switch (routing_mode) {
612                 case RMODE_ROUTER:
613                         {
614                                 node_t *n = NULL;
615                                 uint16_t type;
616
617                                 type = ntohs(*((uint16_t *)(&packet->data[12])));
618                                 switch (type) {
619                                         case 0x0800:
620                                                 n = route_ipv4(packet);
621                                                 break;
622
623                                         case 0x86DD:
624                                                 n = route_ipv6(packet);
625                                                 break;
626
627                                         default:
628                                                 n = myself;
629                                                 break;
630                                 }
631
632                                 if(n) {
633                                         if(n == myself) {
634                                                 if(overwrite_mac)
635                                                         memcpy(packet->data, mymac.x, 6);
636                                                 write_packet(packet);
637                                         } else
638                                                 send_packet(n, packet);
639                                 }
640                         }
641                         break;
642
643                 case RMODE_SWITCH:
644                         {
645                                 subnet_t *subnet;
646
647                                 subnet = lookup_subnet_mac((mac_t *)(&packet->data[0]));
648
649                                 if(subnet) {
650                                         if(subnet->owner == myself)
651                                                 write_packet(packet);
652                                         else
653                                                 send_packet(subnet->owner, packet);
654                                 } else {
655                                         broadcast_packet(source, packet);
656                                         write_packet(packet);
657                                 }
658                         }
659                         break;
660
661                 case RMODE_HUB:
662                         broadcast_packet(source, packet);       /* Spread it on */
663                         write_packet(packet);
664                         break;
665         }
666 }