Sync usage with man page.
[netbsd-mini2440.git] / sys / net / if_bridge.c
blobf3953d85c38a1b43eb0c153e7c91ef68d6f7ab8a
1 /* $NetBSD: if_bridge.c,v 1.69 2009/05/12 23:03:24 elad Exp $ */
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
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.
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.
39 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
40 * All rights reserved.
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.
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.
68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
72 * Network interface bridge support.
74 * TODO:
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).
82 #include <sys/cdefs.h>
83 __KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.69 2009/05/12 23:03:24 elad Exp $");
85 #include "opt_bridge_ipf.h"
86 #include "opt_inet.h"
87 #include "opt_pfil_hooks.h"
88 #include "bpfilter.h"
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/socketvar.h> /* for softnet_lock */
96 #include <sys/sockio.h>
97 #include <sys/systm.h>
98 #include <sys/proc.h>
99 #include <sys/pool.h>
100 #include <sys/kauth.h>
101 #include <sys/cpu.h>
103 #if NBPFILTER > 0
104 #include <net/bpf.h>
105 #endif
106 #include <net/if.h>
107 #include <net/if_dl.h>
108 #include <net/if_types.h>
109 #include <net/if_llc.h>
111 #include <net/if_ether.h>
112 #include <net/if_bridgevar.h>
114 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
115 /* Used for bridge_ip[6]_checkbasic */
116 #include <netinet/in.h>
117 #include <netinet/in_systm.h>
118 #include <netinet/ip.h>
119 #include <netinet/ip_var.h>
120 #include <netinet/ip_private.h> /* XXX */
122 #include <netinet/ip6.h>
123 #include <netinet6/in6_var.h>
124 #include <netinet6/ip6_var.h>
125 #include <netinet6/ip6_private.h> /* XXX */
126 #endif /* BRIDGE_IPF && PFIL_HOOKS */
129 * Size of the route hash table. Must be a power of two.
131 #ifndef BRIDGE_RTHASH_SIZE
132 #define BRIDGE_RTHASH_SIZE 1024
133 #endif
135 #define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
137 #include "carp.h"
138 #if NCARP > 0
139 #include <netinet/in.h>
140 #include <netinet/in_var.h>
141 #include <netinet/ip_carp.h>
142 #endif
145 * Maximum number of addresses to cache.
147 #ifndef BRIDGE_RTABLE_MAX
148 #define BRIDGE_RTABLE_MAX 100
149 #endif
152 * Spanning tree defaults.
154 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
155 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
156 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
157 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
158 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
159 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
160 #define BSTP_DEFAULT_PATH_COST 55
163 * Timeout (in seconds) for entries learned dynamically.
165 #ifndef BRIDGE_RTABLE_TIMEOUT
166 #define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
167 #endif
170 * Number of seconds between walks of the route list.
172 #ifndef BRIDGE_RTABLE_PRUNE_PERIOD
173 #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
174 #endif
176 int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
178 static struct pool bridge_rtnode_pool;
180 void bridgeattach(int);
182 static int bridge_clone_create(struct if_clone *, int);
183 static int bridge_clone_destroy(struct ifnet *);
185 static int bridge_ioctl(struct ifnet *, u_long, void *);
186 static int bridge_init(struct ifnet *);
187 static void bridge_stop(struct ifnet *, int);
188 static void bridge_start(struct ifnet *);
190 static void bridge_forward(void *);
192 static void bridge_timer(void *);
194 static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
195 struct mbuf *);
197 static int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
198 struct ifnet *, int, uint8_t);
199 static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *);
200 static void bridge_rttrim(struct bridge_softc *);
201 static void bridge_rtage(struct bridge_softc *);
202 static void bridge_rtflush(struct bridge_softc *, int);
203 static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
204 static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp);
206 static int bridge_rtable_init(struct bridge_softc *);
207 static void bridge_rtable_fini(struct bridge_softc *);
209 static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
210 const uint8_t *);
211 static int bridge_rtnode_insert(struct bridge_softc *,
212 struct bridge_rtnode *);
213 static void bridge_rtnode_destroy(struct bridge_softc *,
214 struct bridge_rtnode *);
216 static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
217 const char *name);
218 static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
219 struct ifnet *ifp);
220 static void bridge_delete_member(struct bridge_softc *,
221 struct bridge_iflist *);
223 static int bridge_ioctl_add(struct bridge_softc *, void *);
224 static int bridge_ioctl_del(struct bridge_softc *, void *);
225 static int bridge_ioctl_gifflags(struct bridge_softc *, void *);
226 static int bridge_ioctl_sifflags(struct bridge_softc *, void *);
227 static int bridge_ioctl_scache(struct bridge_softc *, void *);
228 static int bridge_ioctl_gcache(struct bridge_softc *, void *);
229 static int bridge_ioctl_gifs(struct bridge_softc *, void *);
230 static int bridge_ioctl_rts(struct bridge_softc *, void *);
231 static int bridge_ioctl_saddr(struct bridge_softc *, void *);
232 static int bridge_ioctl_sto(struct bridge_softc *, void *);
233 static int bridge_ioctl_gto(struct bridge_softc *, void *);
234 static int bridge_ioctl_daddr(struct bridge_softc *, void *);
235 static int bridge_ioctl_flush(struct bridge_softc *, void *);
236 static int bridge_ioctl_gpri(struct bridge_softc *, void *);
237 static int bridge_ioctl_spri(struct bridge_softc *, void *);
238 static int bridge_ioctl_ght(struct bridge_softc *, void *);
239 static int bridge_ioctl_sht(struct bridge_softc *, void *);
240 static int bridge_ioctl_gfd(struct bridge_softc *, void *);
241 static int bridge_ioctl_sfd(struct bridge_softc *, void *);
242 static int bridge_ioctl_gma(struct bridge_softc *, void *);
243 static int bridge_ioctl_sma(struct bridge_softc *, void *);
244 static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
245 static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
246 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
247 static int bridge_ioctl_gfilt(struct bridge_softc *, void *);
248 static int bridge_ioctl_sfilt(struct bridge_softc *, void *);
249 static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int);
250 static int bridge_ip_checkbasic(struct mbuf **mp);
251 # ifdef INET6
252 static int bridge_ip6_checkbasic(struct mbuf **mp);
253 # endif /* INET6 */
254 #endif /* BRIDGE_IPF && PFIL_HOOKS */
256 struct bridge_control {
257 int (*bc_func)(struct bridge_softc *, void *);
258 int bc_argsize;
259 int bc_flags;
262 #define BC_F_COPYIN 0x01 /* copy arguments in */
263 #define BC_F_COPYOUT 0x02 /* copy arguments out */
264 #define BC_F_SUSER 0x04 /* do super-user check */
266 static const struct bridge_control bridge_control_table[] = {
267 [BRDGADD] = {bridge_ioctl_add, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
268 [BRDGDEL] = {bridge_ioctl_del, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
270 [BRDGGIFFLGS] = {bridge_ioctl_gifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_COPYOUT},
271 [BRDGSIFFLGS] = {bridge_ioctl_sifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
273 [BRDGSCACHE] = {bridge_ioctl_scache, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
274 [BRDGGCACHE] = {bridge_ioctl_gcache, sizeof(struct ifbrparam), BC_F_COPYOUT},
276 [BRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_COPYIN|BC_F_COPYOUT},
277 [BRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_COPYIN|BC_F_COPYOUT},
279 [BRDGSADDR] = {bridge_ioctl_saddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},
281 [BRDGSTO] = {bridge_ioctl_sto, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
282 [BRDGGTO] = {bridge_ioctl_gto, sizeof(struct ifbrparam), BC_F_COPYOUT},
284 [BRDGDADDR] = {bridge_ioctl_daddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},
286 [BRDGFLUSH] = {bridge_ioctl_flush, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
288 [BRDGGPRI] = {bridge_ioctl_gpri, sizeof(struct ifbrparam), BC_F_COPYOUT},
289 [BRDGSPRI] = {bridge_ioctl_spri, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
291 [BRDGGHT] = {bridge_ioctl_ght, sizeof(struct ifbrparam), BC_F_COPYOUT},
292 [BRDGSHT] = {bridge_ioctl_sht, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
294 [BRDGGFD] = {bridge_ioctl_gfd, sizeof(struct ifbrparam), BC_F_COPYOUT},
295 [BRDGSFD] = {bridge_ioctl_sfd, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
297 [BRDGGMA] = {bridge_ioctl_gma, sizeof(struct ifbrparam), BC_F_COPYOUT},
298 [BRDGSMA] = {bridge_ioctl_sma, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
300 [BRDGSIFPRIO] = {bridge_ioctl_sifprio, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
302 [BRDGSIFCOST] = {bridge_ioctl_sifcost, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
303 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
304 [BRDGGFILT] = {bridge_ioctl_gfilt, sizeof(struct ifbrparam), BC_F_COPYOUT},
305 [BRDGSFILT] = {bridge_ioctl_sfilt, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
306 #endif /* BRIDGE_IPF && PFIL_HOOKS */
308 static const int bridge_control_table_size = __arraycount(bridge_control_table);
310 static LIST_HEAD(, bridge_softc) bridge_list;
312 static struct if_clone bridge_cloner =
313 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
316 * bridgeattach:
318 * Pseudo-device attach routine.
320 void
321 bridgeattach(int n)
324 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode),
325 0, 0, 0, "brtpl", NULL, IPL_NET);
327 LIST_INIT(&bridge_list);
328 if_clone_attach(&bridge_cloner);
332 * bridge_clone_create:
334 * Create a new bridge instance.
336 static int
337 bridge_clone_create(struct if_clone *ifc, int unit)
339 struct bridge_softc *sc;
340 struct ifnet *ifp;
341 int s;
343 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
344 ifp = &sc->sc_if;
346 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
347 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
348 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
349 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
350 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
351 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
352 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
353 sc->sc_filter_flags = 0;
355 /* software interrupt to do the work */
356 sc->sc_softintr = softint_establish(SOFTINT_NET, bridge_forward, sc);
357 if (sc->sc_softintr == NULL) {
358 free(sc, M_DEVBUF);
359 return ENOMEM;
362 /* Initialize our routing table. */
363 bridge_rtable_init(sc);
365 callout_init(&sc->sc_brcallout, 0);
366 callout_init(&sc->sc_bstpcallout, 0);
368 LIST_INIT(&sc->sc_iflist);
370 if_initname(ifp, ifc->ifc_name, unit);
371 ifp->if_softc = sc;
372 ifp->if_mtu = ETHERMTU;
373 ifp->if_ioctl = bridge_ioctl;
374 ifp->if_output = bridge_output;
375 ifp->if_start = bridge_start;
376 ifp->if_stop = bridge_stop;
377 ifp->if_init = bridge_init;
378 ifp->if_type = IFT_BRIDGE;
379 ifp->if_addrlen = 0;
380 ifp->if_dlt = DLT_EN10MB;
381 ifp->if_hdrlen = ETHER_HDR_LEN;
382 IFQ_SET_READY(&ifp->if_snd);
384 if_attach(ifp);
386 if_alloc_sadl(ifp);
388 s = splnet();
389 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
390 splx(s);
392 return (0);
396 * bridge_clone_destroy:
398 * Destroy a bridge instance.
400 static int
401 bridge_clone_destroy(struct ifnet *ifp)
403 struct bridge_softc *sc = ifp->if_softc;
404 struct bridge_iflist *bif;
405 int s;
407 s = splnet();
409 bridge_stop(ifp, 1);
411 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL)
412 bridge_delete_member(sc, bif);
414 LIST_REMOVE(sc, sc_list);
416 splx(s);
418 if_detach(ifp);
420 /* Tear down the routing table. */
421 bridge_rtable_fini(sc);
423 softint_disestablish(sc->sc_softintr);
425 free(sc, M_DEVBUF);
427 return (0);
431 * bridge_ioctl:
433 * Handle a control request from the operator.
435 static int
436 bridge_ioctl(struct ifnet *ifp, u_long cmd, void *data)
438 struct bridge_softc *sc = ifp->if_softc;
439 struct lwp *l = curlwp; /* XXX */
440 union {
441 struct ifbreq ifbreq;
442 struct ifbifconf ifbifconf;
443 struct ifbareq ifbareq;
444 struct ifbaconf ifbaconf;
445 struct ifbrparam ifbrparam;
446 } args;
447 struct ifdrv *ifd = (struct ifdrv *) data;
448 const struct bridge_control *bc = NULL; /* XXXGCC */
449 int s, error = 0;
451 /* Authorize command before calling splnet(). */
452 switch (cmd) {
453 case SIOCGDRVSPEC:
454 case SIOCSDRVSPEC:
455 if (ifd->ifd_cmd >= bridge_control_table_size) {
456 error = EINVAL;
457 return error;
460 bc = &bridge_control_table[ifd->ifd_cmd];
462 /* We only care about BC_F_SUSER at this point. */
463 if ((bc->bc_flags & BC_F_SUSER) == 0)
464 break;
466 error = kauth_authorize_generic(l->l_cred,
467 KAUTH_GENERIC_ISSUSER, NULL);
468 if (error)
469 return (error);
471 break;
474 s = splnet();
476 switch (cmd) {
477 case SIOCGDRVSPEC:
478 case SIOCSDRVSPEC:
479 KASSERT(bc != NULL);
480 if (cmd == SIOCGDRVSPEC &&
481 (bc->bc_flags & BC_F_COPYOUT) == 0) {
482 error = EINVAL;
483 break;
485 else if (cmd == SIOCSDRVSPEC &&
486 (bc->bc_flags & BC_F_COPYOUT) != 0) {
487 error = EINVAL;
488 break;
491 /* BC_F_SUSER is checked above, before splnet(). */
493 if (ifd->ifd_len != bc->bc_argsize ||
494 ifd->ifd_len > sizeof(args)) {
495 error = EINVAL;
496 break;
499 memset(&args, 0, sizeof(args));
500 if (bc->bc_flags & BC_F_COPYIN) {
501 error = copyin(ifd->ifd_data, &args, ifd->ifd_len);
502 if (error)
503 break;
506 error = (*bc->bc_func)(sc, &args);
507 if (error)
508 break;
510 if (bc->bc_flags & BC_F_COPYOUT)
511 error = copyout(&args, ifd->ifd_data, ifd->ifd_len);
513 break;
515 case SIOCSIFFLAGS:
516 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
517 break;
518 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
519 case IFF_RUNNING:
521 * If interface is marked down and it is running,
522 * then stop and disable it.
524 (*ifp->if_stop)(ifp, 1);
525 break;
526 case IFF_UP:
528 * If interface is marked up and it is stopped, then
529 * start it.
531 error = (*ifp->if_init)(ifp);
532 break;
533 default:
534 break;
536 break;
538 default:
539 error = ifioctl_common(ifp, cmd, data);
540 break;
543 splx(s);
545 return (error);
549 * bridge_lookup_member:
551 * Lookup a bridge member interface. Must be called at splnet().
553 static struct bridge_iflist *
554 bridge_lookup_member(struct bridge_softc *sc, const char *name)
556 struct bridge_iflist *bif;
557 struct ifnet *ifp;
559 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
560 ifp = bif->bif_ifp;
561 if (strcmp(ifp->if_xname, name) == 0)
562 return (bif);
565 return (NULL);
569 * bridge_lookup_member_if:
571 * Lookup a bridge member interface by ifnet*. Must be called at splnet().
573 static struct bridge_iflist *
574 bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp)
576 struct bridge_iflist *bif;
578 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
579 if (bif->bif_ifp == member_ifp)
580 return (bif);
583 return (NULL);
587 * bridge_delete_member:
589 * Delete the specified member interface.
591 static void
592 bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
594 struct ifnet *ifs = bif->bif_ifp;
596 switch (ifs->if_type) {
597 case IFT_ETHER:
599 * Take the interface out of promiscuous mode.
601 (void) ifpromisc(ifs, 0);
602 break;
603 default:
604 #ifdef DIAGNOSTIC
605 panic("bridge_delete_member: impossible");
606 #endif
607 break;
610 ifs->if_bridge = NULL;
611 LIST_REMOVE(bif, bif_next);
613 bridge_rtdelete(sc, ifs);
615 free(bif, M_DEVBUF);
617 if (sc->sc_if.if_flags & IFF_RUNNING)
618 bstp_initialization(sc);
621 static int
622 bridge_ioctl_add(struct bridge_softc *sc, void *arg)
624 struct ifbreq *req = arg;
625 struct bridge_iflist *bif = NULL;
626 struct ifnet *ifs;
627 int error = 0;
629 ifs = ifunit(req->ifbr_ifsname);
630 if (ifs == NULL)
631 return (ENOENT);
633 if (sc->sc_if.if_mtu != ifs->if_mtu)
634 return (EINVAL);
636 if (ifs->if_bridge == sc)
637 return (EEXIST);
639 if (ifs->if_bridge != NULL)
640 return (EBUSY);
642 bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT);
643 if (bif == NULL)
644 return (ENOMEM);
646 switch (ifs->if_type) {
647 case IFT_ETHER:
649 * Place the interface into promiscuous mode.
651 error = ifpromisc(ifs, 1);
652 if (error)
653 goto out;
654 break;
655 default:
656 error = EINVAL;
657 goto out;
660 bif->bif_ifp = ifs;
661 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
662 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
663 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
665 ifs->if_bridge = sc;
666 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
668 if (sc->sc_if.if_flags & IFF_RUNNING)
669 bstp_initialization(sc);
670 else
671 bstp_stop(sc);
673 out:
674 if (error) {
675 if (bif != NULL)
676 free(bif, M_DEVBUF);
678 return (error);
681 static int
682 bridge_ioctl_del(struct bridge_softc *sc, void *arg)
684 struct ifbreq *req = arg;
685 struct bridge_iflist *bif;
687 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
688 if (bif == NULL)
689 return (ENOENT);
691 bridge_delete_member(sc, bif);
693 return (0);
696 static int
697 bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
699 struct ifbreq *req = arg;
700 struct bridge_iflist *bif;
702 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
703 if (bif == NULL)
704 return (ENOENT);
706 req->ifbr_ifsflags = bif->bif_flags;
707 req->ifbr_state = bif->bif_state;
708 req->ifbr_priority = bif->bif_priority;
709 req->ifbr_path_cost = bif->bif_path_cost;
710 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
712 return (0);
715 static int
716 bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
718 struct ifbreq *req = arg;
719 struct bridge_iflist *bif;
721 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
722 if (bif == NULL)
723 return (ENOENT);
725 if (req->ifbr_ifsflags & IFBIF_STP) {
726 switch (bif->bif_ifp->if_type) {
727 case IFT_ETHER:
728 /* These can do spanning tree. */
729 break;
731 default:
732 /* Nothing else can. */
733 return (EINVAL);
737 bif->bif_flags = req->ifbr_ifsflags;
739 if (sc->sc_if.if_flags & IFF_RUNNING)
740 bstp_initialization(sc);
742 return (0);
745 static int
746 bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
748 struct ifbrparam *param = arg;
750 sc->sc_brtmax = param->ifbrp_csize;
751 bridge_rttrim(sc);
753 return (0);
756 static int
757 bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
759 struct ifbrparam *param = arg;
761 param->ifbrp_csize = sc->sc_brtmax;
763 return (0);
766 static int
767 bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
769 struct ifbifconf *bifc = arg;
770 struct bridge_iflist *bif;
771 struct ifbreq breq;
772 int count, len, error = 0;
774 count = 0;
775 LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
776 count++;
778 if (bifc->ifbic_len == 0) {
779 bifc->ifbic_len = sizeof(breq) * count;
780 return (0);
783 count = 0;
784 len = bifc->ifbic_len;
785 memset(&breq, 0, sizeof breq);
786 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
787 if (len < sizeof(breq))
788 break;
790 strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname,
791 sizeof(breq.ifbr_ifsname));
792 breq.ifbr_ifsflags = bif->bif_flags;
793 breq.ifbr_state = bif->bif_state;
794 breq.ifbr_priority = bif->bif_priority;
795 breq.ifbr_path_cost = bif->bif_path_cost;
796 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
797 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
798 if (error)
799 break;
800 count++;
801 len -= sizeof(breq);
804 bifc->ifbic_len = sizeof(breq) * count;
805 return (error);
808 static int
809 bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
811 struct ifbaconf *bac = arg;
812 struct bridge_rtnode *brt;
813 struct ifbareq bareq;
814 int count = 0, error = 0, len;
816 if (bac->ifbac_len == 0)
817 return (0);
819 len = bac->ifbac_len;
820 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
821 if (len < sizeof(bareq))
822 goto out;
823 memset(&bareq, 0, sizeof(bareq));
824 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname,
825 sizeof(bareq.ifba_ifsname));
826 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
827 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
828 bareq.ifba_expire = brt->brt_expire - time_uptime;
829 } else
830 bareq.ifba_expire = 0;
831 bareq.ifba_flags = brt->brt_flags;
833 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
834 if (error)
835 goto out;
836 count++;
837 len -= sizeof(bareq);
839 out:
840 bac->ifbac_len = sizeof(bareq) * count;
841 return (error);
844 static int
845 bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
847 struct ifbareq *req = arg;
848 struct bridge_iflist *bif;
849 int error;
851 bif = bridge_lookup_member(sc, req->ifba_ifsname);
852 if (bif == NULL)
853 return (ENOENT);
855 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
856 req->ifba_flags);
858 return (error);
861 static int
862 bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
864 struct ifbrparam *param = arg;
866 sc->sc_brttimeout = param->ifbrp_ctime;
868 return (0);
871 static int
872 bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
874 struct ifbrparam *param = arg;
876 param->ifbrp_ctime = sc->sc_brttimeout;
878 return (0);
881 static int
882 bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
884 struct ifbareq *req = arg;
886 return (bridge_rtdaddr(sc, req->ifba_dst));
889 static int
890 bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
892 struct ifbreq *req = arg;
894 bridge_rtflush(sc, req->ifbr_ifsflags);
896 return (0);
899 static int
900 bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
902 struct ifbrparam *param = arg;
904 param->ifbrp_prio = sc->sc_bridge_priority;
906 return (0);
909 static int
910 bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
912 struct ifbrparam *param = arg;
914 sc->sc_bridge_priority = param->ifbrp_prio;
916 if (sc->sc_if.if_flags & IFF_RUNNING)
917 bstp_initialization(sc);
919 return (0);
922 static int
923 bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
925 struct ifbrparam *param = arg;
927 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
929 return (0);
932 static int
933 bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
935 struct ifbrparam *param = arg;
937 if (param->ifbrp_hellotime == 0)
938 return (EINVAL);
939 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
941 if (sc->sc_if.if_flags & IFF_RUNNING)
942 bstp_initialization(sc);
944 return (0);
947 static int
948 bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
950 struct ifbrparam *param = arg;
952 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
954 return (0);
957 static int
958 bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
960 struct ifbrparam *param = arg;
962 if (param->ifbrp_fwddelay == 0)
963 return (EINVAL);
964 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
966 if (sc->sc_if.if_flags & IFF_RUNNING)
967 bstp_initialization(sc);
969 return (0);
972 static int
973 bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
975 struct ifbrparam *param = arg;
977 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
979 return (0);
982 static int
983 bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
985 struct ifbrparam *param = arg;
987 if (param->ifbrp_maxage == 0)
988 return (EINVAL);
989 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
991 if (sc->sc_if.if_flags & IFF_RUNNING)
992 bstp_initialization(sc);
994 return (0);
997 static int
998 bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
1000 struct ifbreq *req = arg;
1001 struct bridge_iflist *bif;
1003 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
1004 if (bif == NULL)
1005 return (ENOENT);
1007 bif->bif_priority = req->ifbr_priority;
1009 if (sc->sc_if.if_flags & IFF_RUNNING)
1010 bstp_initialization(sc);
1012 return (0);
1015 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
1016 static int
1017 bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg)
1019 struct ifbrparam *param = arg;
1021 param->ifbrp_filter = sc->sc_filter_flags;
1023 return (0);
1026 static int
1027 bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg)
1029 struct ifbrparam *param = arg;
1030 uint32_t nflags, oflags;
1032 if (param->ifbrp_filter & ~IFBF_FILT_MASK)
1033 return (EINVAL);
1035 nflags = param->ifbrp_filter;
1036 oflags = sc->sc_filter_flags;
1038 if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) {
1039 pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1040 &sc->sc_if.if_pfil);
1042 if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) {
1043 pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1044 &sc->sc_if.if_pfil);
1047 sc->sc_filter_flags = nflags;
1049 return (0);
1051 #endif /* BRIDGE_IPF && PFIL_HOOKS */
1053 static int
1054 bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg)
1056 struct ifbreq *req = arg;
1057 struct bridge_iflist *bif;
1059 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
1060 if (bif == NULL)
1061 return (ENOENT);
1063 bif->bif_path_cost = req->ifbr_path_cost;
1065 if (sc->sc_if.if_flags & IFF_RUNNING)
1066 bstp_initialization(sc);
1068 return (0);
1072 * bridge_ifdetach:
1074 * Detach an interface from a bridge. Called when a member
1075 * interface is detaching.
1077 void
1078 bridge_ifdetach(struct ifnet *ifp)
1080 struct bridge_softc *sc = ifp->if_bridge;
1081 struct ifbreq breq;
1083 memset(&breq, 0, sizeof(breq));
1084 snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), ifp->if_xname);
1086 (void) bridge_ioctl_del(sc, &breq);
1090 * bridge_init:
1092 * Initialize a bridge interface.
1094 static int
1095 bridge_init(struct ifnet *ifp)
1097 struct bridge_softc *sc = ifp->if_softc;
1099 if (ifp->if_flags & IFF_RUNNING)
1100 return (0);
1102 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
1103 bridge_timer, sc);
1105 ifp->if_flags |= IFF_RUNNING;
1106 bstp_initialization(sc);
1107 return (0);
1111 * bridge_stop:
1113 * Stop the bridge interface.
1115 static void
1116 bridge_stop(struct ifnet *ifp, int disable)
1118 struct bridge_softc *sc = ifp->if_softc;
1120 if ((ifp->if_flags & IFF_RUNNING) == 0)
1121 return;
1123 callout_stop(&sc->sc_brcallout);
1124 bstp_stop(sc);
1126 IF_PURGE(&ifp->if_snd);
1128 bridge_rtflush(sc, IFBF_FLUSHDYN);
1130 ifp->if_flags &= ~IFF_RUNNING;
1134 * bridge_enqueue:
1136 * Enqueue a packet on a bridge member interface.
1138 * NOTE: must be called at splnet().
1140 void
1141 bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
1142 int runfilt)
1144 ALTQ_DECL(struct altq_pktattr pktattr;)
1145 int len, error;
1146 short mflags;
1149 * Clear any in-bound checksum flags for this packet.
1151 m->m_pkthdr.csum_flags = 0;
1153 #ifdef PFIL_HOOKS
1154 if (runfilt) {
1155 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m,
1156 dst_ifp, PFIL_OUT) != 0) {
1157 if (m != NULL)
1158 m_freem(m);
1159 return;
1161 if (m == NULL)
1162 return;
1164 #endif /* PFIL_HOOKS */
1166 #ifdef ALTQ
1168 * If ALTQ is enabled on the member interface, do
1169 * classification; the queueing discipline might
1170 * not require classification, but might require
1171 * the address family/header pointer in the pktattr.
1173 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) {
1174 /* XXX IFT_ETHER */
1175 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
1177 #endif /* ALTQ */
1179 len = m->m_pkthdr.len;
1180 m->m_flags |= M_PROTO1;
1181 mflags = m->m_flags;
1182 IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error);
1183 if (error) {
1184 /* mbuf is already freed */
1185 sc->sc_if.if_oerrors++;
1186 return;
1189 sc->sc_if.if_opackets++;
1190 sc->sc_if.if_obytes += len;
1192 dst_ifp->if_obytes += len;
1194 if (mflags & M_MCAST) {
1195 sc->sc_if.if_omcasts++;
1196 dst_ifp->if_omcasts++;
1199 if ((dst_ifp->if_flags & IFF_OACTIVE) == 0)
1200 (*dst_ifp->if_start)(dst_ifp);
1204 * bridge_output:
1206 * Send output from a bridge member interface. This
1207 * performs the bridging function for locally originated
1208 * packets.
1210 * The mbuf has the Ethernet header already attached. We must
1211 * enqueue or free the mbuf before returning.
1214 bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa,
1215 struct rtentry *rt)
1217 struct ether_header *eh;
1218 struct ifnet *dst_if;
1219 struct bridge_softc *sc;
1220 int s;
1222 if (m->m_len < ETHER_HDR_LEN) {
1223 m = m_pullup(m, ETHER_HDR_LEN);
1224 if (m == NULL)
1225 return (0);
1228 eh = mtod(m, struct ether_header *);
1229 sc = ifp->if_bridge;
1231 s = splnet();
1234 * If bridge is down, but the original output interface is up,
1235 * go ahead and send out that interface. Otherwise, the packet
1236 * is dropped below.
1238 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1239 dst_if = ifp;
1240 goto sendunicast;
1244 * If the packet is a multicast, or we don't know a better way to
1245 * get there, send to all interfaces.
1247 if (ETHER_IS_MULTICAST(eh->ether_dhost))
1248 dst_if = NULL;
1249 else
1250 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1251 if (dst_if == NULL) {
1252 struct bridge_iflist *bif;
1253 struct mbuf *mc;
1254 int used = 0;
1256 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1257 dst_if = bif->bif_ifp;
1258 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1259 continue;
1262 * If this is not the original output interface,
1263 * and the interface is participating in spanning
1264 * tree, make sure the port is in a state that
1265 * allows forwarding.
1267 if (dst_if != ifp &&
1268 (bif->bif_flags & IFBIF_STP) != 0) {
1269 switch (bif->bif_state) {
1270 case BSTP_IFSTATE_BLOCKING:
1271 case BSTP_IFSTATE_LISTENING:
1272 case BSTP_IFSTATE_DISABLED:
1273 continue;
1277 if (LIST_NEXT(bif, bif_next) == NULL) {
1278 used = 1;
1279 mc = m;
1280 } else {
1281 mc = m_copym(m, 0, M_COPYALL, M_NOWAIT);
1282 if (mc == NULL) {
1283 sc->sc_if.if_oerrors++;
1284 continue;
1288 bridge_enqueue(sc, dst_if, mc, 0);
1290 if (used == 0)
1291 m_freem(m);
1292 splx(s);
1293 return (0);
1296 sendunicast:
1298 * XXX Spanning tree consideration here?
1301 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1302 m_freem(m);
1303 splx(s);
1304 return (0);
1307 bridge_enqueue(sc, dst_if, m, 0);
1309 splx(s);
1310 return (0);
1314 * bridge_start:
1316 * Start output on a bridge.
1318 * NOTE: This routine should never be called in this implementation.
1320 static void
1321 bridge_start(struct ifnet *ifp)
1324 printf("%s: bridge_start() called\n", ifp->if_xname);
1328 * bridge_forward:
1330 * The forwarding function of the bridge.
1332 static void
1333 bridge_forward(void *v)
1335 struct bridge_softc *sc = v;
1336 struct mbuf *m;
1337 struct bridge_iflist *bif;
1338 struct ifnet *src_if, *dst_if;
1339 struct ether_header *eh;
1340 int s;
1342 mutex_enter(softnet_lock);
1343 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1344 mutex_exit(softnet_lock);
1345 return;
1348 s = splnet();
1349 while (1) {
1350 IFQ_POLL(&sc->sc_if.if_snd, m);
1351 if (m == NULL)
1352 break;
1353 IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
1355 src_if = m->m_pkthdr.rcvif;
1357 sc->sc_if.if_ipackets++;
1358 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1361 * Look up the bridge_iflist.
1363 bif = bridge_lookup_member_if(sc, src_if);
1364 if (bif == NULL) {
1365 /* Interface is not a bridge member (anymore?) */
1366 m_freem(m);
1367 continue;
1370 if (bif->bif_flags & IFBIF_STP) {
1371 switch (bif->bif_state) {
1372 case BSTP_IFSTATE_BLOCKING:
1373 case BSTP_IFSTATE_LISTENING:
1374 case BSTP_IFSTATE_DISABLED:
1375 m_freem(m);
1376 continue;
1380 eh = mtod(m, struct ether_header *);
1383 * If the interface is learning, and the source
1384 * address is valid and not multicast, record
1385 * the address.
1387 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1388 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1389 (eh->ether_shost[0] == 0 &&
1390 eh->ether_shost[1] == 0 &&
1391 eh->ether_shost[2] == 0 &&
1392 eh->ether_shost[3] == 0 &&
1393 eh->ether_shost[4] == 0 &&
1394 eh->ether_shost[5] == 0) == 0) {
1395 (void) bridge_rtupdate(sc, eh->ether_shost,
1396 src_if, 0, IFBAF_DYNAMIC);
1399 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1400 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1401 m_freem(m);
1402 continue;
1406 * At this point, the port either doesn't participate
1407 * in spanning tree or it is in the forwarding state.
1411 * If the packet is unicast, destined for someone on
1412 * "this" side of the bridge, drop it.
1414 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1415 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1416 if (src_if == dst_if) {
1417 m_freem(m);
1418 continue;
1420 } else {
1421 /* ...forward it to all interfaces. */
1422 sc->sc_if.if_imcasts++;
1423 dst_if = NULL;
1426 #ifdef PFIL_HOOKS
1427 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m,
1428 m->m_pkthdr.rcvif, PFIL_IN) != 0) {
1429 if (m != NULL)
1430 m_freem(m);
1431 continue;
1433 if (m == NULL)
1434 continue;
1435 #endif /* PFIL_HOOKS */
1437 if (dst_if == NULL) {
1438 bridge_broadcast(sc, src_if, m);
1439 continue;
1443 * At this point, we're dealing with a unicast frame
1444 * going to a different interface.
1446 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1447 m_freem(m);
1448 continue;
1450 bif = bridge_lookup_member_if(sc, dst_if);
1451 if (bif == NULL) {
1452 /* Not a member of the bridge (anymore?) */
1453 m_freem(m);
1454 continue;
1457 if (bif->bif_flags & IFBIF_STP) {
1458 switch (bif->bif_state) {
1459 case BSTP_IFSTATE_DISABLED:
1460 case BSTP_IFSTATE_BLOCKING:
1461 m_freem(m);
1462 continue;
1466 bridge_enqueue(sc, dst_if, m, 1);
1468 splx(s);
1469 mutex_exit(softnet_lock);
1473 * bridge_input:
1475 * Receive input from a member interface. Queue the packet for
1476 * bridging if it is not for us.
1477 * should be called at splnet()
1479 struct mbuf *
1480 bridge_input(struct ifnet *ifp, struct mbuf *m)
1482 struct bridge_softc *sc = ifp->if_bridge;
1483 struct bridge_iflist *bif;
1484 struct ether_header *eh;
1485 struct mbuf *mc;
1487 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1488 return (m);
1490 bif = bridge_lookup_member_if(sc, ifp);
1491 if (bif == NULL)
1492 return (m);
1494 eh = mtod(m, struct ether_header *);
1496 if (m->m_flags & (M_BCAST|M_MCAST)) {
1497 if (bif->bif_flags & IFBIF_STP) {
1498 /* Tap off 802.1D packets; they do not get forwarded. */
1499 if (memcmp(eh->ether_dhost, bstp_etheraddr,
1500 ETHER_ADDR_LEN) == 0) {
1501 m = bstp_input(sc, bif, m);
1502 if (m == NULL)
1503 return (NULL);
1506 switch (bif->bif_state) {
1507 case BSTP_IFSTATE_BLOCKING:
1508 case BSTP_IFSTATE_LISTENING:
1509 case BSTP_IFSTATE_DISABLED:
1510 return (m);
1515 * Make a deep copy of the packet and enqueue the copy
1516 * for bridge processing; return the original packet for
1517 * local processing.
1519 if (IF_QFULL(&sc->sc_if.if_snd)) {
1520 IF_DROP(&sc->sc_if.if_snd);
1521 return (m);
1523 mc = m_dup(m, 0, M_COPYALL, M_NOWAIT);
1524 if (mc == NULL)
1525 return (m);
1527 /* Perform the bridge forwarding function with the copy. */
1528 IF_ENQUEUE(&sc->sc_if.if_snd, mc);
1529 softint_schedule(sc->sc_softintr);
1531 /* Return the original packet for local processing. */
1532 return (m);
1535 if (bif->bif_flags & IFBIF_STP) {
1536 switch (bif->bif_state) {
1537 case BSTP_IFSTATE_BLOCKING:
1538 case BSTP_IFSTATE_LISTENING:
1539 case BSTP_IFSTATE_DISABLED:
1540 return (m);
1545 * Unicast. Make sure it's not for us.
1547 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1548 /* It is destined for us. */
1549 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost,
1550 ETHER_ADDR_LEN) == 0
1551 #if NCARP > 0
1552 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp,
1553 eh, IFT_ETHER, 0) != NULL)
1554 #endif /* NCARP > 0 */
1556 if (bif->bif_flags & IFBIF_LEARNING)
1557 (void) bridge_rtupdate(sc,
1558 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1559 m->m_pkthdr.rcvif = bif->bif_ifp;
1560 return (m);
1563 /* We just received a packet that we sent out. */
1564 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_shost,
1565 ETHER_ADDR_LEN) == 0
1566 #if NCARP > 0
1567 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp,
1568 eh, IFT_ETHER, 1) != NULL)
1569 #endif /* NCARP > 0 */
1571 m_freem(m);
1572 return (NULL);
1576 /* Perform the bridge forwarding function. */
1577 if (IF_QFULL(&sc->sc_if.if_snd)) {
1578 IF_DROP(&sc->sc_if.if_snd);
1579 m_freem(m);
1580 return (NULL);
1582 IF_ENQUEUE(&sc->sc_if.if_snd, m);
1583 softint_schedule(sc->sc_softintr);
1585 return (NULL);
1589 * bridge_broadcast:
1591 * Send a frame to all interfaces that are members of
1592 * the bridge, except for the one on which the packet
1593 * arrived.
1595 static void
1596 bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1597 struct mbuf *m)
1599 struct bridge_iflist *bif;
1600 struct mbuf *mc;
1601 struct ifnet *dst_if;
1602 int used = 0;
1604 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1605 dst_if = bif->bif_ifp;
1606 if (dst_if == src_if)
1607 continue;
1609 if (bif->bif_flags & IFBIF_STP) {
1610 switch (bif->bif_state) {
1611 case BSTP_IFSTATE_BLOCKING:
1612 case BSTP_IFSTATE_DISABLED:
1613 continue;
1617 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
1618 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
1619 continue;
1621 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1622 continue;
1624 if (LIST_NEXT(bif, bif_next) == NULL) {
1625 mc = m;
1626 used = 1;
1627 } else {
1628 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1629 if (mc == NULL) {
1630 sc->sc_if.if_oerrors++;
1631 continue;
1635 bridge_enqueue(sc, dst_if, mc, 1);
1637 if (used == 0)
1638 m_freem(m);
1642 * bridge_rtupdate:
1644 * Add a bridge routing entry.
1646 static int
1647 bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
1648 struct ifnet *dst_if, int setflags, uint8_t flags)
1650 struct bridge_rtnode *brt;
1651 int error, s;
1654 * A route for this destination might already exist. If so,
1655 * update it, otherwise create a new one.
1657 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) {
1658 if (sc->sc_brtcnt >= sc->sc_brtmax)
1659 return (ENOSPC);
1662 * Allocate a new bridge forwarding node, and
1663 * initialize the expiration time and Ethernet
1664 * address.
1666 s = splnet();
1667 brt = pool_get(&bridge_rtnode_pool, PR_NOWAIT);
1668 splx(s);
1669 if (brt == NULL)
1670 return (ENOMEM);
1672 memset(brt, 0, sizeof(*brt));
1673 brt->brt_expire = time_uptime + sc->sc_brttimeout;
1674 brt->brt_flags = IFBAF_DYNAMIC;
1675 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
1677 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
1678 s = splnet();
1679 pool_put(&bridge_rtnode_pool, brt);
1680 splx(s);
1681 return (error);
1685 brt->brt_ifp = dst_if;
1686 if (setflags) {
1687 brt->brt_flags = flags;
1688 if (flags & IFBAF_STATIC)
1689 brt->brt_expire = 0;
1690 else
1691 brt->brt_expire = time_uptime + sc->sc_brttimeout;
1694 return (0);
1698 * bridge_rtlookup:
1700 * Lookup the destination interface for an address.
1702 static struct ifnet *
1703 bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr)
1705 struct bridge_rtnode *brt;
1707 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1708 return (NULL);
1710 return (brt->brt_ifp);
1714 * bridge_rttrim:
1716 * Trim the routine table so that we have a number
1717 * of routing entries less than or equal to the
1718 * maximum number.
1720 static void
1721 bridge_rttrim(struct bridge_softc *sc)
1723 struct bridge_rtnode *brt, *nbrt;
1725 /* Make sure we actually need to do this. */
1726 if (sc->sc_brtcnt <= sc->sc_brtmax)
1727 return;
1729 /* Force an aging cycle; this might trim enough addresses. */
1730 bridge_rtage(sc);
1731 if (sc->sc_brtcnt <= sc->sc_brtmax)
1732 return;
1734 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1735 nbrt = LIST_NEXT(brt, brt_list);
1736 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1737 bridge_rtnode_destroy(sc, brt);
1738 if (sc->sc_brtcnt <= sc->sc_brtmax)
1739 return;
1745 * bridge_timer:
1747 * Aging timer for the bridge.
1749 static void
1750 bridge_timer(void *arg)
1752 struct bridge_softc *sc = arg;
1753 int s;
1755 s = splnet();
1756 bridge_rtage(sc);
1757 splx(s);
1759 if (sc->sc_if.if_flags & IFF_RUNNING)
1760 callout_reset(&sc->sc_brcallout,
1761 bridge_rtable_prune_period * hz, bridge_timer, sc);
1765 * bridge_rtage:
1767 * Perform an aging cycle.
1769 static void
1770 bridge_rtage(struct bridge_softc *sc)
1772 struct bridge_rtnode *brt, *nbrt;
1774 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1775 nbrt = LIST_NEXT(brt, brt_list);
1776 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1777 if (time_uptime >= brt->brt_expire)
1778 bridge_rtnode_destroy(sc, brt);
1784 * bridge_rtflush:
1786 * Remove all dynamic addresses from the bridge.
1788 static void
1789 bridge_rtflush(struct bridge_softc *sc, int full)
1791 struct bridge_rtnode *brt, *nbrt;
1793 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1794 nbrt = LIST_NEXT(brt, brt_list);
1795 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
1796 bridge_rtnode_destroy(sc, brt);
1801 * bridge_rtdaddr:
1803 * Remove an address from the table.
1805 static int
1806 bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr)
1808 struct bridge_rtnode *brt;
1810 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
1811 return (ENOENT);
1813 bridge_rtnode_destroy(sc, brt);
1814 return (0);
1818 * bridge_rtdelete:
1820 * Delete routes to a speicifc member interface.
1822 static void
1823 bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp)
1825 struct bridge_rtnode *brt, *nbrt;
1827 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
1828 nbrt = LIST_NEXT(brt, brt_list);
1829 if (brt->brt_ifp == ifp)
1830 bridge_rtnode_destroy(sc, brt);
1835 * bridge_rtable_init:
1837 * Initialize the route table for this bridge.
1839 static int
1840 bridge_rtable_init(struct bridge_softc *sc)
1842 int i;
1844 sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
1845 M_DEVBUF, M_NOWAIT);
1846 if (sc->sc_rthash == NULL)
1847 return (ENOMEM);
1849 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
1850 LIST_INIT(&sc->sc_rthash[i]);
1852 sc->sc_rthash_key = arc4random();
1854 LIST_INIT(&sc->sc_rtlist);
1856 return (0);
1860 * bridge_rtable_fini:
1862 * Deconstruct the route table for this bridge.
1864 static void
1865 bridge_rtable_fini(struct bridge_softc *sc)
1868 free(sc->sc_rthash, M_DEVBUF);
1872 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
1873 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1875 #define mix(a, b, c) \
1876 do { \
1877 a -= b; a -= c; a ^= (c >> 13); \
1878 b -= c; b -= a; b ^= (a << 8); \
1879 c -= a; c -= b; c ^= (b >> 13); \
1880 a -= b; a -= c; a ^= (c >> 12); \
1881 b -= c; b -= a; b ^= (a << 16); \
1882 c -= a; c -= b; c ^= (b >> 5); \
1883 a -= b; a -= c; a ^= (c >> 3); \
1884 b -= c; b -= a; b ^= (a << 10); \
1885 c -= a; c -= b; c ^= (b >> 15); \
1886 } while (/*CONSTCOND*/0)
1888 static inline uint32_t
1889 bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
1891 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
1893 b += addr[5] << 8;
1894 b += addr[4];
1895 a += addr[3] << 24;
1896 a += addr[2] << 16;
1897 a += addr[1] << 8;
1898 a += addr[0];
1900 mix(a, b, c);
1902 return (c & BRIDGE_RTHASH_MASK);
1905 #undef mix
1908 * bridge_rtnode_lookup:
1910 * Look up a bridge route node for the specified destination.
1912 static struct bridge_rtnode *
1913 bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
1915 struct bridge_rtnode *brt;
1916 uint32_t hash;
1917 int dir;
1919 hash = bridge_rthash(sc, addr);
1920 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
1921 dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN);
1922 if (dir == 0)
1923 return (brt);
1924 if (dir > 0)
1925 return (NULL);
1928 return (NULL);
1932 * bridge_rtnode_insert:
1934 * Insert the specified bridge node into the route table. We
1935 * assume the entry is not already in the table.
1937 static int
1938 bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
1940 struct bridge_rtnode *lbrt;
1941 uint32_t hash;
1942 int dir;
1944 hash = bridge_rthash(sc, brt->brt_addr);
1946 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
1947 if (lbrt == NULL) {
1948 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
1949 goto out;
1952 do {
1953 dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN);
1954 if (dir == 0)
1955 return (EEXIST);
1956 if (dir > 0) {
1957 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
1958 goto out;
1960 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
1961 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
1962 goto out;
1964 lbrt = LIST_NEXT(lbrt, brt_hash);
1965 } while (lbrt != NULL);
1967 #ifdef DIAGNOSTIC
1968 panic("bridge_rtnode_insert: impossible");
1969 #endif
1971 out:
1972 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
1973 sc->sc_brtcnt++;
1975 return (0);
1979 * bridge_rtnode_destroy:
1981 * Destroy a bridge rtnode.
1983 static void
1984 bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
1986 int s = splnet();
1988 LIST_REMOVE(brt, brt_hash);
1990 LIST_REMOVE(brt, brt_list);
1991 sc->sc_brtcnt--;
1992 pool_put(&bridge_rtnode_pool, brt);
1994 splx(s);
1997 #if defined(BRIDGE_IPF) && defined(PFIL_HOOKS)
1998 extern struct pfil_head inet_pfil_hook; /* XXX */
1999 extern struct pfil_head inet6_pfil_hook; /* XXX */
2002 * Send bridge packets through IPF if they are one of the types IPF can deal
2003 * with, or if they are ARP or REVARP. (IPF will pass ARP and REVARP without
2004 * question.)
2006 static int
2007 bridge_ipf(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
2009 int snap, error;
2010 struct ether_header *eh1, eh2;
2011 struct llc llc1;
2012 uint16_t ether_type;
2014 snap = 0;
2015 error = -1; /* Default error if not error == 0 */
2016 eh1 = mtod(*mp, struct ether_header *);
2017 ether_type = ntohs(eh1->ether_type);
2020 * Check for SNAP/LLC.
2022 if (ether_type < ETHERMTU) {
2023 struct llc *llc2 = (struct llc *)(eh1 + 1);
2025 if ((*mp)->m_len >= ETHER_HDR_LEN + 8 &&
2026 llc2->llc_dsap == LLC_SNAP_LSAP &&
2027 llc2->llc_ssap == LLC_SNAP_LSAP &&
2028 llc2->llc_control == LLC_UI) {
2029 ether_type = htons(llc2->llc_un.type_snap.ether_type);
2030 snap = 1;
2035 * If we're trying to filter bridge traffic, don't look at anything
2036 * other than IP and ARP traffic. If the filter doesn't understand
2037 * IPv6, don't allow IPv6 through the bridge either. This is lame
2038 * since if we really wanted, say, an AppleTalk filter, we are hosed,
2039 * but of course we don't have an AppleTalk filter to begin with.
2040 * (Note that since IPF doesn't understand ARP it will pass *ALL*
2041 * ARP traffic.)
2043 switch (ether_type) {
2044 case ETHERTYPE_ARP:
2045 case ETHERTYPE_REVARP:
2046 return 0; /* Automatically pass */
2047 case ETHERTYPE_IP:
2048 # ifdef INET6
2049 case ETHERTYPE_IPV6:
2050 # endif /* INET6 */
2051 break;
2052 default:
2053 goto bad;
2056 /* Strip off the Ethernet header and keep a copy. */
2057 m_copydata(*mp, 0, ETHER_HDR_LEN, (void *) &eh2);
2058 m_adj(*mp, ETHER_HDR_LEN);
2060 /* Strip off snap header, if present */
2061 if (snap) {
2062 m_copydata(*mp, 0, sizeof(struct llc), (void *) &llc1);
2063 m_adj(*mp, sizeof(struct llc));
2067 * Check basic packet sanity and run IPF through pfil.
2069 KASSERT(!cpu_intr_p());
2070 switch (ether_type)
2072 case ETHERTYPE_IP :
2073 error = (dir == PFIL_IN) ? bridge_ip_checkbasic(mp) : 0;
2074 if (error == 0)
2075 error = pfil_run_hooks(&inet_pfil_hook, mp, ifp, dir);
2076 break;
2077 # ifdef INET6
2078 case ETHERTYPE_IPV6 :
2079 error = (dir == PFIL_IN) ? bridge_ip6_checkbasic(mp) : 0;
2080 if (error == 0)
2081 error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp, dir);
2082 break;
2083 # endif
2084 default :
2085 error = 0;
2086 break;
2089 if (*mp == NULL)
2090 return error;
2091 if (error != 0)
2092 goto bad;
2094 error = -1;
2097 * Finally, put everything back the way it was and return
2099 if (snap) {
2100 M_PREPEND(*mp, sizeof(struct llc), M_DONTWAIT);
2101 if (*mp == NULL)
2102 return error;
2103 bcopy(&llc1, mtod(*mp, void *), sizeof(struct llc));
2106 M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT);
2107 if (*mp == NULL)
2108 return error;
2109 bcopy(&eh2, mtod(*mp, void *), ETHER_HDR_LEN);
2111 return 0;
2113 bad:
2114 m_freem(*mp);
2115 *mp = NULL;
2116 return error;
2120 * Perform basic checks on header size since
2121 * IPF assumes ip_input has already processed
2122 * it for it. Cut-and-pasted from ip_input.c.
2123 * Given how simple the IPv6 version is,
2124 * does the IPv4 version really need to be
2125 * this complicated?
2127 * XXX Should we update ipstat here, or not?
2128 * XXX Right now we update ipstat but not
2129 * XXX csum_counter.
2131 static int
2132 bridge_ip_checkbasic(struct mbuf **mp)
2134 struct mbuf *m = *mp;
2135 struct ip *ip;
2136 int len, hlen;
2138 if (*mp == NULL)
2139 return -1;
2141 if (IP_HDR_ALIGNED_P(mtod(m, void *)) == 0) {
2142 if ((m = m_copyup(m, sizeof(struct ip),
2143 (max_linkhdr + 3) & ~3)) == NULL) {
2144 /* XXXJRT new stat, please */
2145 ip_statinc(IP_STAT_TOOSMALL);
2146 goto bad;
2148 } else if (__predict_false(m->m_len < sizeof (struct ip))) {
2149 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
2150 ip_statinc(IP_STAT_TOOSMALL);
2151 goto bad;
2154 ip = mtod(m, struct ip *);
2155 if (ip == NULL) goto bad;
2157 if (ip->ip_v != IPVERSION) {
2158 ip_statinc(IP_STAT_BADVERS);
2159 goto bad;
2161 hlen = ip->ip_hl << 2;
2162 if (hlen < sizeof(struct ip)) { /* minimum header length */
2163 ip_statinc(IP_STAT_BADHLEN);
2164 goto bad;
2166 if (hlen > m->m_len) {
2167 if ((m = m_pullup(m, hlen)) == 0) {
2168 ip_statinc(IP_STAT_BADHLEN);
2169 goto bad;
2171 ip = mtod(m, struct ip *);
2172 if (ip == NULL) goto bad;
2175 switch (m->m_pkthdr.csum_flags &
2176 ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) |
2177 M_CSUM_IPv4_BAD)) {
2178 case M_CSUM_IPv4|M_CSUM_IPv4_BAD:
2179 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */
2180 goto bad;
2182 case M_CSUM_IPv4:
2183 /* Checksum was okay. */
2184 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); */
2185 break;
2187 default:
2188 /* Must compute it ourselves. */
2189 /* INET_CSUM_COUNTER_INCR(&ip_swcsum); */
2190 if (in_cksum(m, hlen) != 0)
2191 goto bad;
2192 break;
2195 /* Retrieve the packet length. */
2196 len = ntohs(ip->ip_len);
2199 * Check for additional length bogosity
2201 if (len < hlen) {
2202 ip_statinc(IP_STAT_BADLEN);
2203 goto bad;
2207 * Check that the amount of data in the buffers
2208 * is as at least much as the IP header would have us expect.
2209 * Drop packet if shorter than we expect.
2211 if (m->m_pkthdr.len < len) {
2212 ip_statinc(IP_STAT_TOOSHORT);
2213 goto bad;
2216 /* Checks out, proceed */
2217 *mp = m;
2218 return 0;
2220 bad:
2221 *mp = m;
2222 return -1;
2225 # ifdef INET6
2227 * Same as above, but for IPv6.
2228 * Cut-and-pasted from ip6_input.c.
2229 * XXX Should we update ip6stat, or not?
2231 static int
2232 bridge_ip6_checkbasic(struct mbuf **mp)
2234 struct mbuf *m = *mp;
2235 struct ip6_hdr *ip6;
2238 * If the IPv6 header is not aligned, slurp it up into a new
2239 * mbuf with space for link headers, in the event we forward
2240 * it. Otherwise, if it is aligned, make sure the entire base
2241 * IPv6 header is in the first mbuf of the chain.
2243 if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) {
2244 struct ifnet *inifp = m->m_pkthdr.rcvif;
2245 if ((m = m_copyup(m, sizeof(struct ip6_hdr),
2246 (max_linkhdr + 3) & ~3)) == NULL) {
2247 /* XXXJRT new stat, please */
2248 ip6_statinc(IP6_STAT_TOOSMALL);
2249 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2250 goto bad;
2252 } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
2253 struct ifnet *inifp = m->m_pkthdr.rcvif;
2254 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
2255 ip6_statinc(IP6_STAT_TOOSMALL);
2256 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2257 goto bad;
2261 ip6 = mtod(m, struct ip6_hdr *);
2263 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
2264 ip6_statinc(IP6_STAT_BADVERS);
2265 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
2266 goto bad;
2269 /* Checks out, proceed */
2270 *mp = m;
2271 return 0;
2273 bad:
2274 *mp = m;
2275 return -1;
2277 # endif /* INET6 */
2278 #endif /* BRIDGE_IPF && PFIL_HOOKS */