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