if_bridge.c revision 1.14 1 /* $NetBSD: if_bridge.c,v 1.14 2003/05/24 14:22:14 kristerw Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*
39 * Copyright (c) 1999, 2000 Jason L. Wright (jason (at) thought.net)
40 * All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement:
52 * This product includes software developed by Jason L. Wright
53 * 4. The name of the author may not be used to endorse or promote products
54 * derived from this software without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
60 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
61 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
64 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
65 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 * POSSIBILITY OF SUCH DAMAGE.
67 *
68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
69 */
70
71 /*
72 * Network interface bridge support.
73 *
74 * TODO:
75 *
76 * - Currently only supports Ethernet-like interfaces (Ethernet,
77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
78 * to bridge other types of interfaces (FDDI-FDDI, and maybe
79 * consider heterogenous bridges).
80 *
81 * - Add packet filter hooks.
82 */
83
84 #include <sys/cdefs.h>
85 __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.14 2003/05/24 14:22:14 kristerw Exp $");
86
87 #include "opt_bridge_ipf.h"
88 #include "bpfilter.h"
89
90 #include <sys/param.h>
91 #include <sys/kernel.h>
92 #include <sys/mbuf.h>
93 #include <sys/queue.h>
94 #include <sys/socket.h>
95 #include <sys/sockio.h>
96 #include <sys/systm.h>
97 #include <sys/proc.h>
98 #include <sys/pool.h>
99
100 #if NBPFILTER > 0
101 #include <net/bpf.h>
102 #endif
103 #include <net/if.h>
104 #include <net/if_dl.h>
105 #include <net/if_types.h>
106 #include <net/if_llc.h>
107
108 #include <net/if_ether.h>
109 #include <net/if_bridgevar.h>
110
111 #ifdef BRIDGE_IPF /* Used for bridge_ip[6]_checkbasic */
112 #include <netinet/in.h>
113 #include <netinet/in_systm.h>
114 #include <netinet/ip.h>
115 #include <netinet/ip_var.h>
116
117 #include <netinet/ip6.h>
118 #include <netinet6/in6_var.h>
119 #include <netinet6/ip6_var.h>
120 #endif /* BRIDGE_IPF */
121
122 /*
123 * Size of the route hash table. Must be a power of two.
124 */
125 #ifndef BRIDGE_RTHASH_SIZE
126 #define BRIDGE_RTHASH_SIZE 1024
127 #endif
128
129 #define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
130
131 /*
132 * Maximum number of addresses to cache.
133 */
134 #ifndef BRIDGE_RTABLE_MAX
135 #define BRIDGE_RTABLE_MAX 100
136 #endif
137
138 /*
139 * Spanning tree defaults.
140 */
141 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
142 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
143 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
144 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
145 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
146 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
147 #define BSTP_DEFAULT_PATH_COST 55
148
149 /*
150 * Timeout (in seconds) for entries learned dynamically.
151 */
152 #ifndef BRIDGE_RTABLE_TIMEOUT
153 #define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
154 #endif
155
156 /*
157 * Number of seconds between walks of the route list.
158 */
159 #ifndef BRIDGE_RTABLE_PRUNE_PERIOD
160 #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
161 #endif
162
163 int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
164
165 struct pool bridge_rtnode_pool;
166
167 void bridgeattach(int);
168
169 int bridge_clone_create(struct if_clone *, int);
170 void bridge_clone_destroy(struct ifnet *);
171
172 int bridge_ioctl(struct ifnet *, u_long, caddr_t);
173 int bridge_init(struct ifnet *);
174 void bridge_stop(struct ifnet *, int);
175 void bridge_start(struct ifnet *);
176
177 void bridge_forward(struct bridge_softc *, struct mbuf *m);
178
179 void bridge_timer(void *);
180
181 void bridge_broadcast(struct bridge_softc *, struct ifnet *, struct mbuf *);
182
183 int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
184 struct ifnet *, int, uint8_t);
185 struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *);
186 void bridge_rttrim(struct bridge_softc *);
187 void bridge_rtage(struct bridge_softc *);
188 void bridge_rtflush(struct bridge_softc *, int);
189 int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
190 void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp);
191
192 int bridge_rtable_init(struct bridge_softc *);
193 void bridge_rtable_fini(struct bridge_softc *);
194
195 struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
196 const uint8_t *);
197 int bridge_rtnode_insert(struct bridge_softc *, struct bridge_rtnode *);
198 void bridge_rtnode_destroy(struct bridge_softc *, struct bridge_rtnode *);
199
200 struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
201 const char *name);
202 struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
203 struct ifnet *ifp);
204 void bridge_delete_member(struct bridge_softc *, struct bridge_iflist *);
205
206 int bridge_ioctl_add(struct bridge_softc *, void *);
207 int bridge_ioctl_del(struct bridge_softc *, void *);
208 int bridge_ioctl_gifflags(struct bridge_softc *, void *);
209 int bridge_ioctl_sifflags(struct bridge_softc *, void *);
210 int bridge_ioctl_scache(struct bridge_softc *, void *);
211 int bridge_ioctl_gcache(struct bridge_softc *, void *);
212 int bridge_ioctl_gifs(struct bridge_softc *, void *);
213 int bridge_ioctl_rts(struct bridge_softc *, void *);
214 int bridge_ioctl_saddr(struct bridge_softc *, void *);
215 int bridge_ioctl_sto(struct bridge_softc *, void *);
216 int bridge_ioctl_gto(struct bridge_softc *, void *);
217 int bridge_ioctl_daddr(struct bridge_softc *, void *);
218 int bridge_ioctl_flush(struct bridge_softc *, void *);
219 int bridge_ioctl_gpri(struct bridge_softc *, void *);
220 int bridge_ioctl_spri(struct bridge_softc *, void *);
221 int bridge_ioctl_ght(struct bridge_softc *, void *);
222 int bridge_ioctl_sht(struct bridge_softc *, void *);
223 int bridge_ioctl_gfd(struct bridge_softc *, void *);
224 int bridge_ioctl_sfd(struct bridge_softc *, void *);
225 int bridge_ioctl_gma(struct bridge_softc *, void *);
226 int bridge_ioctl_sma(struct bridge_softc *, void *);
227 int bridge_ioctl_sifprio(struct bridge_softc *, void *);
228 int bridge_ioctl_sifcost(struct bridge_softc *, void *);
229 #ifdef BRIDGE_IPF
230 int bridge_ioctl_gfilt(struct bridge_softc *, void *);
231 int bridge_ioctl_sfilt(struct bridge_softc *, void *);
232 static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int);
233 static int bridge_ip_checkbasic(struct mbuf **mp);
234 # ifdef INET6
235 static int bridge_ip6_checkbasic(struct mbuf **mp);
236 # endif /* INET6 */
237 #endif /* BRIDGE_IPF */
238
239 struct bridge_control {
240 int (*bc_func)(struct bridge_softc *, void *);
241 int bc_argsize;
242 int bc_flags;
243 };
244
245 #define BC_F_COPYIN 0x01 /* copy arguments in */
246 #define BC_F_COPYOUT 0x02 /* copy arguments out */
247 #define BC_F_SUSER 0x04 /* do super-user check */
248
249 const struct bridge_control bridge_control_table[] = {
250 { bridge_ioctl_add, sizeof(struct ifbreq),
251 BC_F_COPYIN|BC_F_SUSER },
252 { bridge_ioctl_del, sizeof(struct ifbreq),
253 BC_F_COPYIN|BC_F_SUSER },
254
255 { bridge_ioctl_gifflags, sizeof(struct ifbreq),
256 BC_F_COPYIN|BC_F_COPYOUT },
257 { bridge_ioctl_sifflags, sizeof(struct ifbreq),
258 BC_F_COPYIN|BC_F_SUSER },
259
260 { bridge_ioctl_scache, sizeof(struct ifbrparam),
261 BC_F_COPYIN|BC_F_SUSER },
262 { bridge_ioctl_gcache, sizeof(struct ifbrparam),
263 BC_F_COPYOUT },
264
265 { bridge_ioctl_gifs, sizeof(struct ifbifconf),
266 BC_F_COPYIN|BC_F_COPYOUT },
267 { bridge_ioctl_rts, sizeof(struct ifbaconf),
268 BC_F_COPYIN|BC_F_COPYOUT },
269
270 { bridge_ioctl_saddr, sizeof(struct ifbareq),
271 BC_F_COPYIN|BC_F_SUSER },
272
273 { bridge_ioctl_sto, sizeof(struct ifbrparam),
274 BC_F_COPYIN|BC_F_SUSER },
275 { bridge_ioctl_gto, sizeof(struct ifbrparam),
276 BC_F_COPYOUT },
277
278 { bridge_ioctl_daddr, sizeof(struct ifbareq),
279 BC_F_COPYIN|BC_F_SUSER },
280
281 { bridge_ioctl_flush, sizeof(struct ifbreq),
282 BC_F_COPYIN|BC_F_SUSER },
283
284 { bridge_ioctl_gpri, sizeof(struct ifbrparam),
285 BC_F_COPYOUT },
286 { bridge_ioctl_spri, sizeof(struct ifbrparam),
287 BC_F_COPYIN|BC_F_SUSER },
288
289 { bridge_ioctl_ght, sizeof(struct ifbrparam),
290 BC_F_COPYOUT },
291 { bridge_ioctl_sht, sizeof(struct ifbrparam),
292 BC_F_COPYIN|BC_F_SUSER },
293
294 { bridge_ioctl_gfd, sizeof(struct ifbrparam),
295 BC_F_COPYOUT },
296 { bridge_ioctl_sfd, sizeof(struct ifbrparam),
297 BC_F_COPYIN|BC_F_SUSER },
298
299 { bridge_ioctl_gma, sizeof(struct ifbrparam),
300 BC_F_COPYOUT },
301 { bridge_ioctl_sma, sizeof(struct ifbrparam),
302 BC_F_COPYIN|BC_F_SUSER },
303
304 { bridge_ioctl_sifprio, sizeof(struct ifbreq),
305 BC_F_COPYIN|BC_F_SUSER },
306
307 { bridge_ioctl_sifcost, sizeof(struct ifbreq),
308 BC_F_COPYIN|BC_F_SUSER },
309 #ifdef BRIDGE_IPF
310 { bridge_ioctl_gfilt, sizeof(struct ifbrparam),
311 BC_F_COPYOUT },
312 { bridge_ioctl_sfilt, sizeof(struct ifbrparam),
313 BC_F_COPYIN|BC_F_SUSER },
314 #endif /* BRIDGE_IPF */
315 };
316 const int bridge_control_table_size =
317 sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
318
319 LIST_HEAD(, bridge_softc) bridge_list;
320
321 struct if_clone bridge_cloner =
322 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
323
324 /*
325 * bridgeattach:
326 *
327 * Pseudo-device attach routine.
328 */
329 void
330 bridgeattach(int n)
331 {
332
333 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode),
334 0, 0, 0, "brtpl", NULL);
335
336 LIST_INIT(&bridge_list);
337 if_clone_attach(&bridge_cloner);
338 }
339
340 /*
341 * bridge_clone_create:
342 *
343 * Create a new bridge instance.
344 */
345 int
346 bridge_clone_create(struct if_clone *ifc, int unit)
347 {
348 struct bridge_softc *sc;
349 struct ifnet *ifp;
350 int s;
351
352 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
353 memset(sc, 0, sizeof(*sc));
354 ifp = &sc->sc_if;
355
356 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
357 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
358 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
359 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
360 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
361 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
362 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
363 sc->sc_filter_flags = 0;
364
365 /* Initialize our routing table. */
366 bridge_rtable_init(sc);
367
368 callout_init(&sc->sc_brcallout);
369 callout_init(&sc->sc_bstpcallout);
370
371 LIST_INIT(&sc->sc_iflist);
372
373 sprintf(ifp->if_xname, "%s%d", ifc->ifc_name, unit);
374 ifp->if_softc = sc;
375 ifp->if_mtu = ETHERMTU;
376 ifp->if_ioctl = bridge_ioctl;
377 ifp->if_output = bridge_output;
378 ifp->if_start = bridge_start;
379 ifp->if_stop = bridge_stop;
380 ifp->if_init = bridge_init;
381 ifp->if_type = IFT_BRIDGE;
382 ifp->if_addrlen = 0;
383 ifp->if_dlt = DLT_EN10MB;
384 ifp->if_hdrlen = ETHER_HDR_LEN;
385
386 if_attach(ifp);
387
388 if_alloc_sadl(ifp);
389
390 s = splnet();
391 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
392 splx(s);
393
394 return (0);
395 }
396
397 /*
398 * bridge_clone_destroy:
399 *
400 * Destroy a bridge instance.
401 */
402 void
403 bridge_clone_destroy(struct ifnet *ifp)
404 {
405 struct bridge_softc *sc = ifp->if_softc;
406 struct bridge_iflist *bif;
407 int s;
408
409 s = splnet();
410
411 bridge_stop(ifp, 1);
412
413 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL)
414 bridge_delete_member(sc, bif);
415
416 LIST_REMOVE(sc, sc_list);
417
418 splx(s);
419
420 if_detach(ifp);
421
422 /* Tear down the routing table. */
423 bridge_rtable_fini(sc);
424
425 free(sc, M_DEVBUF);
426 }
427
428 /*
429 * bridge_ioctl:
430 *
431 * Handle a control request from the operator.
432 */
433 int
434 bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
435 {
436 struct bridge_softc *sc = ifp->if_softc;
437 struct proc *p = curproc; /* XXX */
438 union {
439 struct ifbreq ifbreq;
440 struct ifbifconf ifbifconf;
441 struct ifbareq ifbareq;
442 struct ifbaconf ifbaconf;
443 struct ifbrparam ifbrparam;
444 } args;
445 struct ifdrv *ifd = (struct ifdrv *) data;
446 const struct bridge_control *bc;
447 int s, error = 0;
448
449 s = splnet();
450
451 switch (cmd) {
452 case SIOCGDRVSPEC:
453 case SIOCSDRVSPEC:
454 if (ifd->ifd_cmd >= bridge_control_table_size) {
455 error = EINVAL;
456 break;
457 }
458 bc = &bridge_control_table[ifd->ifd_cmd];
459
460 if (cmd == SIOCGDRVSPEC &&
461 (bc->bc_flags & BC_F_COPYOUT) == 0) {
462 error = EINVAL;
463 break;
464 }
465 else if (cmd == SIOCSDRVSPEC &&
466 (bc->bc_flags & BC_F_COPYOUT) != 0) {
467 error = EINVAL;
468 break;
469 }
470
471 if (bc->bc_flags & BC_F_SUSER) {
472 error = suser(p->p_ucred, &p->p_acflag);
473 if (error)
474 break;
475 }
476
477 if (ifd->ifd_len != bc->bc_argsize ||
478 ifd->ifd_len > sizeof(args)) {
479 error = EINVAL;
480 break;
481 }
482
483 if (bc->bc_flags & BC_F_COPYIN) {
484 error = copyin(ifd->ifd_data, &args, ifd->ifd_len);
485 if (error)
486 break;
487 }
488
489 error = (*bc->bc_func)(sc, &args);
490 if (error)
491 break;
492
493 if (bc->bc_flags & BC_F_COPYOUT)
494 error = copyout(&args, ifd->ifd_data, ifd->ifd_len);
495
496 break;
497
498 case SIOCSIFFLAGS:
499 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
500 /*
501 * If interface is marked down and it is running,
502 * then stop and disable it.
503 */
504 (*ifp->if_stop)(ifp, 1);
505 } else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
506 /*
507 * If interface is marked up and it is stopped, then
508 * start it.
509 */
510 error = (*ifp->if_init)(ifp);
511 }
512 break;
513
514 default:
515 error = ENOTTY;
516 break;
517 }
518
519 splx(s);
520
521 return (error);
522 }
523
524 /*
525 * bridge_lookup_member:
526 *
527 * Lookup a bridge member interface. Must be called at splnet().
528 */
529 struct bridge_iflist *
530 bridge_lookup_member(struct bridge_softc *sc, const char *name)
531 {
532 struct bridge_iflist *bif;
533 struct ifnet *ifp;
534
535 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
536 ifp = bif->bif_ifp;
537 if (strcmp(ifp->if_xname, name) == 0)
538 return (bif);
539 }
540
541 return (NULL);
542 }
543
544 /*
545 * bridge_lookup_member_if:
546 *
547 * Lookup a bridge member interface by ifnet*. Must be called at splnet().
548 */
549 struct bridge_iflist *
550 bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp)
551 {
552 struct bridge_iflist *bif;
553
554 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
555 if (bif->bif_ifp == member_ifp)
556 return (bif);
557 }
558
559 return (NULL);
560 }
561
562 /*
563 * bridge_delete_member:
564 *
565 * Delete the specified member interface.
566 */
567 void
568 bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
569 {
570 struct ifnet *ifs = bif->bif_ifp;
571
572 switch (ifs->if_type) {
573 case IFT_ETHER:
574 /*
575 * Take the interface out of promiscuous mode.
576 */
577 (void) ifpromisc(ifs, 0);
578 break;
579
580 default:
581 #ifdef DIAGNOSTIC
582 panic("bridge_delete_member: impossible");
583 #endif
584 break;
585 }
586
587 ifs->if_bridge = NULL;
588 LIST_REMOVE(bif, bif_next);
589
590 bridge_rtdelete(sc, ifs);
591
592 free(bif, M_DEVBUF);
593
594 if (sc->sc_if.if_flags & IFF_RUNNING)
595 bstp_initialization(sc);
596 }
597
598 int
599 bridge_ioctl_add(struct bridge_softc *sc, void *arg)
600 {
601 struct ifbreq *req = arg;
602 struct bridge_iflist *bif = NULL;
603 struct ifnet *ifs;
604 int error = 0;
605
606 ifs = ifunit(req->ifbr_ifsname);
607 if (ifs == NULL)
608 return (ENOENT);
609
610 if (sc->sc_if.if_mtu != ifs->if_mtu)
611 return (EINVAL);
612
613 if (ifs->if_bridge == sc)
614 return (EEXIST);
615
616 if (ifs->if_bridge != NULL)
617 return (EBUSY);
618
619 bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT);
620 if (bif == NULL)
621 return (ENOMEM);
622
623 switch (ifs->if_type) {
624 case IFT_ETHER:
625 /*
626 * Place the interface into promiscuous mode.
627 */
628 error = ifpromisc(ifs, 1);
629 if (error)
630 goto out;
631 break;
632
633 default:
634 error = EINVAL;
635 goto out;
636 }
637
638 bif->bif_ifp = ifs;
639 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
640 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
641 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
642
643 ifs->if_bridge = sc;
644 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
645
646 if (sc->sc_if.if_flags & IFF_RUNNING)
647 bstp_initialization(sc);
648 else
649 bstp_stop(sc);
650
651 out:
652 if (error) {
653 if (bif != NULL)
654 free(bif, M_DEVBUF);
655 }
656 return (error);
657 }
658
659 int
660 bridge_ioctl_del(struct bridge_softc *sc, void *arg)
661 {
662 struct ifbreq *req = arg;
663 struct bridge_iflist *bif;
664
665 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
666 if (bif == NULL)
667 return (ENOENT);
668
669 bridge_delete_member(sc, bif);
670
671 return (0);
672 }
673
674 int
675 bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
676 {
677 struct ifbreq *req = arg;
678 struct bridge_iflist *bif;
679
680 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
681 if (bif == NULL)
682 return (ENOENT);
683
684 req->ifbr_ifsflags = bif->bif_flags;
685 req->ifbr_state = bif->bif_state;
686 req->ifbr_priority = bif->bif_priority;
687 req->ifbr_path_cost = bif->bif_path_cost;
688 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
689
690 return (0);
691 }
692
693 int
694 bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
695 {
696 struct ifbreq *req = arg;
697 struct bridge_iflist *bif;
698
699 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
700 if (bif == NULL)
701 return (ENOENT);
702
703 if (req->ifbr_ifsflags & IFBIF_STP) {
704 switch (bif->bif_ifp->if_type) {
705 case IFT_ETHER:
706 /* These can do spanning tree. */
707 break;
708
709 default:
710 /* Nothing else can. */
711 return (EINVAL);
712 }
713 }
714
715 bif->bif_flags = req->ifbr_ifsflags;
716
717 if (sc->sc_if.if_flags & IFF_RUNNING)
718 bstp_initialization(sc);
719
720 return (0);
721 }
722
723 int
724 bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
725 {
726 struct ifbrparam *param = arg;
727
728 sc->sc_brtmax = param->ifbrp_csize;
729 bridge_rttrim(sc);
730
731 return (0);
732 }
733
734 int
735 bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
736 {
737 struct ifbrparam *param = arg;
738
739 param->ifbrp_csize = sc->sc_brtmax;
740
741 return (0);
742 }
743
744 int
745 bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
746 {
747 struct ifbifconf *bifc = arg;
748 struct bridge_iflist *bif;
749 struct ifbreq breq;
750 int count, len, error = 0;
751
752 count = 0;
753 LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
754 count++;
755
756 if (bifc->ifbic_len == 0) {
757 bifc->ifbic_len = sizeof(breq) * count;
758 return (0);
759 }
760
761 count = 0;
762 len = bifc->ifbic_len;
763 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
764 if (len < sizeof(breq))
765 break;
766
767 strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname,
768 sizeof(breq.ifbr_ifsname));
769 breq.ifbr_ifsflags = bif->bif_flags;
770 breq.ifbr_state = bif->bif_state;
771 breq.ifbr_priority = bif->bif_priority;
772 breq.ifbr_path_cost = bif->bif_path_cost;
773 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
774 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
775 if (error)
776 break;
777 count++;
778 len -= sizeof(breq);
779 }
780
781 bifc->ifbic_len = sizeof(breq) * count;
782 return (error);
783 }
784
785 int
786 bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
787 {
788 struct ifbaconf *bac = arg;
789 struct bridge_rtnode *brt;
790 struct ifbareq bareq;
791 int count = 0, error = 0, len;
792
793 if (bac->ifbac_len == 0)
794 return (0);
795
796 len = bac->ifbac_len;
797 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
798 if (len < sizeof(bareq))
799 goto out;
800 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname,
801 sizeof(bareq.ifba_ifsname));
802 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
803 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
804 bareq.ifba_expire = brt->brt_expire - mono_time.tv_sec;
805 else
806 bareq.ifba_expire = 0;
807 bareq.ifba_flags = brt->brt_flags;
808
809 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
810 if (error)
811 goto out;
812 count++;
813 len -= sizeof(bareq);
814 }
815 out:
816 bac->ifbac_len = sizeof(bareq) * count;
817 return (error);
818 }
819
820 int
821 bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
822 {
823 struct ifbareq *req = arg;
824 struct bridge_iflist *bif;
825 int error;
826
827 bif = bridge_lookup_member(sc, req->ifba_ifsname);
828 if (bif == NULL)
829 return (ENOENT);
830
831 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
832 req->ifba_flags);
833
834 return (error);
835 }
836
837 int
838 bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
839 {
840 struct ifbrparam *param = arg;
841
842 sc->sc_brttimeout = param->ifbrp_ctime;
843
844 return (0);
845 }
846
847 int
848 bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
849 {
850 struct ifbrparam *param = arg;
851
852 param->ifbrp_ctime = sc->sc_brttimeout;
853
854 return (0);
855 }
856
857 int
858 bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
859 {
860 struct ifbareq *req = arg;
861
862 return (bridge_rtdaddr(sc, req->ifba_dst));
863 }
864
865 int
866 bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
867 {
868 struct ifbreq *req = arg;
869
870 bridge_rtflush(sc, req->ifbr_ifsflags);
871
872 return (0);
873 }
874
875 int
876 bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
877 {
878 struct ifbrparam *param = arg;
879
880 param->ifbrp_prio = sc->sc_bridge_priority;
881
882 return (0);
883 }
884
885 int
886 bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
887 {
888 struct ifbrparam *param = arg;
889
890 sc->sc_bridge_priority = param->ifbrp_prio;
891
892 if (sc->sc_if.if_flags & IFF_RUNNING)
893 bstp_initialization(sc);
894
895 return (0);
896 }
897
898 int
899 bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
900 {
901 struct ifbrparam *param = arg;
902
903 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
904
905 return (0);
906 }
907
908 int
909 bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
910 {
911 struct ifbrparam *param = arg;
912
913 if (param->ifbrp_hellotime == 0)
914 return (EINVAL);
915 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
916
917 if (sc->sc_if.if_flags & IFF_RUNNING)
918 bstp_initialization(sc);
919
920 return (0);
921 }
922
923 int
924 bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
925 {
926 struct ifbrparam *param = arg;
927
928 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
929
930 return (0);
931 }
932
933 int
934 bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
935 {
936 struct ifbrparam *param = arg;
937
938 if (param->ifbrp_fwddelay == 0)
939 return (EINVAL);
940 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
941
942 if (sc->sc_if.if_flags & IFF_RUNNING)
943 bstp_initialization(sc);
944
945 return (0);
946 }
947
948 int
949 bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
950 {
951 struct ifbrparam *param = arg;
952
953 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
954
955 return (0);
956 }
957
958 int
959 bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
960 {
961 struct ifbrparam *param = arg;
962
963 if (param->ifbrp_maxage == 0)
964 return (EINVAL);
965 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
966
967 if (sc->sc_if.if_flags & IFF_RUNNING)
968 bstp_initialization(sc);
969
970 return (0);
971 }
972
973 int
974 bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
975 {
976 struct ifbreq *req = arg;
977 struct bridge_iflist *bif;
978
979 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
980 if (bif == NULL)
981 return (ENOENT);
982
983 bif->bif_priority = req->ifbr_priority;
984
985 if (sc->sc_if.if_flags & IFF_RUNNING)
986 bstp_initialization(sc);
987
988 return (0);
989 }
990
991 #ifdef BRIDGE_IPF
992 int
993 bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg)
994 {
995 struct ifbrparam *param = arg;
996
997 param->ifbrp_filter = sc->sc_filter_flags;
998
999 return (0);
1000 }
1001
1002 int
1003 bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg)
1004 {
1005 struct ifbrparam *param = arg;
1006 uint32_t nflags, oflags;
1007
1008 if (param->ifbrp_filter & ~IFBF_FILT_MASK)
1009 return (EINVAL);
1010
1011 nflags = param->ifbrp_filter;
1012 oflags = sc->sc_filter_flags;
1013
1014 if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) {
1015 pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1016 &sc->sc_if.if_pfil);
1017 }
1018 if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) {
1019 pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1020 &sc->sc_if.if_pfil);
1021 }
1022
1023 sc->sc_filter_flags = nflags;
1024
1025 return (0);
1026 }
1027 #endif /* BRIDGE_IPF */
1028
1029 int
1030 bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg)
1031 {
1032 struct ifbreq *req = arg;
1033 struct bridge_iflist *bif;
1034
1035 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
1036 if (bif == NULL)
1037 return (ENOENT);
1038
1039 bif->bif_path_cost = req->ifbr_path_cost;
1040
1041 if (sc->sc_if.if_flags & IFF_RUNNING)
1042 bstp_initialization(sc);
1043
1044 return (0);
1045 }
1046
1047 /*
1048 * bridge_ifdetach:
1049 *
1050 * Detach an interface from a bridge. Called when a member
1051 * interface is detaching.
1052 */
1053 void
1054 bridge_ifdetach(struct ifnet *ifp)
1055 {
1056 struct bridge_softc *sc = ifp->if_bridge;
1057 struct ifbreq breq;
1058
1059 memset(&breq, 0, sizeof(breq));
1060 sprintf(breq.ifbr_ifsname, ifp->if_xname);
1061
1062 (void) bridge_ioctl_del(sc, &breq);
1063 }
1064
1065 /*
1066 * bridge_init:
1067 *
1068 * Initialize a bridge interface.
1069 */
1070 int
1071 bridge_init(struct ifnet *ifp)
1072 {
1073 struct bridge_softc *sc = ifp->if_softc;
1074
1075 if (ifp->if_flags & IFF_RUNNING)
1076 return (0);
1077
1078 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
1079 bridge_timer, sc);
1080
1081 ifp->if_flags |= IFF_RUNNING;
1082 bstp_initialization(sc);
1083 return (0);
1084 }
1085
1086 /*
1087 * bridge_stop:
1088 *
1089 * Stop the bridge interface.
1090 */
1091 void
1092 bridge_stop(struct ifnet *ifp, int disable)
1093 {
1094 struct bridge_softc *sc = ifp->if_softc;
1095
1096 if ((ifp->if_flags & IFF_RUNNING) == 0)
1097 return;
1098
1099 callout_stop(&sc->sc_brcallout);
1100 bstp_stop(sc);
1101
1102 IF_PURGE(&ifp->if_snd);
1103
1104 bridge_rtflush(sc, IFBF_FLUSHDYN);
1105
1106 ifp->if_flags &= ~IFF_RUNNING;
1107 }
1108
1109 /*
1110 * bridge_enqueue:
1111 *
1112 * Enqueue a packet on a bridge member interface.
1113 *
1114 * NOTE: must be called at splnet().
1115 */
1116 __inline void
1117 bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
1118 {
1119 ALTQ_DECL(struct altq_pktattr pktattr;)
1120 int len, error;
1121 short mflags;
1122
1123 #ifdef PFIL_HOOKS
1124 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, dst_ifp, PFIL_OUT) != 0) {
1125 m_freem(m);
1126 return;
1127 }
1128 if (m == NULL)
1129 return;
1130 #endif /* PFIL_HOOKS */
1131
1132 #ifdef ALTQ
1133 /*
1134 * If ALTQ is enabled on the member interface, do
1135 * classification; the queueing discipline might
1136 * not require classification, but might require
1137 * the address family/header pointer in the pktattr.
1138 */
1139 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) {
1140 /* XXX IFT_ETHER */
1141 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
1142 }
1143 #endif /* ALTQ */
1144
1145 len = m->m_pkthdr.len;
1146 mflags = m->m_flags;
1147 IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
1148 if (error) {
1149 /* mbuf is already freed */
1150 sc->sc_if.if_oerrors++;
1151 return;
1152 }
1153
1154 sc->sc_if.if_opackets++;
1155 sc->sc_if.if_obytes += len;
1156
1157 dst_ifp->if_obytes += len;
1158
1159 if (mflags & M_MCAST) {
1160 sc->sc_if.if_omcasts++;
1161 dst_ifp->if_omcasts++;
1162 }
1163
1164 if ((dst_ifp->if_flags & IFF_OACTIVE) == 0)
1165 (*dst_ifp->if_start)(dst_ifp);
1166 }
1167
1168 /*
1169 * bridge_output:
1170 *
1171 * Send output from a bridge member interface. This
1172 * performs the bridging function for locally originated
1173 * packets.
1174 *
1175 * The mbuf has the Ethernet header already attached. We must
1176 * enqueue or free the mbuf before returning.
1177 */
1178 int
1179 bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
1180 struct rtentry *rt)
1181 {
1182 struct ether_header *eh;
1183 struct ifnet *dst_if;
1184 struct bridge_softc *sc;
1185 int s;
1186
1187 if (m->m_len < ETHER_HDR_LEN) {
1188 m = m_pullup(m, ETHER_HDR_LEN);
1189 if (m == NULL)
1190 return (0);
1191 }
1192
1193 eh = mtod(m, struct ether_header *);
1194 sc = ifp->if_bridge;
1195
1196 s = splnet();
1197
1198 /*
1199 * If bridge is down, but the original output interface is up,
1200 * go ahead and send out that interface. Otherwise, the packet
1201 * is dropped below.
1202 */
1203 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1204 dst_if = ifp;
1205 goto sendunicast;
1206 }
1207
1208 /*
1209 * If the packet is a multicast, or we don't know a better way to
1210 * get there, send to all interfaces.
1211 */
1212 if (ETHER_IS_MULTICAST(eh->ether_dhost))
1213 dst_if = NULL;
1214 else
1215 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1216 if (dst_if == NULL) {
1217 struct bridge_iflist *bif;
1218 struct mbuf *mc;
1219 int used = 0;
1220
1221 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1222 dst_if = bif->bif_ifp;
1223 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1224 continue;
1225
1226 /*
1227 * If this is not the original output interface,
1228 * and the interface is participating in spanning
1229 * tree, make sure the port is in a state that
1230 * allows forwarding.
1231 */
1232 if (dst_if != ifp &&
1233 (bif->bif_flags & IFBIF_STP) != 0) {
1234 switch (bif->bif_state) {
1235 case BSTP_IFSTATE_BLOCKING:
1236 case BSTP_IFSTATE_LISTENING:
1237 case BSTP_IFSTATE_DISABLED:
1238 continue;
1239 }
1240 }
1241
1242 if (LIST_NEXT(bif, bif_next) == NULL) {
1243 used = 1;
1244 mc = m;
1245 } else {
1246 mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1247 if (mc == NULL) {
1248 sc->sc_if.if_oerrors++;
1249 continue;
1250 }
1251 }
1252
1253 bridge_enqueue(sc, dst_if, mc);
1254 }
1255 if (used == 0)
1256 m_freem(m);
1257 splx(s);
1258 return (0);
1259 }
1260
1261 sendunicast:
1262 /*
1263 * XXX Spanning tree consideration here?
1264 */
1265
1266 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1267 m_freem(m);
1268 splx(s);
1269 return (0);
1270 }
1271
1272 bridge_enqueue(sc, dst_if, m);
1273
1274 splx(s);
1275 return (0);
1276 }
1277
1278 /*
1279 * bridge_start:
1280 *
1281 * Start output on a bridge.
1282 *
1283 * NOTE: This routine should never be called in this implementation.
1284 */
1285 void
1286 bridge_start(struct ifnet *ifp)
1287 {
1288
1289 printf("%s: bridge_start() called\n", ifp->if_xname);
1290 }
1291
1292 /*
1293 * bridge_forward:
1294 *
1295 * The fowarding function of the bridge.
1296 */
1297 void
1298 bridge_forward(struct bridge_softc *sc, struct mbuf *m)
1299 {
1300 struct bridge_iflist *bif;
1301 struct ifnet *src_if, *dst_if;
1302 struct ether_header *eh;
1303
1304 src_if = m->m_pkthdr.rcvif;
1305
1306 sc->sc_if.if_ipackets++;
1307 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1308
1309 /*
1310 * Look up the bridge_iflist.
1311 */
1312 bif = bridge_lookup_member_if(sc, src_if);
1313 if (bif == NULL) {
1314 /* Interface is not a bridge member (anymore?) */
1315 m_freem(m);
1316 return;
1317 }
1318
1319 if (bif->bif_flags & IFBIF_STP) {
1320 switch (bif->bif_state) {
1321 case BSTP_IFSTATE_BLOCKING:
1322 case BSTP_IFSTATE_LISTENING:
1323 case BSTP_IFSTATE_DISABLED:
1324 m_freem(m);
1325 return;
1326 }
1327 }
1328
1329 eh = mtod(m, struct ether_header *);
1330
1331 /*
1332 * If the interface is learning, and the source
1333 * address is valid and not multicast, record
1334 * the address.
1335 */
1336 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1337 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1338 (eh->ether_shost[0] == 0 &&
1339 eh->ether_shost[1] == 0 &&
1340 eh->ether_shost[2] == 0 &&
1341 eh->ether_shost[3] == 0 &&
1342 eh->ether_shost[4] == 0 &&
1343 eh->ether_shost[5] == 0) == 0) {
1344 (void) bridge_rtupdate(sc, eh->ether_shost,
1345 src_if, 0, IFBAF_DYNAMIC);
1346 }
1347
1348 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1349 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1350 m_freem(m);
1351 return;
1352 }
1353
1354 /*
1355 * At this point, the port either doesn't participate
1356 * in spanning tree or it is in the forwarding state.
1357 */
1358
1359 /*
1360 * If the packet is unicast, destined for someone on
1361 * "this" side of the bridge, drop it.
1362 */
1363 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1364 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1365 if (src_if == dst_if) {
1366 m_freem(m);
1367 return;
1368 }
1369 } else {
1370 /* ...forward it to all interfaces. */
1371 sc->sc_if.if_imcasts++;
1372 dst_if = NULL;
1373 }
1374
1375 #ifdef PFIL_HOOKS
1376 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, m->m_pkthdr.rcvif, PFIL_IN) != 0) {
1377 m_freem(m);
1378 return;
1379 }
1380 if (m == NULL)
1381 return;
1382 #endif /* PFIL_HOOKS */
1383
1384 if (dst_if == NULL) {
1385 bridge_broadcast(sc, src_if, m);
1386 return;
1387 }
1388
1389 /*
1390 * At this point, we're dealing with a unicast frame
1391 * going to a different interface.
1392 */
1393 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1394 m_freem(m);
1395 return;
1396 }
1397 bif = bridge_lookup_member_if(sc, dst_if);
1398 if (bif == NULL) {
1399 /* Not a member of the bridge (anymore?) */
1400 m_freem(m);
1401 return;
1402 }
1403
1404 if (bif->bif_flags & IFBIF_STP) {
1405 switch (bif->bif_state) {
1406 case BSTP_IFSTATE_DISABLED:
1407 case BSTP_IFSTATE_BLOCKING:
1408 m_freem(m);
1409 return;
1410 }
1411 }
1412
1413 bridge_enqueue(sc, dst_if, m);
1414 }
1415
1416 /*
1417 * bridge_input:
1418 *
1419 * Receive input from a member interface. Queue the packet for
1420 * bridging if it is not for us.
1421 */
1422 struct mbuf *
1423 bridge_input(struct ifnet *ifp, struct mbuf *m)
1424 {
1425 struct bridge_softc *sc = ifp->if_bridge;
1426 struct bridge_iflist *bif;
1427 struct ether_header *eh;
1428 struct mbuf *mc;
1429
1430 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1431 return (m);
1432
1433 bif = bridge_lookup_member_if(sc, ifp);
1434 if (bif == NULL)
1435 return (m);
1436
1437 eh = mtod(m, struct ether_header *);
1438
1439 if (m->m_flags & (M_BCAST|M_MCAST)) {
1440 /* Tap off 802.1D packets; they do not get forwarded. */
1441 if (memcmp(eh->ether_dhost, bstp_etheraddr,
1442 ETHER_ADDR_LEN) == 0) {
1443 m = bstp_input(ifp, m);
1444 if (m == NULL)
1445 return (NULL);
1446 }
1447
1448 if (bif->bif_flags & IFBIF_STP) {
1449 switch (bif->bif_state) {
1450 case BSTP_IFSTATE_BLOCKING:
1451 case BSTP_IFSTATE_LISTENING:
1452 case BSTP_IFSTATE_DISABLED:
1453 return (m);
1454 }
1455 }
1456
1457 /*
1458 * Make a deep copy of the packet and enqueue the copy
1459 * for bridge processing; return the original packet for
1460 * local processing.
1461 */
1462 mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
1463 if (mc == NULL)
1464 return (m);
1465
1466 /* Perform the bridge forwarding function with the copy. */
1467 bridge_forward(sc, mc);
1468
1469 /* Return the original packet for local processing. */
1470 return (m);
1471 }
1472
1473 if (bif->bif_flags & IFBIF_STP) {
1474 switch (bif->bif_state) {
1475 case BSTP_IFSTATE_BLOCKING:
1476 case BSTP_IFSTATE_LISTENING:
1477 case BSTP_IFSTATE_DISABLED:
1478 return (m);
1479 }
1480 }
1481
1482 /*
1483 * Unicast. Make sure it's not for us.
1484 */
1485 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1486 /* It is destined for us. */
1487 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1488 ETHER_ADDR_LEN) == 0) {
1489 if (bif->bif_flags & IFBIF_LEARNING)
1490 (void) bridge_rtupdate(sc,
1491 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1492 m->m_pkthdr.rcvif = bif->bif_ifp;
1493 return (m);
1494 }
1495
1496 /* We just received a packet that we sent out. */
1497 if (memcmp(LLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1498 ETHER_ADDR_LEN) == 0) {
1499 m_freem(m);
1500 return (NULL);
1501 }
1502 }
1503
1504 /* Perform the bridge forwarding function. */
1505 bridge_forward(sc, m);
1506
1507 return (NULL);
1508 }
1509
1510 /*
1511 * bridge_broadcast:
1512 *
1513 * Send a frame to all interfaces that are members of
1514 * the bridge, except for the one on which the packet
1515 * arrived.
1516 */
1517 void
1518 bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1519 struct mbuf *m)
1520 {
1521 struct bridge_iflist *bif;
1522 struct mbuf *mc;
1523 struct ifnet *dst_if;
1524 int used = 0;
1525
1526 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1527 dst_if = bif->bif_ifp;
1528 if (dst_if == src_if)
1529 continue;
1530
1531 if (bif->bif_flags & IFBIF_STP) {
1532 switch (bif->bif_state) {
1533 case BSTP_IFSTATE_BLOCKING:
1534 case BSTP_IFSTATE_DISABLED:
1535 continue;
1536 }
1537 }
1538
1539 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
1540 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
1541 continue;
1542
1543 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1544 continue;
1545
1546 if (LIST_NEXT(bif, bif_next) == NULL) {
1547 mc = m;
1548 used = 1;
1549 } else {
1550 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1551 if (mc == NULL) {
1552 sc->sc_if.if_oerrors++;
1553 continue;
1554 }
1555 }
1556
1557 bridge_enqueue(sc, dst_if, mc);
1558 }
1559 if (used == 0)
1560 m_freem(m);
1561 }
1562
1563 /*
1564 * bridge_rtupdate:
1565 *
1566 * Add a bridge routing entry.
1567 */
1568 int
1569 bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
1570 struct ifnet *dst_if, int setflags, uint8_t flags)
1571 {
1572 struct bridge_rtnode *brt;
1573 int error;
1574
1575 /*
1576 * A route for this destination might already exist. If so,
1577 * update it, otherwise create a new one.
1578 */
1579 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) {
1580 if (sc->sc_brtcnt >= sc->sc_brtmax)
1581 return (ENOSPC);
1582
1583 /*
1584 * Allocate a new bridge forwarding node, and
1585 * initialize the expiration time and Ethernet
1586 * address.
1587 */
1588 brt = pool_get(&bridge_rtnode_pool, PR_NOWAIT);
1589 if (brt == NULL)
1590 return (ENOMEM);
1591
1592 memset(brt, 0, sizeof(*brt));
1593 brt->brt_expire = mono_time.tv_sec + sc->sc_brttimeout;
1594 brt->brt_flags = IFBAF_DYNAMIC;
1595 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
1596
1597 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
1598 pool_put(&bridge_rtnode_pool, brt);
1599 return (error);
1600 }
1601 }
1602
1603 brt->brt_ifp = dst_if;
1604 if (setflags) {
1605 brt->brt_flags = flags;
1606 brt->brt_expire = (flags & IFBAF_STATIC) ? 0 :
1607 mono_time.tv_sec + sc->sc_brttimeout;
1608 }
1609
1610 return (0);
1611 }
1612
1613 /*
1614 * bridge_rtlookup:
1615 *
1616 * Lookup the destination interface for an address.
1617 */
1618 struct ifnet *
1619 bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr)
1620 {
1621 struct bridge_rtnode *brt;
1622
1623 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1624 return (NULL);
1625
1626 return (brt->brt_ifp);
1627 }
1628
1629 /*
1630 * bridge_rttrim:
1631 *
1632 * Trim the routine table so that we have a number
1633 * of routing entries less than or equal to the
1634 * maximum number.
1635 */
1636 void
1637 bridge_rttrim(struct bridge_softc *sc)
1638 {
1639 struct bridge_rtnode *brt, *nbrt;
1640
1641 /* Make sure we actually need to do this. */
1642 if (sc->sc_brtcnt <= sc->sc_brtmax)
1643 return;
1644
1645 /* Force an aging cycle; this might trim enough addresses. */
1646 bridge_rtage(sc);
1647 if (sc->sc_brtcnt <= sc->sc_brtmax)
1648 return;
1649
1650 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1651 nbrt = LIST_NEXT(brt, brt_list);
1652 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1653 bridge_rtnode_destroy(sc, brt);
1654 if (sc->sc_brtcnt <= sc->sc_brtmax)
1655 return;
1656 }
1657 }
1658 }
1659
1660 /*
1661 * bridge_timer:
1662 *
1663 * Aging timer for the bridge.
1664 */
1665 void
1666 bridge_timer(void *arg)
1667 {
1668 struct bridge_softc *sc = arg;
1669 int s;
1670
1671 s = splnet();
1672 bridge_rtage(sc);
1673 splx(s);
1674
1675 if (sc->sc_if.if_flags & IFF_RUNNING)
1676 callout_reset(&sc->sc_brcallout,
1677 bridge_rtable_prune_period * hz, bridge_timer, sc);
1678 }
1679
1680 /*
1681 * bridge_rtage:
1682 *
1683 * Perform an aging cycle.
1684 */
1685 void
1686 bridge_rtage(struct bridge_softc *sc)
1687 {
1688 struct bridge_rtnode *brt, *nbrt;
1689
1690 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1691 nbrt = LIST_NEXT(brt, brt_list);
1692 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1693 if (mono_time.tv_sec >= brt->brt_expire)
1694 bridge_rtnode_destroy(sc, brt);
1695 }
1696 }
1697 }
1698
1699 /*
1700 * bridge_rtflush:
1701 *
1702 * Remove all dynamic addresses from the bridge.
1703 */
1704 void
1705 bridge_rtflush(struct bridge_softc *sc, int full)
1706 {
1707 struct bridge_rtnode *brt, *nbrt;
1708
1709 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1710 nbrt = LIST_NEXT(brt, brt_list);
1711 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
1712 bridge_rtnode_destroy(sc, brt);
1713 }
1714 }
1715
1716 /*
1717 * bridge_rtdaddr:
1718 *
1719 * Remove an address from the table.
1720 */
1721 int
1722 bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr)
1723 {
1724 struct bridge_rtnode *brt;
1725
1726 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1727 return (ENOENT);
1728
1729 bridge_rtnode_destroy(sc, brt);
1730 return (0);
1731 }
1732
1733 /*
1734 * bridge_rtdelete:
1735 *
1736 * Delete routes to a speicifc member interface.
1737 */
1738 void
1739 bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp)
1740 {
1741 struct bridge_rtnode *brt, *nbrt;
1742
1743 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1744 nbrt = LIST_NEXT(brt, brt_list);
1745 if (brt->brt_ifp == ifp)
1746 bridge_rtnode_destroy(sc, brt);
1747 }
1748 }
1749
1750 /*
1751 * bridge_rtable_init:
1752 *
1753 * Initialize the route table for this bridge.
1754 */
1755 int
1756 bridge_rtable_init(struct bridge_softc *sc)
1757 {
1758 int i;
1759
1760 sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
1761 M_DEVBUF, M_NOWAIT);
1762 if (sc->sc_rthash == NULL)
1763 return (ENOMEM);
1764
1765 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
1766 LIST_INIT(&sc->sc_rthash[i]);
1767
1768 sc->sc_rthash_key = arc4random();
1769
1770 LIST_INIT(&sc->sc_rtlist);
1771
1772 return (0);
1773 }
1774
1775 /*
1776 * bridge_rtable_fini:
1777 *
1778 * Deconstruct the route table for this bridge.
1779 */
1780 void
1781 bridge_rtable_fini(struct bridge_softc *sc)
1782 {
1783
1784 free(sc->sc_rthash, M_DEVBUF);
1785 }
1786
1787 /*
1788 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1789 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1790 */
1791 #define mix(a, b, c) \
1792 do { \
1793 a -= b; a -= c; a ^= (c >> 13); \
1794 b -= c; b -= a; b ^= (a << 8); \
1795 c -= a; c -= b; c ^= (b >> 13); \
1796 a -= b; a -= c; a ^= (c >> 12); \
1797 b -= c; b -= a; b ^= (a << 16); \
1798 c -= a; c -= b; c ^= (b >> 5); \
1799 a -= b; a -= c; a ^= (c >> 3); \
1800 b -= c; b -= a; b ^= (a << 10); \
1801 c -= a; c -= b; c ^= (b >> 15); \
1802 } while (/*CONSTCOND*/0)
1803
1804 static __inline uint32_t
1805 bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
1806 {
1807 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
1808
1809 b += addr[5] << 8;
1810 b += addr[4];
1811 a += addr[3] << 24;
1812 a += addr[2] << 16;
1813 a += addr[1] << 8;
1814 a += addr[0];
1815
1816 mix(a, b, c);
1817
1818 return (c & BRIDGE_RTHASH_MASK);
1819 }
1820
1821 #undef mix
1822
1823 /*
1824 * bridge_rtnode_lookup:
1825 *
1826 * Look up a bridge route node for the specified destination.
1827 */
1828 struct bridge_rtnode *
1829 bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
1830 {
1831 struct bridge_rtnode *brt;
1832 uint32_t hash;
1833 int dir;
1834
1835 hash = bridge_rthash(sc, addr);
1836 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
1837 dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN);
1838 if (dir == 0)
1839 return (brt);
1840 if (dir > 0)
1841 return (NULL);
1842 }
1843
1844 return (NULL);
1845 }
1846
1847 /*
1848 * bridge_rtnode_insert:
1849 *
1850 * Insert the specified bridge node into the route table. We
1851 * assume the entry is not already in the table.
1852 */
1853 int
1854 bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
1855 {
1856 struct bridge_rtnode *lbrt;
1857 uint32_t hash;
1858 int dir;
1859
1860 hash = bridge_rthash(sc, brt->brt_addr);
1861
1862 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
1863 if (lbrt == NULL) {
1864 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
1865 goto out;
1866 }
1867
1868 do {
1869 dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN);
1870 if (dir == 0)
1871 return (EEXIST);
1872 if (dir > 0) {
1873 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
1874 goto out;
1875 }
1876 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
1877 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
1878 goto out;
1879 }
1880 lbrt = LIST_NEXT(lbrt, brt_hash);
1881 } while (lbrt != NULL);
1882
1883 #ifdef DIAGNOSTIC
1884 panic("bridge_rtnode_insert: impossible");
1885 #endif
1886
1887 out:
1888 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
1889 sc->sc_brtcnt++;
1890
1891 return (0);
1892 }
1893
1894 /*
1895 * bridge_rtnode_destroy:
1896 *
1897 * Destroy a bridge rtnode.
1898 */
1899 void
1900 bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
1901 {
1902
1903 LIST_REMOVE(brt, brt_hash);
1904
1905 LIST_REMOVE(brt, brt_list);
1906 sc->sc_brtcnt--;
1907 pool_put(&bridge_rtnode_pool, brt);
1908 }
1909
1910 #ifdef BRIDGE_IPF
1911 extern struct pfil_head inet_pfil_hook; /* XXX */
1912 extern struct pfil_head inet6_pfil_hook; /* XXX */
1913
1914 /*
1915 * Send bridge packets through IPF if they are one of the types IPF can deal
1916 * with, or if they are ARP or REVARP. (IPF will pass ARP and REVARP without
1917 * question.)
1918 */
1919 static int bridge_ipf(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
1920 {
1921 int snap, error;
1922 struct ether_header *eh;
1923 struct mbuf *m1, *m2;
1924 u_int16_t ether_type;
1925
1926 snap = 0;
1927 error = -1; /* Default error if not error == 0 */
1928 eh = mtod(*mp, struct ether_header *);
1929 ether_type = ntohs(eh->ether_type);
1930
1931 /*
1932 * Check for SNAP/LLC.
1933 */
1934 if (ether_type < ETHERMTU) {
1935 struct llc *llc = (struct llc *)(eh + 1);
1936
1937 if ((*mp)->m_len >= ETHER_HDR_LEN + 8 &&
1938 llc->llc_dsap == LLC_SNAP_LSAP &&
1939 llc->llc_ssap == LLC_SNAP_LSAP &&
1940 llc->llc_control == LLC_UI) {
1941 ether_type = htons(llc->llc_un.type_snap.ether_type);
1942 snap = 1;
1943 }
1944 }
1945
1946 /*
1947 * If we're trying to filter bridge traffic, don't look at anything
1948 * other than IP and ARP traffic. If the filter doesn't understand
1949 * IPv6, don't allow IPv6 through the bridge either. This is lame
1950 * since if we really wanted, say, an AppleTalk filter, we are hosed,
1951 * but of course we don't have an AppleTalk filter to begin with.
1952 * (Note that since IPF doesn't understand ARP it will pass *ALL*
1953 * ARP traffic.)
1954 */
1955 switch (ether_type) {
1956 case ETHERTYPE_ARP:
1957 case ETHERTYPE_REVARP:
1958 return 0; /* Automatically pass */
1959 case ETHERTYPE_IP:
1960 # ifdef INET6
1961 case ETHERTYPE_IPV6:
1962 # endif /* INET6 */
1963 break;
1964 default:
1965 goto bad;
1966 }
1967
1968 /* Strip off the Ethernet header---but keep a copy. */
1969 if ((m1 = m_split(*mp, sizeof(struct ether_header), M_NOWAIT)) == NULL)
1970 goto bad;
1971 /* Strip off snap header, if present */
1972 if (snap) {
1973 if ((m2 = m_split(m1, sizeof(struct llc), M_NOWAIT)) == NULL)
1974 goto bad2;
1975 } else
1976 m2 = m1;
1977
1978 /*
1979 * Check basic packet sanity, if the packet is outbound, and
1980 * run IPF filter.
1981 */
1982 if (ether_type == ETHERTYPE_IP &&
1983 (dir == PFIL_OUT || bridge_ip_checkbasic(&m2) == 0)) {
1984 error = pfil_run_hooks(&inet_pfil_hook, &m2, ifp, dir);
1985 if (error) goto bad2;
1986 }
1987 # ifdef INET6
1988 if (ether_type == ETHERTYPE_IPV6 &&
1989 (dir == PFIL_OUT || bridge_ip6_checkbasic(&m2) == 0)) {
1990 error = pfil_run_hooks(&inet6_pfil_hook, &m2, ifp, dir);
1991 if (error) goto bad2;
1992 }
1993 # endif
1994 if (m2 == NULL) goto bad2;
1995
1996 /*
1997 * Finally, put everything back the way it was and return
1998 */
1999 if (snap)
2000 m_cat(m1, m2);
2001 else
2002 m1 = m2;
2003 m_cat(*mp, m1);
2004 return 0;
2005
2006
2007 bad2:
2008 if (snap)
2009 m_freem(m1);
2010 m_freem(m2);
2011 bad:
2012 m_freem(*mp);
2013 *mp = NULL;
2014 return error;
2015 }
2016
2017 /*
2018 * Perform basic checks on header size since
2019 * IPF assumes ip_input has already processed
2020 * it for it. Cut-and-pasted from ip_input.c.
2021 * Given how simple the IPv6 version is,
2022 * does the IPv4 version really need to be
2023 * this complicated?
2024 *
2025 * XXX Should we update ipstat here, or not?
2026 * XXX Right now we update ipstat but not
2027 * XXX csum_counter.
2028 */
2029 static int
2030 bridge_ip_checkbasic(struct mbuf **mp)
2031 {
2032 struct mbuf *m = *mp;
2033 struct ip *ip;
2034 int len, hlen;
2035
2036 if (*mp == NULL)
2037 return -1;
2038
2039 if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
2040 if ((m = m_copyup(m, sizeof(struct ip),
2041 (max_linkhdr + 3) & ~3)) == NULL) {
2042 /* XXXJRT new stat, please */
2043 ipstat.ips_toosmall++;
2044 goto bad;
2045 }
2046 } else if (__predict_false(m->m_len < sizeof (struct ip))) {
2047 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
2048 ipstat.ips_toosmall++;
2049 goto bad;
2050 }
2051 }
2052 ip = mtod(m, struct ip *);
2053 if (ip == NULL) goto bad;
2054
2055 if (ip->ip_v != IPVERSION) {
2056 ipstat.ips_badvers++;
2057 goto bad;
2058 }
2059 hlen = ip->ip_hl << 2;
2060 if (hlen < sizeof(struct ip)) { /* minimum header length */
2061 ipstat.ips_badhlen++;
2062 goto bad;
2063 }
2064 if (hlen > m->m_len) {
2065 if ((m = m_pullup(m, hlen)) == 0) {
2066 ipstat.ips_badhlen++;
2067 goto bad;
2068 }
2069 ip = mtod(m, struct ip *);
2070 if (ip == NULL) goto bad;
2071 }
2072
2073 switch (m->m_pkthdr.csum_flags &
2074 ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
2075 M_CSUM_IPv4_BAD)) {
2076 case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
2077 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */
2078 goto bad;
2079
2080 case M_CSUM_IPv4:
2081 /* Checksum was okay. */
2082 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); */
2083 break;
2084
2085 default:
2086 /* Must compute it ourselves. */
2087 /* INET_CSUM_COUNTER_INCR(&ip_swcsum); */
2088 if (in_cksum(m, hlen) != 0)
2089 goto bad;
2090 break;
2091 }
2092
2093 /* Retrieve the packet length. */
2094 len = ntohs(ip->ip_len);
2095
2096 /*
2097 * Check for additional length bogosity
2098 */
2099 if (len < hlen) {
2100 ipstat.ips_badlen++;
2101 goto bad;
2102 }
2103
2104 /*
2105 * Check that the amount of data in the buffers
2106 * is as at least much as the IP header would have us expect.
2107 * Drop packet if shorter than we expect.
2108 */
2109 if (m->m_pkthdr.len < len) {
2110 ipstat.ips_tooshort++;
2111 goto bad;
2112 }
2113
2114 /* Checks out, proceed */
2115 *mp = m;
2116 return 0;
2117
2118 bad:
2119 *mp = m;
2120 return -1;
2121 }
2122
2123 # ifdef INET6
2124 /*
2125 * Same as above, but for IPv6.
2126 * Cut-and-pasted from ip6_input.c.
2127 * XXX Should we update ip6stat, or not?
2128 */
2129 static int
2130 bridge_ip6_checkbasic(struct mbuf **mp)
2131 {
2132 struct mbuf *m = *mp;
2133 struct ip6 *ip6;
2134
2135 /*
2136 * If the IPv6 header is not aligned, slurp it up into a new
2137 * mbuf with space for link headers, in the event we forward
2138 * it. Otherwise, if it is aligned, make sure the entire base
2139 * IPv6 header is in the first mbuf of the chain.
2140 */
2141 if (IP6_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
2142 struct ifnet *inifp = m->m_pkthdr.rcvif;
2143 if ((m = m_copyup(m, sizeof(struct ip6_hdr),
2144 (max_linkhdr + 3) & ~3)) == NULL) {
2145 /* XXXJRT new stat, please */
2146 ip6stat.ip6s_toosmall++;
2147 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2148 goto bad;
2149 }
2150 } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
2151 struct ifnet *inifp = m->m_pkthdr.rcvif;
2152 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
2153 ip6stat.ip6s_toosmall++;
2154 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2155 goto bad;
2156 }
2157 }
2158
2159 ip6 = mtod(m, struct ip6_hdr *);
2160
2161 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
2162 ip6stat.ip6s_badvers++;
2163 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
2164 goto bad;
2165 }
2166
2167 /* Checks out, proceed */
2168 *mp = m;
2169 return 0;
2170
2171 bad:
2172 *mp = m;
2173 return -1;
2174 }
2175 # endif /* INET6 */
2176 #endif /* BRIDGE_IPF */
2177