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