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