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