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