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