Adjust a couple of kmalloc calls to use M_WAITOK instead of M_RNOWAIT. It
[dragonfly.git] / sys / net / bridge / if_bridge.c
CommitLineData
ac93838f
SS
1/*
2 * Copyright 2001 Wasabi Systems, Inc.
3 * All rights reserved.
4 *
5 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the NetBSD Project by
18 * Wasabi Systems, Inc.
19 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
20 * or promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36/*
37 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by Jason L. Wright
51 * 4. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
56 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
57 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
59 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
60 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
62 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
63 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 *
66 * $OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp $
67 * $NetBSD: if_bridge.c,v 1.31 2005/06/01 19:45:34 jdc Exp $
68 * $FreeBSD: src/sys/net/if_bridge.c,v 1.26 2005/10/13 23:05:55 thompsa Exp $
6676e111 69 * $DragonFly: src/sys/net/bridge/if_bridge.c,v 1.16 2007/01/04 18:55:18 tgen Exp $
ac93838f
SS
70 */
71
72/*
73 * Network interface bridge support.
74 *
75 * TODO:
76 *
77 * - Currently only supports Ethernet-like interfaces (Ethernet,
78 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
79 * to bridge other types of interfaces (FDDI-FDDI, and maybe
80 * consider heterogenous bridges).
81 */
82
83#include <sys/cdefs.h>
84
85#include "opt_inet.h"
86#include "opt_inet6.h"
87
88#include <sys/param.h>
89#include <sys/mbuf.h>
90#include <sys/malloc.h>
91#include <sys/protosw.h>
92#include <sys/systm.h>
93#include <sys/time.h>
94#include <sys/socket.h> /* for net/if.h */
95#include <sys/sockio.h>
96#include <sys/ctype.h> /* string functions */
97#include <sys/kernel.h>
98#include <sys/random.h>
99#include <sys/sysctl.h>
100#include <sys/module.h>
101#include <sys/proc.h>
102#include <sys/lock.h>
103#include <sys/thread.h>
104#include <sys/thread2.h>
105#include <sys/mpipe.h>
106
107#include <net/bpf.h>
108#include <net/if.h>
109#include <net/if_dl.h>
110#include <net/if_types.h>
111#include <net/if_var.h>
112#include <net/pfil.h>
113#include <net/ifq_var.h>
114
115#include <netinet/in.h> /* for struct arpcom */
116#include <netinet/in_systm.h>
117#include <netinet/in_var.h>
118#include <netinet/ip.h>
119#include <netinet/ip_var.h>
120#ifdef INET6
121#include <netinet/ip6.h>
122#include <netinet6/ip6_var.h>
123#endif
124#include <netinet/if_ether.h> /* for struct arpcom */
125#include <net/bridge/if_bridgevar.h>
126#include <net/if_llc.h>
127
128#include <net/route.h>
129#include <sys/in_cksum.h>
130
131/*
132 * Size of the route hash table. Must be a power of two.
133 */
134#ifndef BRIDGE_RTHASH_SIZE
135#define BRIDGE_RTHASH_SIZE 1024
136#endif
137
138#define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
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
d217f5e5
SU
172/*
173 * List of capabilities to mask on the member interface.
174 */
175#define BRIDGE_IFCAPS_MASK IFCAP_TXCSUM
176
177eventhandler_tag bridge_detach_cookie = NULL;
178
ac93838f
SS
179extern struct mbuf *(*bridge_input_p)(struct ifnet *, struct mbuf *);
180extern int (*bridge_output_p)(struct ifnet *, struct mbuf *,
181 struct sockaddr *, struct rtentry *);
182extern void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
ac93838f 183
d217f5e5 184static int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
ac93838f 185
d217f5e5
SU
186static int bridge_clone_create(struct if_clone *, int);
187static void bridge_clone_destroy(struct ifnet *);
ac93838f 188
d217f5e5
SU
189static int bridge_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
190static void bridge_mutecaps(struct bridge_iflist *, int);
191static void bridge_ifdetach(void *arg __unused, struct ifnet *);
ac93838f 192static void bridge_init(void *);
d217f5e5
SU
193static void bridge_stop(struct ifnet *, int);
194static void bridge_start(struct ifnet *);
195static struct mbuf *bridge_input(struct ifnet *, struct mbuf *);
196static int bridge_output_serialized(struct ifnet *, struct mbuf *,
197 struct sockaddr *, struct rtentry *);
198
199static void bridge_forward(struct bridge_softc *, struct mbuf *m);
200
201static void bridge_timer(void *);
202
203static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
204 struct mbuf *, int);
205static void bridge_span(struct bridge_softc *, struct mbuf *);
206
207static int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
208 struct ifnet *, int, uint8_t);
209static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *);
210static void bridge_rttrim(struct bridge_softc *);
211static void bridge_rtage(struct bridge_softc *);
212static void bridge_rtflush(struct bridge_softc *, int);
213static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
214
215static int bridge_rtable_init(struct bridge_softc *);
216static void bridge_rtable_fini(struct bridge_softc *);
217
218static int bridge_rtnode_addr_cmp(const uint8_t *, const uint8_t *);
219static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
220 const uint8_t *);
221static int bridge_rtnode_insert(struct bridge_softc *,
222 struct bridge_rtnode *);
223static void bridge_rtnode_destroy(struct bridge_softc *,
224 struct bridge_rtnode *);
225
226static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
227 const char *name);
228static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
229 struct ifnet *ifp);
230static void bridge_delete_member(struct bridge_softc *,
231 struct bridge_iflist *, int);
232static void bridge_delete_span(struct bridge_softc *,
233 struct bridge_iflist *);
234
235static int bridge_ioctl_add(struct bridge_softc *, void *);
236static int bridge_ioctl_del(struct bridge_softc *, void *);
237static int bridge_ioctl_gifflags(struct bridge_softc *, void *);
238static int bridge_ioctl_sifflags(struct bridge_softc *, void *);
239static int bridge_ioctl_scache(struct bridge_softc *, void *);
240static int bridge_ioctl_gcache(struct bridge_softc *, void *);
241static int bridge_ioctl_gifs(struct bridge_softc *, void *);
242static int bridge_ioctl_rts(struct bridge_softc *, void *);
243static int bridge_ioctl_saddr(struct bridge_softc *, void *);
244static int bridge_ioctl_sto(struct bridge_softc *, void *);
245static int bridge_ioctl_gto(struct bridge_softc *, void *);
246static int bridge_ioctl_daddr(struct bridge_softc *, void *);
247static int bridge_ioctl_flush(struct bridge_softc *, void *);
248static int bridge_ioctl_gpri(struct bridge_softc *, void *);
249static int bridge_ioctl_spri(struct bridge_softc *, void *);
250static int bridge_ioctl_ght(struct bridge_softc *, void *);
251static int bridge_ioctl_sht(struct bridge_softc *, void *);
252static int bridge_ioctl_gfd(struct bridge_softc *, void *);
253static int bridge_ioctl_sfd(struct bridge_softc *, void *);
254static int bridge_ioctl_gma(struct bridge_softc *, void *);
255static int bridge_ioctl_sma(struct bridge_softc *, void *);
256static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
257static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
258static int bridge_ioctl_addspan(struct bridge_softc *, void *);
259static int bridge_ioctl_delspan(struct bridge_softc *, void *);
260static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *,
261 int);
262static int bridge_ip_checkbasic(struct mbuf **mp);
263#ifdef INET6
264static int bridge_ip6_checkbasic(struct mbuf **mp);
265#endif /* INET6 */
266static int bridge_fragment(struct ifnet *, struct mbuf *,
267 struct ether_header *, int, struct llc *);
ac93838f
SS
268
269SYSCTL_DECL(_net_link);
270SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge");
271
d217f5e5 272static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */
ac93838f
SS
273static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */
274static int pfil_member = 1; /* run pfil hooks on the member interface */
d217f5e5
SU
275SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW,
276 &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled");
ac93838f
SS
277SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW,
278 &pfil_bridge, 0, "Packet filter on the bridge interface");
279SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW,
280 &pfil_member, 0, "Packet filter on the member interface");
281
282struct bridge_control {
283 int (*bc_func)(struct bridge_softc *, void *);
284 int bc_argsize;
285 int bc_flags;
286};
287
288#define BC_F_COPYIN 0x01 /* copy arguments in */
289#define BC_F_COPYOUT 0x02 /* copy arguments out */
290#define BC_F_SUSER 0x04 /* do super-user check */
291
292const struct bridge_control bridge_control_table[] = {
293 { bridge_ioctl_add, sizeof(struct ifbreq),
294 BC_F_COPYIN|BC_F_SUSER },
295 { bridge_ioctl_del, sizeof(struct ifbreq),
296 BC_F_COPYIN|BC_F_SUSER },
297
298 { bridge_ioctl_gifflags, sizeof(struct ifbreq),
299 BC_F_COPYIN|BC_F_COPYOUT },
300 { bridge_ioctl_sifflags, sizeof(struct ifbreq),
301 BC_F_COPYIN|BC_F_SUSER },
302
303 { bridge_ioctl_scache, sizeof(struct ifbrparam),
304 BC_F_COPYIN|BC_F_SUSER },
305 { bridge_ioctl_gcache, sizeof(struct ifbrparam),
306 BC_F_COPYOUT },
307
308 { bridge_ioctl_gifs, sizeof(struct ifbifconf),
309 BC_F_COPYIN|BC_F_COPYOUT },
310 { bridge_ioctl_rts, sizeof(struct ifbaconf),
311 BC_F_COPYIN|BC_F_COPYOUT },
312
313 { bridge_ioctl_saddr, sizeof(struct ifbareq),
314 BC_F_COPYIN|BC_F_SUSER },
315
316 { bridge_ioctl_sto, sizeof(struct ifbrparam),
317 BC_F_COPYIN|BC_F_SUSER },
318 { bridge_ioctl_gto, sizeof(struct ifbrparam),
319 BC_F_COPYOUT },
320
321 { bridge_ioctl_daddr, sizeof(struct ifbareq),
322 BC_F_COPYIN|BC_F_SUSER },
323
324 { bridge_ioctl_flush, sizeof(struct ifbreq),
325 BC_F_COPYIN|BC_F_SUSER },
326
327 { bridge_ioctl_gpri, sizeof(struct ifbrparam),
328 BC_F_COPYOUT },
329 { bridge_ioctl_spri, sizeof(struct ifbrparam),
330 BC_F_COPYIN|BC_F_SUSER },
331
332 { bridge_ioctl_ght, sizeof(struct ifbrparam),
333 BC_F_COPYOUT },
334 { bridge_ioctl_sht, sizeof(struct ifbrparam),
335 BC_F_COPYIN|BC_F_SUSER },
336
337 { bridge_ioctl_gfd, sizeof(struct ifbrparam),
338 BC_F_COPYOUT },
339 { bridge_ioctl_sfd, sizeof(struct ifbrparam),
340 BC_F_COPYIN|BC_F_SUSER },
341
342 { bridge_ioctl_gma, sizeof(struct ifbrparam),
343 BC_F_COPYOUT },
344 { bridge_ioctl_sma, sizeof(struct ifbrparam),
345 BC_F_COPYIN|BC_F_SUSER },
346
347 { bridge_ioctl_sifprio, sizeof(struct ifbreq),
348 BC_F_COPYIN|BC_F_SUSER },
349
350 { bridge_ioctl_sifcost, sizeof(struct ifbreq),
351 BC_F_COPYIN|BC_F_SUSER },
d217f5e5
SU
352
353 { bridge_ioctl_addspan, sizeof(struct ifbreq),
354 BC_F_COPYIN|BC_F_SUSER },
355 { bridge_ioctl_delspan, sizeof(struct ifbreq),
356 BC_F_COPYIN|BC_F_SUSER },
ac93838f
SS
357};
358const int bridge_control_table_size =
359 sizeof(bridge_control_table) / sizeof(bridge_control_table[0]);
360
ac93838f
SS
361LIST_HEAD(, bridge_softc) bridge_list;
362
363struct if_clone bridge_cloner = IF_CLONE_INITIALIZER("bridge",
d217f5e5 364 bridge_clone_create,
ac93838f
SS
365 bridge_clone_destroy, 0, IF_MAXUNIT);
366
367static int
368bridge_modevent(module_t mod, int type, void *data)
369{
370
371 switch (type) {
372 case MOD_LOAD:
373 LIST_INIT(&bridge_list);
374 if_clone_attach(&bridge_cloner);
375 bridge_input_p = bridge_input;
376 bridge_output_p = bridge_output_serialized;
d217f5e5
SU
377 bridge_detach_cookie = EVENTHANDLER_REGISTER(
378 ifnet_detach_event, bridge_ifdetach, NULL,
379 EVENTHANDLER_PRI_ANY);
ac93838f 380#if notyet
ac93838f
SS
381 bstp_linkstate_p = bstp_linkstate;
382#endif
383 break;
384 case MOD_UNLOAD:
385 if (!LIST_EMPTY(&bridge_list))
d217f5e5
SU
386 return (EBUSY);
387 EVENTHANDLER_DEREGISTER(ifnet_detach_event,
388 bridge_detach_cookie);
ac93838f
SS
389 if_clone_detach(&bridge_cloner);
390 bridge_input_p = NULL;
391 bridge_output_p = NULL;
392#if notyet
ac93838f
SS
393 bstp_linkstate_p = NULL;
394#endif
395 break;
396 default:
d217f5e5 397 return (EOPNOTSUPP);
ac93838f 398 }
d217f5e5 399 return (0);
ac93838f
SS
400}
401
402static moduledata_t bridge_mod = {
d217f5e5
SU
403 "if_bridge",
404 bridge_modevent,
ac93838f
SS
405 0
406};
407
408DECLARE_MODULE(if_bridge, bridge_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
409
410
411/*
412 * bridge_clone_create:
413 *
414 * Create a new bridge instance.
415 */
d217f5e5 416static int
ac93838f
SS
417bridge_clone_create(struct if_clone *ifc, int unit)
418{
419 struct bridge_softc *sc;
420 struct ifnet *ifp;
421 u_char eaddr[6];
422
efda3bd0 423 sc = kmalloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
ac93838f
SS
424 ifp = sc->sc_ifp = &sc->sc_if;
425
426 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
427 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
428 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
429 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
430 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
431 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
432 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
433
434 /* Initialize our routing table. */
435 bridge_rtable_init(sc);
436
437 callout_init(&sc->sc_brcallout);
438 callout_init(&sc->sc_bstpcallout);
439
440 LIST_INIT(&sc->sc_iflist);
d217f5e5 441 LIST_INIT(&sc->sc_spanlist);
ac93838f
SS
442
443 ifp->if_softc = sc;
444 if_initname(ifp, ifc->ifc_name, unit);
445 ifp->if_mtu = ETHERMTU;
d217f5e5 446 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
ac93838f
SS
447 ifp->if_ioctl = bridge_ioctl;
448 ifp->if_start = bridge_start;
449 ifp->if_init = bridge_init;
450 ifp->if_type = IFT_BRIDGE;
451 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
452 ifp->if_snd.ifq_maxlen = ifqmaxlen;
453 ifq_set_ready(&ifp->if_snd);
454 ifp->if_hdrlen = ETHER_HDR_LEN;
455
456 /*
457 * Generate a random ethernet address and use the private AC:DE:48
458 * OUI code.
459 */
460 {
0ced1954 461 int rnd = karc4random();
d217f5e5 462 bcopy(&rnd, &eaddr[0], 4); /* ETHER_ADDR_LEN == 6 */
0ced1954 463 rnd = karc4random();
ac93838f
SS
464 bcopy(&rnd, &eaddr[2], 4); /* ETHER_ADDR_LEN == 6 */
465 }
d217f5e5
SU
466 eaddr[0] &= ~1; /* clear multicast bit */
467 eaddr[0] |= 2; /* set the LAA bit */
ac93838f
SS
468
469 ether_ifattach(ifp, eaddr, NULL);
470 /* Now undo some of the damage... */
471 ifp->if_baudrate = 0;
472 ifp->if_type = IFT_BRIDGE;
473
474 crit_enter();
475 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
476 crit_exit();
477
478 return (0);
479}
480
481/*
482 * bridge_clone_destroy:
483 *
484 * Destroy a bridge instance.
485 */
d217f5e5 486static void
ac93838f
SS
487bridge_clone_destroy(struct ifnet *ifp)
488{
489 struct bridge_softc *sc = ifp->if_softc;
490 struct bridge_iflist *bif;
491
492 lwkt_serialize_enter(ifp->if_serializer);
493
494 bridge_stop(ifp, 1);
495 ifp->if_flags &= ~IFF_UP;
496
497 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL)
d217f5e5
SU
498 bridge_delete_member(sc, bif, 0);
499
500 while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) {
501 bridge_delete_span(sc, bif);
502 }
ac93838f
SS
503
504 callout_stop(&sc->sc_brcallout);
505 callout_stop(&sc->sc_bstpcallout);
506
507 lwkt_serialize_exit(ifp->if_serializer);
508
509 crit_enter();
510 LIST_REMOVE(sc, sc_list);
511 crit_exit();
512
513 ether_ifdetach(ifp);
514
ac93838f
SS
515 /* Tear down the routing table. */
516 bridge_rtable_fini(sc);
517
efda3bd0 518 kfree(sc, M_DEVBUF);
ac93838f
SS
519}
520
521/*
522 * bridge_ioctl:
523 *
524 * Handle a control request from the operator.
525 */
d217f5e5 526static int
ac93838f
SS
527bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
528{
529 struct bridge_softc *sc = ifp->if_softc;
530 struct thread *td = curthread;
531 union {
532 struct ifbreq ifbreq;
533 struct ifbifconf ifbifconf;
534 struct ifbareq ifbareq;
535 struct ifbaconf ifbaconf;
536 struct ifbrparam ifbrparam;
537 } args;
538 struct ifdrv *ifd = (struct ifdrv *) data;
539 const struct bridge_control *bc;
540 int error = 0;
541
542 switch (cmd) {
543
544 case SIOCADDMULTI:
545 case SIOCDELMULTI:
546 break;
547
548 case SIOCGDRVSPEC:
549 case SIOCSDRVSPEC:
550 if (ifd->ifd_cmd >= bridge_control_table_size) {
551 error = EINVAL;
552 break;
553 }
554 bc = &bridge_control_table[ifd->ifd_cmd];
555
556 if (cmd == SIOCGDRVSPEC &&
557 (bc->bc_flags & BC_F_COPYOUT) == 0) {
558 error = EINVAL;
559 break;
560 }
561 else if (cmd == SIOCSDRVSPEC &&
562 (bc->bc_flags & BC_F_COPYOUT) != 0) {
563 error = EINVAL;
564 break;
565 }
566
567 if (bc->bc_flags & BC_F_SUSER) {
568 error = suser(td);
569 if (error)
570 break;
571 }
572
573 if (ifd->ifd_len != bc->bc_argsize ||
574 ifd->ifd_len > sizeof(args)) {
575 error = EINVAL;
576 break;
577 }
578
60d8d1d3 579 memset(&args, 0, sizeof(args));
ac93838f
SS
580 if (bc->bc_flags & BC_F_COPYIN) {
581 error = copyin(ifd->ifd_data, &args, ifd->ifd_len);
582 if (error)
583 break;
584 }
585
586 error = (*bc->bc_func)(sc, &args);
587 if (error)
588 break;
589
590 if (bc->bc_flags & BC_F_COPYOUT)
591 error = copyout(&args, ifd->ifd_data, ifd->ifd_len);
592
593 break;
594
595 case SIOCSIFFLAGS:
596 if (!(ifp->if_flags & IFF_UP) &&
597 (ifp->if_flags & IFF_RUNNING)) {
598 /*
599 * If interface is marked down and it is running,
600 * then stop and disable it.
601 */
602 bridge_stop(ifp, 1);
603 } else if ((ifp->if_flags & IFF_UP) &&
604 !(ifp->if_flags & IFF_RUNNING)) {
605 /*
606 * If interface is marked up and it is stopped, then
607 * start it.
608 */
609 (*ifp->if_init)(sc);
610 }
611 break;
612
613 case SIOCSIFMTU:
614 /* Do not allow the MTU to be changed on the bridge */
615 error = EINVAL;
616 break;
617
618 default:
d217f5e5 619 /*
ac93838f
SS
620 * drop the lock as ether_ioctl() will call bridge_start() and
621 * cause the lock to be recursed.
622 */
623 error = ether_ioctl(ifp, cmd, data);
624 break;
625 }
626
627 return (error);
628}
629
d217f5e5
SU
630/*
631 * bridge_mutecaps:
632 *
633 * Clear or restore unwanted capabilities on the member interface
634 */
635static void
636bridge_mutecaps(struct bridge_iflist *bif, int mute)
637{
638 struct ifnet *ifp = bif->bif_ifp;
639 struct ifreq ifr;
640 int error;
641
642 if (ifp->if_ioctl == NULL)
643 return;
644
645 bzero(&ifr, sizeof(ifr));
646 ifr.ifr_reqcap = ifp->if_capenable;
647
648 if (mute) {
649 /* mask off and save capabilities */
650 bif->bif_mutecap = ifr.ifr_reqcap & BRIDGE_IFCAPS_MASK;
651 if (bif->bif_mutecap != 0)
652 ifr.ifr_reqcap &= ~BRIDGE_IFCAPS_MASK;
653 } else
654 /* restore muted capabilities */
655 ifr.ifr_reqcap |= bif->bif_mutecap;
656
657 if (bif->bif_mutecap != 0) {
658 lwkt_serialize_enter(ifp->if_serializer);
659 error = (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr, NULL);
660 lwkt_serialize_exit(ifp->if_serializer);
661 }
662}
663
ac93838f
SS
664/*
665 * bridge_lookup_member:
666 *
667 * Lookup a bridge member interface.
668 */
d217f5e5 669static struct bridge_iflist *
ac93838f
SS
670bridge_lookup_member(struct bridge_softc *sc, const char *name)
671{
672 struct bridge_iflist *bif;
673 struct ifnet *ifp;
674
675 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
676 ifp = bif->bif_ifp;
677 if (strcmp(ifp->if_xname, name) == 0)
678 return (bif);
679 }
680
681 return (NULL);
682}
683
684/*
685 * bridge_lookup_member_if:
686 *
687 * Lookup a bridge member interface by ifnet*.
688 */
d217f5e5 689static struct bridge_iflist *
ac93838f
SS
690bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp)
691{
692 struct bridge_iflist *bif;
693
694 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
695 if (bif->bif_ifp == member_ifp)
696 return (bif);
697 }
698
699 return (NULL);
700}
701
702/*
703 * bridge_delete_member:
704 *
705 * Delete the specified member interface.
706 */
d217f5e5
SU
707static void
708bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
709 int gone)
ac93838f
SS
710{
711 struct ifnet *ifs = bif->bif_ifp;
712
d217f5e5
SU
713 if (!gone) {
714 switch (ifs->if_type) {
715 case IFT_ETHER:
716 case IFT_L2VLAN:
717 /*
718 * Take the interface out of promiscuous mode.
719 */
720 (void) ifpromisc(ifs, 0);
721 bridge_mutecaps(bif, 0);
722 break;
ac93838f 723
d217f5e5
SU
724 case IFT_GIF:
725 break;
ac93838f 726
d217f5e5 727 default:
ac93838f 728#ifdef DIAGNOSTIC
d217f5e5 729 panic("bridge_delete_member: impossible");
ac93838f 730#endif
d217f5e5
SU
731 break;
732 }
ac93838f
SS
733 }
734
735 ifs->if_bridge = NULL;
ac93838f
SS
736 LIST_REMOVE(bif, bif_next);
737
738 bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
739
efda3bd0 740 kfree(bif, M_DEVBUF);
ac93838f
SS
741
742 if (sc->sc_ifp->if_flags & IFF_RUNNING)
743 bstp_initialization(sc);
744}
745
d217f5e5
SU
746/*
747 * bridge_delete_span:
748 *
749 * Delete the specified span interface.
750 */
751static void
752bridge_delete_span(struct bridge_softc *sc, struct bridge_iflist *bif)
753{
754 KASSERT(bif->bif_ifp->if_bridge == NULL,
755 ("%s: not a span interface", __func__));
756
757 LIST_REMOVE(bif, bif_next);
efda3bd0 758 kfree(bif, M_DEVBUF);
d217f5e5
SU
759}
760
761static int
ac93838f
SS
762bridge_ioctl_add(struct bridge_softc *sc, void *arg)
763{
764 struct ifbreq *req = arg;
765 struct bridge_iflist *bif = NULL;
766 struct ifnet *ifs;
767 int error = 0;
768
769 ifs = ifunit(req->ifbr_ifsname);
770 if (ifs == NULL)
771 return (ENOENT);
772
d217f5e5
SU
773 /* If it's in the span list, it can't be a member. */
774 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
775 if (ifs == bif->bif_ifp)
776 return (EBUSY);
777
778 /* Allow the first Ethernet member to define the MTU */
779 if (ifs->if_type != IFT_GIF) {
780 if (LIST_EMPTY(&sc->sc_iflist))
781 sc->sc_ifp->if_mtu = ifs->if_mtu;
782 else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
783 if_printf(sc->sc_ifp, "invalid MTU for %s\n",
784 ifs->if_xname);
785 return (EINVAL);
786 }
ac93838f
SS
787 }
788
789 if (ifs->if_bridge == sc)
790 return (EEXIST);
791
792 if (ifs->if_bridge != NULL)
793 return (EBUSY);
794
6676e111 795 bif = kmalloc(sizeof(*bif), M_DEVBUF, M_WAITOK|M_ZERO);
ac93838f
SS
796 if (bif == NULL)
797 return (ENOMEM);
798
d217f5e5
SU
799 bif->bif_ifp = ifs;
800 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
801 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
802 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
803
ac93838f
SS
804 switch (ifs->if_type) {
805 case IFT_ETHER:
806 case IFT_L2VLAN:
807 /*
808 * Place the interface into promiscuous mode.
809 */
810 error = ifpromisc(ifs, 1);
811 if (error)
812 goto out;
d217f5e5
SU
813
814 bridge_mutecaps(bif, 1);
ac93838f
SS
815 break;
816
817 case IFT_GIF: /* :^) */
818 break;
819
820 default:
821 error = EINVAL;
822 goto out;
823 }
824
ac93838f
SS
825 ifs->if_bridge = sc;
826
827 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next);
828
829 if (sc->sc_ifp->if_flags & IFF_RUNNING)
830 bstp_initialization(sc);
831 else
832 bstp_stop(sc);
833
d217f5e5 834out:
ac93838f
SS
835 if (error) {
836 if (bif != NULL)
efda3bd0 837 kfree(bif, M_DEVBUF);
ac93838f
SS
838 }
839 return (error);
840}
841
d217f5e5 842static int
ac93838f
SS
843bridge_ioctl_del(struct bridge_softc *sc, void *arg)
844{
845 struct ifbreq *req = arg;
846 struct bridge_iflist *bif;
847
848 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
849 if (bif == NULL)
850 return (ENOENT);
851
d217f5e5 852 bridge_delete_member(sc, bif, 0);
ac93838f
SS
853
854 return (0);
855}
856
d217f5e5 857static int
ac93838f
SS
858bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
859{
860 struct ifbreq *req = arg;
861 struct bridge_iflist *bif;
862
863 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
864 if (bif == NULL)
865 return (ENOENT);
866
867 req->ifbr_ifsflags = bif->bif_flags;
868 req->ifbr_state = bif->bif_state;
869 req->ifbr_priority = bif->bif_priority;
870 req->ifbr_path_cost = bif->bif_path_cost;
871 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
872
873 return (0);
874}
875
d217f5e5 876static int
ac93838f
SS
877bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
878{
879 struct ifbreq *req = arg;
880 struct bridge_iflist *bif;
881
882 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
883 if (bif == NULL)
884 return (ENOENT);
885
d217f5e5
SU
886 if (req->ifbr_ifsflags & IFBIF_SPAN)
887 /* SPAN is readonly */
888 return (EINVAL);
889
ac93838f
SS
890 if (req->ifbr_ifsflags & IFBIF_STP) {
891 switch (bif->bif_ifp->if_type) {
892 case IFT_ETHER:
893 /* These can do spanning tree. */
894 break;
895
896 default:
897 /* Nothing else can. */
898 return (EINVAL);
899 }
900 }
901
902 bif->bif_flags = req->ifbr_ifsflags;
903
904 if (sc->sc_ifp->if_flags & IFF_RUNNING)
905 bstp_initialization(sc);
906
907 return (0);
908}
909
d217f5e5 910static int
ac93838f
SS
911bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
912{
913 struct ifbrparam *param = arg;
914
915 sc->sc_brtmax = param->ifbrp_csize;
916 bridge_rttrim(sc);
917
918 return (0);
919}
920
d217f5e5 921static int
ac93838f
SS
922bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
923{
924 struct ifbrparam *param = arg;
925
926 param->ifbrp_csize = sc->sc_brtmax;
927
928 return (0);
929}
930
d217f5e5 931static int
ac93838f
SS
932bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
933{
934 struct ifbifconf *bifc = arg;
935 struct bridge_iflist *bif;
936 struct ifbreq breq;
937 int count, len, error = 0;
938
939 count = 0;
940 LIST_FOREACH(bif, &sc->sc_iflist, bif_next)
941 count++;
d217f5e5
SU
942 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
943 count++;
ac93838f
SS
944
945 if (bifc->ifbic_len == 0) {
946 bifc->ifbic_len = sizeof(breq) * count;
947 return (0);
948 }
949
950 count = 0;
951 len = bifc->ifbic_len;
60d8d1d3 952 memset(&breq, 0, sizeof breq);
ac93838f
SS
953 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
954 if (len < sizeof(breq))
955 break;
956
957 strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname,
958 sizeof(breq.ifbr_ifsname));
959 breq.ifbr_ifsflags = bif->bif_flags;
960 breq.ifbr_state = bif->bif_state;
961 breq.ifbr_priority = bif->bif_priority;
962 breq.ifbr_path_cost = bif->bif_path_cost;
963 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
964 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
965 if (error)
966 break;
967 count++;
968 len -= sizeof(breq);
969 }
d217f5e5
SU
970 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) {
971 if (len < sizeof(breq))
972 break;
973
974 strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname,
975 sizeof(breq.ifbr_ifsname));
976 breq.ifbr_ifsflags = bif->bif_flags;
977 breq.ifbr_state = bif->bif_state;
978 breq.ifbr_priority = bif->bif_priority;
979 breq.ifbr_path_cost = bif->bif_path_cost;
980 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff;
981 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq));
982 if (error)
983 break;
984 count++;
985 len -= sizeof(breq);
986 }
ac93838f
SS
987
988 bifc->ifbic_len = sizeof(breq) * count;
989 return (error);
990}
991
d217f5e5 992static int
ac93838f
SS
993bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
994{
995 struct ifbaconf *bac = arg;
996 struct bridge_rtnode *brt;
997 struct ifbareq bareq;
998 int count = 0, error = 0, len;
999
1000 if (bac->ifbac_len == 0)
1001 return (0);
1002
1003 len = bac->ifbac_len;
d217f5e5 1004 memset(&bareq, 0, sizeof(bareq));
ac93838f
SS
1005 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
1006 if (len < sizeof(bareq))
1007 goto out;
1008 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname,
1009 sizeof(bareq.ifba_ifsname));
1010 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
1011 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC &&
1012 time_second < brt->brt_expire)
1013 bareq.ifba_expire = brt->brt_expire - time_second;
1014 else
1015 bareq.ifba_expire = 0;
1016 bareq.ifba_flags = brt->brt_flags;
1017
1018 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
1019 if (error)
1020 goto out;
1021 count++;
1022 len -= sizeof(bareq);
1023 }
d217f5e5 1024out:
ac93838f
SS
1025 bac->ifbac_len = sizeof(bareq) * count;
1026 return (error);
1027}
1028
d217f5e5 1029static int
ac93838f
SS
1030bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
1031{
1032 struct ifbareq *req = arg;
1033 struct bridge_iflist *bif;
1034 int error;
1035
1036 bif = bridge_lookup_member(sc, req->ifba_ifsname);
1037 if (bif == NULL)
1038 return (ENOENT);
1039
1040 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
1041 req->ifba_flags);
1042
1043 return (error);
1044}
1045
d217f5e5 1046static int
ac93838f
SS
1047bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
1048{
1049 struct ifbrparam *param = arg;
1050
1051 sc->sc_brttimeout = param->ifbrp_ctime;
1052
1053 return (0);
1054}
1055
d217f5e5 1056static int
ac93838f
SS
1057bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
1058{
1059 struct ifbrparam *param = arg;
1060
1061 param->ifbrp_ctime = sc->sc_brttimeout;
1062
1063 return (0);
1064}
1065
d217f5e5 1066static int
ac93838f
SS
1067bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
1068{
1069 struct ifbareq *req = arg;
1070
1071 return (bridge_rtdaddr(sc, req->ifba_dst));
1072}
1073
d217f5e5 1074static int
ac93838f
SS
1075bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
1076{
1077 struct ifbreq *req = arg;
1078
1079 bridge_rtflush(sc, req->ifbr_ifsflags);
1080
1081 return (0);
1082}
1083
d217f5e5 1084static int
ac93838f
SS
1085bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
1086{
1087 struct ifbrparam *param = arg;
1088
1089 param->ifbrp_prio = sc->sc_bridge_priority;
1090
1091 return (0);
1092}
1093
d217f5e5 1094static int
ac93838f
SS
1095bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
1096{
1097 struct ifbrparam *param = arg;
1098
1099 sc->sc_bridge_priority = param->ifbrp_prio;
1100
1101 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1102 bstp_initialization(sc);
1103
1104 return (0);
1105}
1106
d217f5e5 1107static int
ac93838f
SS
1108bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
1109{
1110 struct ifbrparam *param = arg;
1111
1112 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
1113
1114 return (0);
1115}
1116
d217f5e5 1117static int
ac93838f
SS
1118bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
1119{
1120 struct ifbrparam *param = arg;
1121
1122 if (param->ifbrp_hellotime == 0)
1123 return (EINVAL);
1124 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
1125
1126 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1127 bstp_initialization(sc);
1128
1129 return (0);
1130}
1131
d217f5e5 1132static int
ac93838f
SS
1133bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
1134{
1135 struct ifbrparam *param = arg;
1136
1137 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
1138
1139 return (0);
1140}
1141
d217f5e5 1142static int
ac93838f
SS
1143bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
1144{
1145 struct ifbrparam *param = arg;
1146
1147 if (param->ifbrp_fwddelay == 0)
1148 return (EINVAL);
1149 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
1150
1151 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1152 bstp_initialization(sc);
1153
1154 return (0);
1155}
1156
d217f5e5 1157static int
ac93838f
SS
1158bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
1159{
1160 struct ifbrparam *param = arg;
1161
1162 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
1163
1164 return (0);
1165}
1166
d217f5e5 1167static int
ac93838f
SS
1168bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
1169{
1170 struct ifbrparam *param = arg;
1171
1172 if (param->ifbrp_maxage == 0)
1173 return (EINVAL);
1174 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
1175
1176 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1177 bstp_initialization(sc);
1178
1179 return (0);
1180}
1181
d217f5e5 1182static int
ac93838f
SS
1183bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
1184{
1185 struct ifbreq *req = arg;
1186 struct bridge_iflist *bif;
1187
1188 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
1189 if (bif == NULL)
1190 return (ENOENT);
1191
1192 bif->bif_priority = req->ifbr_priority;
1193
1194 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1195 bstp_initialization(sc);
1196
1197 return (0);
1198}
1199
d217f5e5 1200static int
ac93838f
SS
1201bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg)
1202{
1203 struct ifbreq *req = arg;
1204 struct bridge_iflist *bif;
1205
1206 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
1207 if (bif == NULL)
1208 return (ENOENT);
1209
1210 bif->bif_path_cost = req->ifbr_path_cost;
1211
1212 if (sc->sc_ifp->if_flags & IFF_RUNNING)
1213 bstp_initialization(sc);
1214
1215 return (0);
1216}
1217
d217f5e5
SU
1218static int
1219bridge_ioctl_addspan(struct bridge_softc *sc, void *arg)
1220{
1221 struct ifbreq *req = arg;
1222 struct bridge_iflist *bif = NULL;
1223 struct ifnet *ifs;
1224
1225 ifs = ifunit(req->ifbr_ifsname);
1226 if (ifs == NULL)
1227 return (ENOENT);
1228
1229 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
1230 if (ifs == bif->bif_ifp)
1231 return (EBUSY);
1232
1233 if (ifs->if_bridge != NULL)
1234 return (EBUSY);
1235
1236 switch (ifs->if_type) {
1237 case IFT_ETHER:
1238 case IFT_GIF:
1239 case IFT_L2VLAN:
1240 break;
1241 default:
1242 return (EINVAL);
1243 }
1244
6676e111 1245 bif = kmalloc(sizeof(*bif), M_DEVBUF, M_WAITOK|M_ZERO);
d217f5e5
SU
1246 if (bif == NULL)
1247 return (ENOMEM);
1248
1249 bif->bif_ifp = ifs;
1250 bif->bif_flags = IFBIF_SPAN;
1251
1252 LIST_INSERT_HEAD(&sc->sc_spanlist, bif, bif_next);
1253
1254 return (0);
1255}
1256
1257static int
1258bridge_ioctl_delspan(struct bridge_softc *sc, void *arg)
1259{
1260 struct ifbreq *req = arg;
1261 struct bridge_iflist *bif;
1262 struct ifnet *ifs;
1263
1264 ifs = ifunit(req->ifbr_ifsname);
1265 if (ifs == NULL)
1266 return (ENOENT);
1267
1268 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
1269 if (ifs == bif->bif_ifp)
1270 break;
1271
1272 if (bif == NULL)
1273 return (ENOENT);
1274
1275 bridge_delete_span(sc, bif);
1276
1277 return (0);
1278}
1279
ac93838f
SS
1280/*
1281 * bridge_ifdetach:
1282 *
1283 * Detach an interface from a bridge. Called when a member
1284 * interface is detaching.
1285 */
d217f5e5
SU
1286static void
1287bridge_ifdetach(void *arg __unused, struct ifnet *ifp)
ac93838f
SS
1288{
1289 struct bridge_softc *sc = ifp->if_bridge;
d217f5e5 1290 struct bridge_iflist *bif;
ac93838f 1291
d217f5e5
SU
1292 /* Check if the interface is a bridge member */
1293 if (sc != NULL) {
1294 lwkt_serialize_enter(ifp->if_serializer);
ac93838f 1295
d217f5e5
SU
1296 bif = bridge_lookup_member_if(sc, ifp);
1297 if (bif != NULL)
1298 bridge_delete_member(sc, bif, 1);
1299
1300 lwkt_serialize_exit(ifp->if_serializer);
1301 return;
1302 }
1303
1304 /* Check if the interface is a span port */
1305 LIST_FOREACH(sc, &bridge_list, sc_list) {
1306 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next)
1307 if (ifp == bif->bif_ifp) {
1308 bridge_delete_span(sc, bif);
1309 break;
1310 }
1311 }
ac93838f
SS
1312}
1313
1314/*
1315 * bridge_init:
1316 *
1317 * Initialize a bridge interface.
1318 */
1319static void
1320bridge_init(void *xsc)
1321{
1322 struct bridge_softc *sc = (struct bridge_softc *)xsc;
1323 struct ifnet *ifp = sc->sc_ifp;
1324
1325 if (ifp->if_flags & IFF_RUNNING)
1326 return;
1327
1328 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
1329 bridge_timer, sc);
1330
1331 ifp->if_flags |= IFF_RUNNING;
1332 bstp_initialization(sc);
1333 return;
1334}
1335
1336/*
1337 * bridge_stop:
1338 *
1339 * Stop the bridge interface.
1340 */
d217f5e5 1341static void
ac93838f
SS
1342bridge_stop(struct ifnet *ifp, int disable)
1343{
1344 struct bridge_softc *sc = ifp->if_softc;
1345
1346 ASSERT_SERIALIZED(ifp->if_serializer);
1347
1348 if ((ifp->if_flags & IFF_RUNNING) == 0)
1349 return;
1350
1351 callout_stop(&sc->sc_brcallout);
1352 bstp_stop(sc);
1353
1354 bridge_rtflush(sc, IFBF_FLUSHDYN);
1355
1356 ifp->if_flags &= ~IFF_RUNNING;
1357}
1358
1359/*
1360 * bridge_enqueue:
1361 *
1362 * Enqueue a packet on a bridge member interface.
1363 *
1364 */
1365__inline void
1366bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
1367{
1368 struct altq_pktattr pktattr;
d217f5e5 1369 struct mbuf *m0;
ac93838f
SS
1370
1371 while (m->m_type == MT_TAG) {
1372 /* XXX see ether_output_frame for full rules check */
1373 m = m->m_next;
1374 }
1375
1376 lwkt_serialize_enter(dst_ifp->if_serializer);
1377
d217f5e5
SU
1378 /* We may be sending a fragment so traverse the mbuf */
1379 for (; m; m = m0) {
1380 m0 = m->m_nextpkt;
1381 m->m_nextpkt = NULL;
1382
1383 if (ifq_is_enabled(&dst_ifp->if_snd))
1384 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr);
ac93838f 1385
d217f5e5
SU
1386 ifq_handoff(dst_ifp, m, &pktattr);
1387 }
ac93838f
SS
1388
1389 lwkt_serialize_exit(dst_ifp->if_serializer);
1390}
1391
1392/*
1393 * bridge_output_serialized:
1394 *
1395 * Send output from a bridge member interface. This
1396 * performs the bridging function for locally originated
1397 * packets.
1398 *
1399 * The mbuf has the Ethernet header already attached. We must
1400 * enqueue or free the mbuf before returning.
1401 */
1402int
1403bridge_output_serialized(struct ifnet *ifp, struct mbuf *m,
1404 struct sockaddr *sa, struct rtentry *rt)
1405{
1406 struct ether_header *eh;
1407 struct ifnet *dst_if;
1408 struct bridge_softc *sc;
1409
1410 sc = ifp->if_bridge;
1411
1412 ASSERT_SERIALIZED(ifp->if_serializer);
1413
1414 if (m->m_len < ETHER_HDR_LEN) {
1415 m = m_pullup(m, ETHER_HDR_LEN);
1416 if (m == NULL)
1417 return (0);
1418 }
1419
1420 /*
1421 * Serialize our bridge interface. We have to get rid of the
1422 * originating interface lock to avoid a deadlock.
1423 */
1424 lwkt_serialize_exit(ifp->if_serializer);
1425 lwkt_serialize_enter(sc->sc_ifp->if_serializer);
1426
1427 eh = mtod(m, struct ether_header *);
1428
1429 /*
1430 * If bridge is down, but the original output interface is up,
1431 * go ahead and send out that interface. Otherwise, the packet
1432 * is dropped below.
1433 */
1434 if ((sc->sc_ifp->if_flags & IFF_RUNNING) == 0) {
1435 dst_if = ifp;
1436 goto sendunicast;
1437 }
1438
1439 /*
1440 * If the packet is a multicast, or we don't know a better way to
1441 * get there, send to all interfaces.
1442 */
1443 if (ETHER_IS_MULTICAST(eh->ether_dhost))
1444 dst_if = NULL;
1445 else
1446 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1447 if (dst_if == NULL) {
1448 struct bridge_iflist *bif;
1449 struct mbuf *mc;
1450 int used = 0;
1451
d217f5e5
SU
1452 bridge_span(sc, m);
1453
ac93838f
SS
1454 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1455 dst_if = bif->bif_ifp;
1456 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1457 continue;
1458
1459 /*
1460 * If this is not the original output interface,
1461 * and the interface is participating in spanning
1462 * tree, make sure the port is in a state that
1463 * allows forwarding.
1464 */
1465 if (dst_if != ifp &&
1466 (bif->bif_flags & IFBIF_STP) != 0) {
1467 switch (bif->bif_state) {
1468 case BSTP_IFSTATE_BLOCKING:
1469 case BSTP_IFSTATE_LISTENING:
1470 case BSTP_IFSTATE_DISABLED:
1471 continue;
1472 }
1473 }
1474
1475 if (LIST_NEXT(bif, bif_next) == NULL) {
1476 used = 1;
1477 mc = m;
1478 } else {
1479 mc = m_copypacket(m, MB_DONTWAIT);
1480 if (mc == NULL) {
1481 sc->sc_ifp->if_oerrors++;
1482 continue;
1483 }
1484 }
1485 lwkt_serialize_exit(sc->sc_ifp->if_serializer);
1486 bridge_enqueue(sc, dst_if, mc);
1487 lwkt_serialize_enter(sc->sc_ifp->if_serializer);
1488 }
1489 if (used == 0)
1490 m_freem(m);
1491 lwkt_serialize_exit(sc->sc_ifp->if_serializer);
1492 goto done;
1493 }
1494
d217f5e5 1495sendunicast:
ac93838f
SS
1496 /*
1497 * XXX Spanning tree consideration here?
1498 */
1499
d217f5e5 1500 bridge_span(sc, m);
ac93838f
SS
1501 lwkt_serialize_exit(sc->sc_ifp->if_serializer);
1502 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1503 m_freem(m);
1504 } else {
1505 bridge_enqueue(sc, dst_if, m);
1506 }
1507done:
1508 lwkt_serialize_enter(ifp->if_serializer);
1509 return (0);
1510}
1511
1512/*
1513 * bridge_start:
1514 *
1515 * Start output on a bridge.
1516 *
1517 */
d217f5e5 1518static void
ac93838f
SS
1519bridge_start(struct ifnet *ifp)
1520{
1521 struct bridge_softc *sc;
1522 struct mbuf *m;
1523 struct ether_header *eh;
1524 struct ifnet *dst_if;
1525
1526 sc = ifp->if_softc;
1527
1528 ifp->if_flags |= IFF_OACTIVE;
1529 for (;;) {
1530 m = ifq_dequeue(&ifp->if_snd, NULL);
1531 if (m == 0)
1532 break;
1533 BPF_MTAP(ifp, m);
c5a216a9 1534 ifp->if_opackets++;
ac93838f
SS
1535
1536 eh = mtod(m, struct ether_header *);
1537 dst_if = NULL;
1538
1539 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1540 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1541 }
1542
1543 if (dst_if == NULL)
1544 bridge_broadcast(sc, ifp, m, 0);
1545 else
1546 bridge_enqueue(sc, dst_if, m);
1547 }
1548 ifp->if_flags &= ~IFF_OACTIVE;
1549
1550 return;
1551}
1552
1553/*
1554 * bridge_forward:
1555 *
1556 * The forwarding function of the bridge.
1557 */
d217f5e5 1558static void
ac93838f
SS
1559bridge_forward(struct bridge_softc *sc, struct mbuf *m)
1560{
1561 struct bridge_iflist *bif;
1562 struct ifnet *src_if, *dst_if, *ifp;
1563 struct ether_header *eh;
1564
1565 src_if = m->m_pkthdr.rcvif;
1566 ifp = sc->sc_ifp;
1567
1568 ASSERT_SERIALIZED(ifp->if_serializer);
1569
1570 sc->sc_ifp->if_ipackets++;
1571 sc->sc_ifp->if_ibytes += m->m_pkthdr.len;
1572
1573 /*
1574 * Look up the bridge_iflist.
1575 */
1576 bif = bridge_lookup_member_if(sc, src_if);
1577 if (bif == NULL) {
1578 /* Interface is not a bridge member (anymore?) */
1579 m_freem(m);
1580 return;
1581 }
1582
1583 if (bif->bif_flags & IFBIF_STP) {
1584 switch (bif->bif_state) {
1585 case BSTP_IFSTATE_BLOCKING:
1586 case BSTP_IFSTATE_LISTENING:
1587 case BSTP_IFSTATE_DISABLED:
1588 m_freem(m);
1589 return;
1590 }
1591 }
1592
1593 eh = mtod(m, struct ether_header *);
1594
ecdefdda
MD
1595 /*
1596 * Various ifp's are used below, release the serializer for
1597 * the bridge ifp so other ifp serializers can be acquired.
1598 */
1599 lwkt_serialize_exit(ifp->if_serializer);
1600
ac93838f
SS
1601 /*
1602 * If the interface is learning, and the source
1603 * address is valid and not multicast, record
1604 * the address.
1605 */
1606 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1607 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1608 (eh->ether_shost[0] == 0 &&
1609 eh->ether_shost[1] == 0 &&
1610 eh->ether_shost[2] == 0 &&
1611 eh->ether_shost[3] == 0 &&
1612 eh->ether_shost[4] == 0 &&
1613 eh->ether_shost[5] == 0) == 0) {
3bf25ce1 1614 bridge_rtupdate(sc, eh->ether_shost, src_if, 0, IFBAF_DYNAMIC);
ac93838f
SS
1615 }
1616
1617 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1618 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1619 m_freem(m);
ecdefdda 1620 goto done;
ac93838f
SS
1621 }
1622
1623 /*
1624 * At this point, the port either doesn't participate
1625 * in spanning tree or it is in the forwarding state.
1626 */
1627
1628 /*
1629 * If the packet is unicast, destined for someone on
1630 * "this" side of the bridge, drop it.
1631 */
1632 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1633 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1634 if (src_if == dst_if) {
1635 m_freem(m);
ecdefdda 1636 goto done;
ac93838f
SS
1637 }
1638 } else {
1639 /* ...forward it to all interfaces. */
1640 sc->sc_ifp->if_imcasts++;
1641 dst_if = NULL;
1642 }
1643
1644 /* run the packet filter */
1645 if (inet_pfil_hook.ph_hashooks > 0
1646#ifdef INET6
1647 || inet6_pfil_hook.ph_hashooks > 0
1648#endif
1649 ) {
1650 if (bridge_pfil(&m, ifp, src_if, PFIL_IN) != 0)
ecdefdda 1651 goto done;
ac93838f 1652 if (m == NULL)
ecdefdda 1653 goto done;
ac93838f
SS
1654 }
1655
1656 if (dst_if == NULL) {
ac93838f 1657 bridge_broadcast(sc, src_if, m, 1);
ecdefdda 1658 goto done;
ac93838f
SS
1659 }
1660
1661 /*
1662 * At this point, we're dealing with a unicast frame
1663 * going to a different interface.
1664 */
1665 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1666 m_freem(m);
ecdefdda 1667 goto done;
ac93838f
SS
1668 }
1669 bif = bridge_lookup_member_if(sc, dst_if);
1670 if (bif == NULL) {
1671 /* Not a member of the bridge (anymore?) */
1672 m_freem(m);
ecdefdda 1673 goto done;
ac93838f
SS
1674 }
1675
1676 if (bif->bif_flags & IFBIF_STP) {
1677 switch (bif->bif_state) {
1678 case BSTP_IFSTATE_DISABLED:
1679 case BSTP_IFSTATE_BLOCKING:
1680 m_freem(m);
ecdefdda 1681 goto done;
ac93838f
SS
1682 }
1683 }
1684
1685 if (inet_pfil_hook.ph_hashooks > 0
1686#ifdef INET6
1687 || inet6_pfil_hook.ph_hashooks > 0
1688#endif
1689 ) {
1690 if (bridge_pfil(&m, sc->sc_ifp, dst_if, PFIL_OUT) != 0)
ecdefdda 1691 goto done;
ac93838f 1692 if (m == NULL)
ecdefdda 1693 goto done;
ac93838f 1694 }
ac93838f 1695 bridge_enqueue(sc, dst_if, m);
ecdefdda
MD
1696
1697 /*
1698 * ifp's serializer was held on entry and is expected to be held
1699 * on return.
1700 */
1701done:
ac93838f
SS
1702 lwkt_serialize_enter(ifp->if_serializer);
1703}
1704
1705/*
1706 * bridge_input:
1707 *
1708 * Receive input from a member interface. Queue the packet for
1709 * bridging if it is not for us.
1710 */
1711struct mbuf *
1712bridge_input(struct ifnet *ifp, struct mbuf *m)
1713{
1714 struct bridge_softc *sc = ifp->if_bridge;
1715 struct bridge_iflist *bif;
1716 struct ifnet *bifp;
1717 struct ether_header *eh;
1718 struct mbuf *mc, *mc2;
1719
1720 bifp = sc->sc_ifp;
1721 lwkt_serialize_enter(bifp->if_serializer);
1722
1723 if ((sc->sc_ifp->if_flags & IFF_RUNNING) == 0)
1724 goto out;
1725
3a593c54
MD
1726 /*
1727 * Implement support for bridge monitoring. If this flag has been
1728 * set on this interface, discard the packet once we push it through
1729 * the bpf(4) machinery, but before we do, increment the byte and
1730 * packet counters associated with this interface.
1731 */
1732 if ((bifp->if_flags & IFF_MONITOR) != 0) {
1733 m->m_pkthdr.rcvif = bifp;
1734 BPF_MTAP(bifp, m);
1735 bifp->if_ipackets++;
1736 bifp->if_ibytes += m->m_pkthdr.len;
1737 m_freem(m);
1738 goto out;
1739 }
1740
ac93838f
SS
1741 bif = bridge_lookup_member_if(sc, ifp);
1742 if (bif == NULL)
1743 goto out;
1744
1745 eh = mtod(m, struct ether_header *);
1746
1747 m->m_flags &= ~M_PROTO1; /* XXX Hack - loop prevention */
1748
f94bb7f0
SS
1749 /*
1750 * Tap all packets arriving on the bridge, no matter if
1751 * they are local destinations or not. In is in.
1752 */
1753 BPF_MTAP(bifp, m);
1754
ac93838f
SS
1755#define IFP2AC(ifp) ((struct arpcom *)(ifp))
1756#define IFP2ENADDR(ifp) (IFP2AC(ifp)->ac_enaddr)
1757 if (memcmp(eh->ether_dhost, IFP2ENADDR(bifp),
1758 ETHER_ADDR_LEN) == 0) {
1759 /*
1760 * If the packet is for us, set the packets source as the
1761 * bridge, and return the packet back to ether_input for
1762 * local processing.
1763 */
1764
1765 /* Mark the packet as arriving on the bridge interface */
1766 m->m_pkthdr.rcvif = bifp;
1767 bifp->if_ipackets++;
1768
1769 goto out;
1770 }
1771
d217f5e5
SU
1772 bridge_span(sc, m);
1773
ac93838f
SS
1774 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
1775 /* Tap off 802.1D packets; they do not get forwarded. */
1776 if (memcmp(eh->ether_dhost, bstp_etheraddr,
1777 ETHER_ADDR_LEN) == 0) {
1778 m = bstp_input(ifp, m);
1779 if (m == NULL)
1780 goto out;
1781 }
1782
1783 if (bif->bif_flags & IFBIF_STP) {
1784 switch (bif->bif_state) {
1785 case BSTP_IFSTATE_BLOCKING:
1786 case BSTP_IFSTATE_LISTENING:
1787 case BSTP_IFSTATE_DISABLED:
1788 goto out;
1789 }
1790 }
1791
1792 if (bcmp(etherbroadcastaddr, eh->ether_dhost,
1793 sizeof(etherbroadcastaddr)) == 0)
1794 m->m_flags |= M_BCAST;
1795 else
1796 m->m_flags |= M_MCAST;
1797
1798 /*
1799 * Make a deep copy of the packet and enqueue the copy
1800 * for bridge processing; return the original packet for
1801 * local processing.
1802 */
1803 mc = m_dup(m, MB_DONTWAIT);
1804 if (mc == NULL)
1805 goto out;
1806
1807 bridge_forward(sc, mc);
1808
1809 /*
1810 * Reinject the mbuf as arriving on the bridge so we have a
1811 * chance at claiming multicast packets. We can not loop back
1812 * here from ether_input as a bridge is never a member of a
1813 * bridge.
1814 */
1815 KASSERT(bifp->if_bridge == NULL,
1816 ("loop created in bridge_input"));
d217f5e5
SU
1817 mc2 = m_dup(m, MB_DONTWAIT);
1818#ifdef notyet
1819 if (mc2 != NULL) {
1820 /* Keep the layer3 header aligned */
1821 int i = min(mc2->m_pkthdr.len, max_protohdr);
1822 mc2 = m_copyup(mc2, i, ETHER_ALIGN);
1823 }
1824#endif
ac93838f
SS
1825 if (mc2 != NULL) {
1826 mc2->m_pkthdr.rcvif = bifp;
1827 (*bifp->if_input)(bifp, mc2);
1828 }
1829
1830 /* Return the original packet for local processing. */
1831 goto out;
1832 }
1833
1834 if (bif->bif_flags & IFBIF_STP) {
1835 switch (bif->bif_state) {
1836 case BSTP_IFSTATE_BLOCKING:
1837 case BSTP_IFSTATE_LISTENING:
1838 case BSTP_IFSTATE_DISABLED:
1839 goto out;
1840 }
1841 }
1842
1843 /*
1844 * Unicast. Make sure it's not for us.
1845 */
1846 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1847 if (bif->bif_ifp->if_type != IFT_ETHER)
1848 continue;
1849 /* It is destined for us. */
1850 if (memcmp(IF_LLADDR(bif->bif_ifp), eh->ether_dhost,
1851 ETHER_ADDR_LEN) == 0) {
1852 if (bif->bif_flags & IFBIF_LEARNING)
3bf25ce1 1853 bridge_rtupdate(sc,
ac93838f
SS
1854 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC);
1855 m->m_pkthdr.rcvif = bif->bif_ifp;
1856 if (ifp->if_type == IFT_GIF) {
1857 m->m_flags |= M_PROTO1;
1858 /*
1859 * Avoid an interface ordering deadlock.
1860 */
1861 lwkt_serialize_exit(bifp->if_serializer);
1862 lwkt_serialize_enter(bif->bif_ifp->if_serializer);
1863 (*bif->bif_ifp->if_input)(bif->bif_ifp, m);
1864 lwkt_serialize_exit(bif->bif_ifp->if_serializer);
1865 lwkt_serialize_enter(bifp->if_serializer);
1866 m = NULL;
1867 }
1868 goto out;
1869 }
1870
1871 /* We just received a packet that we sent out. */
1872 if (memcmp(IF_LLADDR(bif->bif_ifp), eh->ether_shost,
1873 ETHER_ADDR_LEN) == 0) {
1874 m_freem(m);
1875 m = NULL;
1876 goto out;
1877 }
1878 }
1879
1880 /* Perform the bridge forwarding function. */
1881 bridge_forward(sc, m);
1882 m = NULL;
1883
1884out:
1885 lwkt_serialize_exit(bifp->if_serializer);
d217f5e5 1886 return (m);
ac93838f
SS
1887}
1888
1889/*
1890 * bridge_broadcast:
1891 *
1892 * Send a frame to all interfaces that are members of
1893 * the bridge, except for the one on which the packet
1894 * arrived.
1895 */
d217f5e5 1896static void
ac93838f
SS
1897bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
1898 struct mbuf *m, int runfilt)
1899{
1900 struct bridge_iflist *bif;
1901 struct mbuf *mc;
1902 struct ifnet *dst_if;
1903 int used = 0;
1904
1905 /* Filter on the bridge interface before broadcasting */
1906 if (runfilt && (inet_pfil_hook.ph_hashooks > 0
1907#ifdef INET6
d217f5e5 1908 || inet6_pfil_hook.ph_hashooks > 0
ac93838f
SS
1909#endif
1910 )) {
1911 if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0)
1912 return;
1913 if (m == NULL)
1914 return;
1915 }
1916
1917 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
1918 dst_if = bif->bif_ifp;
1919 if (dst_if == src_if)
1920 continue;
1921
1922 if (bif->bif_flags & IFBIF_STP) {
1923 switch (bif->bif_state) {
1924 case BSTP_IFSTATE_BLOCKING:
1925 case BSTP_IFSTATE_DISABLED:
1926 continue;
1927 }
1928 }
1929
1930 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 &&
1931 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
1932 continue;
1933
1934 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1935 continue;
1936
1937 if (LIST_NEXT(bif, bif_next) == NULL) {
1938 mc = m;
1939 used = 1;
1940 } else {
1941 mc = m_copypacket(m, MB_DONTWAIT);
1942 if (mc == NULL) {
1943 sc->sc_ifp->if_oerrors++;
1944 continue;
1945 }
1946 }
1947
1948 /*
1949 * Filter on the output interface. Pass a NULL bridge interface
1950 * pointer so we do not redundantly filter on the bridge for
1951 * each interface we broadcast on.
1952 */
1953 if (runfilt && (inet_pfil_hook.ph_hashooks > 0
1954#ifdef INET6
1955 || inet6_pfil_hook.ph_hashooks > 0
1956#endif
1957 )) {
d217f5e5
SU
1958 if (bridge_pfil(&mc, NULL, dst_if, PFIL_OUT) != 0)
1959 continue;
1960 if (mc == NULL)
1961 continue;
ac93838f
SS
1962 }
1963
1964 bridge_enqueue(sc, dst_if, mc);
1965 }
1966 if (used == 0)
1967 m_freem(m);
1968}
1969
d217f5e5
SU
1970/*
1971 * bridge_span:
1972 *
1973 * Duplicate a packet out one or more interfaces that are in span mode,
1974 * the original mbuf is unmodified.
1975 */
1976static void
1977bridge_span(struct bridge_softc *sc, struct mbuf *m)
1978{
1979 struct bridge_iflist *bif;
1980 struct ifnet *dst_if;
1981 struct mbuf *mc;
1982
1983 if (LIST_EMPTY(&sc->sc_spanlist))
1984 return;
1985
1986 LIST_FOREACH(bif, &sc->sc_spanlist, bif_next) {
1987 dst_if = bif->bif_ifp;
1988
1989 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1990 continue;
1991
1992 mc = m_copypacket(m, MB_DONTWAIT);
1993 if (mc == NULL) {
1994 sc->sc_ifp->if_oerrors++;
1995 continue;
1996 }
1997
1998 bridge_enqueue(sc, dst_if, mc);
1999 }
2000}
2001
ac93838f
SS
2002/*
2003 * bridge_rtupdate:
2004 *
2005 * Add a bridge routing entry.
2006 */
d217f5e5 2007static int
ac93838f
SS
2008bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
2009 struct ifnet *dst_if, int setflags, uint8_t flags)
2010{
2011 struct bridge_rtnode *brt;
2012 int error;
2013
2014 /*
2015 * A route for this destination might already exist. If so,
2016 * update it, otherwise create a new one.
2017 */
2018 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) {
2019 if (sc->sc_brtcnt >= sc->sc_brtmax)
2020 return (ENOSPC);
2021
2022 /*
2023 * Allocate a new bridge forwarding node, and
2024 * initialize the expiration time and Ethernet
2025 * address.
2026 */
6676e111 2027 brt = kmalloc(sizeof(struct bridge_rtnode), M_DEVBUF, M_WAITOK|M_ZERO);
ac93838f
SS
2028 if (brt == NULL)
2029 return (ENOMEM);
2030
ac93838f
SS
2031 brt->brt_flags = IFBAF_DYNAMIC;
2032 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
2033
2034 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
efda3bd0 2035 kfree(brt, M_DEVBUF);
ac93838f
SS
2036 return (error);
2037 }
2038 }
2039
d217f5e5
SU
2040 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
2041 brt->brt_ifp = dst_if;
2042 if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
2043 brt->brt_expire = time_second + sc->sc_brttimeout;
2044 if (setflags)
ac93838f 2045 brt->brt_flags = flags;
ac93838f
SS
2046
2047 return (0);
2048}
2049
2050/*
2051 * bridge_rtlookup:
2052 *
2053 * Lookup the destination interface for an address.
2054 */
d217f5e5 2055static struct ifnet *
ac93838f
SS
2056bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr)
2057{
2058 struct bridge_rtnode *brt;
2059
2060 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
2061 return (NULL);
2062
2063 return (brt->brt_ifp);
2064}
2065
2066/*
2067 * bridge_rttrim:
2068 *
2069 * Trim the routine table so that we have a number
2070 * of routing entries less than or equal to the
2071 * maximum number.
2072 */
d217f5e5 2073static void
ac93838f
SS
2074bridge_rttrim(struct bridge_softc *sc)
2075{
2076 struct bridge_rtnode *brt, *nbrt;
2077
2078 /* Make sure we actually need to do this. */
2079 if (sc->sc_brtcnt <= sc->sc_brtmax)
2080 return;
2081
2082 /* Force an aging cycle; this might trim enough addresses. */
2083 bridge_rtage(sc);
2084 if (sc->sc_brtcnt <= sc->sc_brtmax)
2085 return;
2086
2087 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
2088 nbrt = LIST_NEXT(brt, brt_list);
2089 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
2090 bridge_rtnode_destroy(sc, brt);
2091 if (sc->sc_brtcnt <= sc->sc_brtmax)
2092 return;
2093 }
2094 }
2095}
2096
2097/*
2098 * bridge_timer:
2099 *
2100 * Aging timer for the bridge.
2101 */
d217f5e5 2102static void
ac93838f
SS
2103bridge_timer(void *arg)
2104{
2105 struct bridge_softc *sc = arg;
2106
2107 lwkt_serialize_enter(sc->sc_ifp->if_serializer);
2108
2109 bridge_rtage(sc);
2110
2111 if (sc->sc_ifp->if_flags & IFF_RUNNING)
2112 callout_reset(&sc->sc_brcallout,
2113 bridge_rtable_prune_period * hz, bridge_timer, sc);
2114
2115 lwkt_serialize_exit(sc->sc_ifp->if_serializer);
2116}
2117
2118/*
2119 * bridge_rtage:
2120 *
2121 * Perform an aging cycle.
2122 */
d217f5e5 2123static void
ac93838f
SS
2124bridge_rtage(struct bridge_softc *sc)
2125{
2126 struct bridge_rtnode *brt, *nbrt;
2127
2128 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
2129 nbrt = LIST_NEXT(brt, brt_list);
2130 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
2131 if (time_second >= brt->brt_expire)
2132 bridge_rtnode_destroy(sc, brt);
2133 }
2134 }
2135}
2136
2137/*
2138 * bridge_rtflush:
2139 *
2140 * Remove all dynamic addresses from the bridge.
2141 */
d217f5e5 2142static void
ac93838f
SS
2143bridge_rtflush(struct bridge_softc *sc, int full)
2144{
2145 struct bridge_rtnode *brt, *nbrt;
2146
2147 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
2148 nbrt = LIST_NEXT(brt, brt_list);
2149 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
2150 bridge_rtnode_destroy(sc, brt);
2151 }
2152}
2153
2154/*
2155 * bridge_rtdaddr:
2156 *
2157 * Remove an address from the table.
2158 */
d217f5e5 2159static int
ac93838f
SS
2160bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr)
2161{
2162 struct bridge_rtnode *brt;
2163
2164 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL)
2165 return (ENOENT);
2166
2167 bridge_rtnode_destroy(sc, brt);
2168 return (0);
2169}
2170
2171/*
2172 * bridge_rtdelete:
2173 *
2174 * Delete routes to a speicifc member interface.
2175 */
2176void
2177bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp, int full)
2178{
2179 struct bridge_rtnode *brt, *nbrt;
2180
2181 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) {
2182 nbrt = LIST_NEXT(brt, brt_list);
d217f5e5 2183 if (brt->brt_ifp == ifp && (full ||
ac93838f
SS
2184 (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC))
2185 bridge_rtnode_destroy(sc, brt);
2186 }
2187}
2188
2189/*
2190 * bridge_rtable_init:
2191 *
2192 * Initialize the route table for this bridge.
2193 */
d217f5e5 2194static int
ac93838f
SS
2195bridge_rtable_init(struct bridge_softc *sc)
2196{
2197 int i;
2198
77652cad 2199 sc->sc_rthash = kmalloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
d217f5e5 2200 M_DEVBUF, M_WAITOK);
ac93838f
SS
2201
2202 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++)
2203 LIST_INIT(&sc->sc_rthash[i]);
2204
0ced1954 2205 sc->sc_rthash_key = karc4random();
ac93838f
SS
2206
2207 LIST_INIT(&sc->sc_rtlist);
2208
2209 return (0);
2210}
2211
2212/*
2213 * bridge_rtable_fini:
2214 *
2215 * Deconstruct the route table for this bridge.
2216 */
d217f5e5 2217static void
ac93838f
SS
2218bridge_rtable_fini(struct bridge_softc *sc)
2219{
2220
efda3bd0 2221 kfree(sc->sc_rthash, M_DEVBUF);
ac93838f
SS
2222}
2223
2224/*
2225 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
2226 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
2227 */
2228#define mix(a, b, c) \
2229do { \
2230 a -= b; a -= c; a ^= (c >> 13); \
2231 b -= c; b -= a; b ^= (a << 8); \
2232 c -= a; c -= b; c ^= (b >> 13); \
2233 a -= b; a -= c; a ^= (c >> 12); \
2234 b -= c; b -= a; b ^= (a << 16); \
2235 c -= a; c -= b; c ^= (b >> 5); \
2236 a -= b; a -= c; a ^= (c >> 3); \
2237 b -= c; b -= a; b ^= (a << 10); \
2238 c -= a; c -= b; c ^= (b >> 15); \
2239} while (/*CONSTCOND*/0)
2240
2241static __inline uint32_t
2242bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
2243{
2244 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
2245
2246 b += addr[5] << 8;
2247 b += addr[4];
2248 a += addr[3] << 24;
2249 a += addr[2] << 16;
2250 a += addr[1] << 8;
2251 a += addr[0];
2252
2253 mix(a, b, c);
2254
2255 return (c & BRIDGE_RTHASH_MASK);
2256}
2257
2258#undef mix
2259
d217f5e5
SU
2260static int
2261bridge_rtnode_addr_cmp(const uint8_t *a, const uint8_t *b)
2262{
2263 int i, d;
2264
2265 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
2266 d = ((int)a[i]) - ((int)b[i]);
2267 }
2268
2269 return (d);
2270}
2271
ac93838f
SS
2272/*
2273 * bridge_rtnode_lookup:
2274 *
2275 * Look up a bridge route node for the specified destination.
2276 */
d217f5e5 2277static struct bridge_rtnode *
ac93838f
SS
2278bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
2279{
2280 struct bridge_rtnode *brt;
2281 uint32_t hash;
2282 int dir;
2283
2284 hash = bridge_rthash(sc, addr);
2285 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
d217f5e5 2286 dir = bridge_rtnode_addr_cmp(addr, brt->brt_addr);
ac93838f
SS
2287 if (dir == 0)
2288 return (brt);
2289 if (dir > 0)
2290 return (NULL);
2291 }
2292
2293 return (NULL);
2294}
2295
2296/*
2297 * bridge_rtnode_insert:
2298 *
2299 * Insert the specified bridge node into the route table. We
2300 * assume the entry is not already in the table.
2301 */
d217f5e5 2302static int
ac93838f
SS
2303bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
2304{
2305 struct bridge_rtnode *lbrt;
2306 uint32_t hash;
2307 int dir;
2308
2309 hash = bridge_rthash(sc, brt->brt_addr);
2310
2311 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
2312 if (lbrt == NULL) {
2313 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
2314 goto out;
2315 }
2316
2317 do {
d217f5e5 2318 dir = bridge_rtnode_addr_cmp(brt->brt_addr, lbrt->brt_addr);
ac93838f
SS
2319 if (dir == 0)
2320 return (EEXIST);
2321 if (dir > 0) {
2322 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
2323 goto out;
2324 }
2325 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
2326 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
2327 goto out;
2328 }
2329 lbrt = LIST_NEXT(lbrt, brt_hash);
2330 } while (lbrt != NULL);
2331
2332#ifdef DIAGNOSTIC
2333 panic("bridge_rtnode_insert: impossible");
2334#endif
2335
d217f5e5 2336out:
ac93838f
SS
2337 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
2338 sc->sc_brtcnt++;
2339
2340 return (0);
2341}
2342
2343/*
2344 * bridge_rtnode_destroy:
2345 *
2346 * Destroy a bridge rtnode.
2347 */
d217f5e5 2348static void
ac93838f
SS
2349bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
2350{
2351
2352 LIST_REMOVE(brt, brt_hash);
2353
2354 LIST_REMOVE(brt, brt_list);
2355 sc->sc_brtcnt--;
efda3bd0 2356 kfree(brt, M_DEVBUF);
ac93838f
SS
2357}
2358
2359/*
2360 * Send bridge packets through pfil if they are one of the types pfil can deal
2361 * with, or if they are ARP or REVARP. (pfil will pass ARP and REVARP without
2362 * question.) If *bifp or *ifp are NULL then packet filtering is skipped for
2363 * that interface.
2364 */
3bf25ce1
SW
2365static int
2366bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
ac93838f 2367{
d217f5e5 2368 int snap, error, i, hlen;
ac93838f
SS
2369 struct ether_header *eh1, eh2;
2370 struct ip *ip;
2371 struct llc llc1;
2372 u_int16_t ether_type;
2373
2374 snap = 0;
2375 error = -1; /* Default error if not error == 0 */
2376
d217f5e5
SU
2377 if (pfil_bridge == 0 && pfil_member == 0)
2378 return (0); /* filtering is disabled */
2379
ac93838f
SS
2380 i = min((*mp)->m_pkthdr.len, max_protohdr);
2381 if ((*mp)->m_len < i) {
2382 *mp = m_pullup(*mp, i);
2383 if (*mp == NULL) {
4b1cf444 2384 kprintf("%s: m_pullup failed\n", __func__);
d217f5e5 2385 return (-1);
ac93838f
SS
2386 }
2387 }
2388
2389 eh1 = mtod(*mp, struct ether_header *);
2390 ether_type = ntohs(eh1->ether_type);
2391
2392 /*
2393 * Check for SNAP/LLC.
2394 */
2395 if (ether_type < ETHERMTU) {
2396 struct llc *llc2 = (struct llc *)(eh1 + 1);
2397
2398 if ((*mp)->m_len >= ETHER_HDR_LEN + 8 &&
2399 llc2->llc_dsap == LLC_SNAP_LSAP &&
2400 llc2->llc_ssap == LLC_SNAP_LSAP &&
2401 llc2->llc_control == LLC_UI) {
2402 ether_type = htons(llc2->llc_un.type_snap.ether_type);
2403 snap = 1;
2404 }
2405 }
2406
2407 /*
2408 * If we're trying to filter bridge traffic, don't look at anything
2409 * other than IP and ARP traffic. If the filter doesn't understand
2410 * IPv6, don't allow IPv6 through the bridge either. This is lame
2411 * since if we really wanted, say, an AppleTalk filter, we are hosed,
2412 * but of course we don't have an AppleTalk filter to begin with.
2413 * (Note that since pfil doesn't understand ARP it will pass *ALL*
2414 * ARP traffic.)
2415 */
2416 switch (ether_type) {
2417 case ETHERTYPE_ARP:
2418 case ETHERTYPE_REVARP:
d217f5e5 2419 return (0); /* Automatically pass */
ac93838f 2420 case ETHERTYPE_IP:
d217f5e5 2421#ifdef INET6
ac93838f 2422 case ETHERTYPE_IPV6:
d217f5e5 2423#endif /* INET6 */
ac93838f
SS
2424 break;
2425 default:
d217f5e5
SU
2426 /*
2427 * Check to see if the user wants to pass non-ip
2428 * packets, these will not be checked by pfil(9) and
2429 * passed unconditionally so the default is to drop.
2430 */
2431 if (pfil_onlyip)
2432 goto bad;
ac93838f
SS
2433 }
2434
2435 /* Strip off the Ethernet header and keep a copy. */
2436 m_copydata(*mp, 0, ETHER_HDR_LEN, (caddr_t) &eh2);
2437 m_adj(*mp, ETHER_HDR_LEN);
2438
2439 /* Strip off snap header, if present */
2440 if (snap) {
2441 m_copydata(*mp, 0, sizeof(struct llc), (caddr_t) &llc1);
2442 m_adj(*mp, sizeof(struct llc));
2443 }
2444
2445 /*
2446 * Check the IP header for alignment and errors
2447 */
2448 if (dir == PFIL_IN) {
2449 switch (ether_type) {
2450 case ETHERTYPE_IP:
2451 error = bridge_ip_checkbasic(mp);
2452 break;
d217f5e5 2453#ifdef INET6
ac93838f
SS
2454 case ETHERTYPE_IPV6:
2455 error = bridge_ip6_checkbasic(mp);
2456 break;
d217f5e5 2457#endif /* INET6 */
ac93838f
SS
2458 default:
2459 error = 0;
2460 }
2461 if (error)
2462 goto bad;
2463 }
2464
2465 error = 0;
2466
2467 /*
2468 * Run the packet through pfil
2469 */
2470 switch (ether_type)
2471 {
2472 case ETHERTYPE_IP :
2473 /*
2474 * before calling the firewall, swap fields the same as
2475 * IP does. here we assume the header is contiguous
2476 */
2477 ip = mtod(*mp, struct ip *);
2478
2479 ip->ip_len = ntohs(ip->ip_len);
2480 ip->ip_off = ntohs(ip->ip_off);
2481
2482 /*
2483 * Run pfil on the member interface and the bridge, both can
2484 * be skipped by clearing pfil_member or pfil_bridge.
2485 *
2486 * Keep the order:
2487 * in_if -> bridge_if -> out_if
2488 */
2489 if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
2490 error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
2491 dir);
2492
2493 if (*mp == NULL || error != 0) /* filter may consume */
2494 break;
2495
2496 if (pfil_member && ifp != NULL)
2497 error = pfil_run_hooks(&inet_pfil_hook, mp, ifp,
2498 dir);
2499
2500 if (*mp == NULL || error != 0) /* filter may consume */
2501 break;
2502
2503 if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
2504 error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
2505 dir);
2506
d217f5e5
SU
2507 if (*mp == NULL || error != 0) /* filter may consume */
2508 break;
2509
2510 /* check if we need to fragment the packet */
2511 if (pfil_member && ifp != NULL && dir == PFIL_OUT) {
2512 i = (*mp)->m_pkthdr.len;
2513 if (i > ifp->if_mtu) {
2514 error = bridge_fragment(ifp, *mp, &eh2, snap,
2515 &llc1);
2516 return (error);
2517 }
2518 }
2519
2520 /* Recalculate the ip checksum and restore byte ordering */
2521 ip = mtod(*mp, struct ip *);
2522 hlen = ip->ip_hl << 2;
2523 if (hlen < sizeof(struct ip))
2524 goto bad;
2525 if (hlen > (*mp)->m_len) {
2526 if ((*mp = m_pullup(*mp, hlen)) == 0)
2527 goto bad;
ac93838f 2528 ip = mtod(*mp, struct ip *);
d217f5e5
SU
2529 if (ip == NULL)
2530 goto bad;
ac93838f 2531 }
d217f5e5
SU
2532 ip->ip_len = htons(ip->ip_len);
2533 ip->ip_off = htons(ip->ip_off);
2534 ip->ip_sum = 0;
2535 if (hlen == sizeof(struct ip))
2536 ip->ip_sum = in_cksum_hdr(ip);
2537 else
2538 ip->ip_sum = in_cksum(*mp, hlen);
ac93838f
SS
2539
2540 break;
d217f5e5 2541#ifdef INET6
ac93838f
SS
2542 case ETHERTYPE_IPV6 :
2543 if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
2544 error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
2545 dir);
2546
2547 if (*mp == NULL || error != 0) /* filter may consume */
2548 break;
2549
2550 if (pfil_member && ifp != NULL)
2551 error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp,
2552 dir);
2553
2554 if (*mp == NULL || error != 0) /* filter may consume */
2555 break;
2556
2557 if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
2558 error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
2559 dir);
2560 break;
d217f5e5 2561#endif
ac93838f
SS
2562 default :
2563 error = 0;
2564 break;
2565 }
2566
2567 if (*mp == NULL)
d217f5e5 2568 return (error);
ac93838f
SS
2569 if (error != 0)
2570 goto bad;
2571
2572 error = -1;
2573
2574 /*
2575 * Finally, put everything back the way it was and return
2576 */
2577 if (snap) {
2578 M_PREPEND(*mp, sizeof(struct llc), MB_DONTWAIT);
2579 if (*mp == NULL)
d217f5e5 2580 return (error);
ac93838f
SS
2581 bcopy(&llc1, mtod(*mp, caddr_t), sizeof(struct llc));
2582 }
2583
2584 M_PREPEND(*mp, ETHER_HDR_LEN, MB_DONTWAIT);
2585 if (*mp == NULL)
d217f5e5 2586 return (error);
ac93838f
SS
2587 bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
2588
d217f5e5 2589 return (0);
ac93838f 2590
d217f5e5 2591bad:
ac93838f
SS
2592 m_freem(*mp);
2593 *mp = NULL;
d217f5e5 2594 return (error);
ac93838f
SS
2595}
2596
2597/*
2598 * Perform basic checks on header size since
2599 * pfil assumes ip_input has already processed
2600 * it for it. Cut-and-pasted from ip_input.c.
2601 * Given how simple the IPv6 version is,
2602 * does the IPv4 version really need to be
2603 * this complicated?
2604 *
2605 * XXX Should we update ipstat here, or not?
2606 * XXX Right now we update ipstat but not
2607 * XXX csum_counter.
2608 */
2609static int
2610bridge_ip_checkbasic(struct mbuf **mp)
2611{
2612 struct mbuf *m = *mp;
2613 struct ip *ip;
2614 int len, hlen;
2615 u_short sum;
2616
2617 if (*mp == NULL)
d217f5e5 2618 return (-1);
ac93838f
SS
2619#if notyet
2620 if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
2621 if ((m = m_copyup(m, sizeof(struct ip),
2622 (max_linkhdr + 3) & ~3)) == NULL) {
2623 /* XXXJRT new stat, please */
2624 ipstat.ips_toosmall++;
2625 goto bad;
2626 }
2627 } else
2628#endif
2629#ifndef __predict_false
2630#define __predict_false(x) x
2631#endif
2632 if (__predict_false(m->m_len < sizeof (struct ip))) {
2633 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
2634 ipstat.ips_toosmall++;
2635 goto bad;
2636 }
2637 }
2638 ip = mtod(m, struct ip *);
2639 if (ip == NULL) goto bad;
2640
2641 if (ip->ip_v != IPVERSION) {
2642 ipstat.ips_badvers++;
2643 goto bad;
2644 }
2645 hlen = ip->ip_hl << 2;
2646 if (hlen < sizeof(struct ip)) { /* minimum header length */
2647 ipstat.ips_badhlen++;
2648 goto bad;
2649 }
2650 if (hlen > m->m_len) {
2651 if ((m = m_pullup(m, hlen)) == 0) {
2652 ipstat.ips_badhlen++;
2653 goto bad;
2654 }
2655 ip = mtod(m, struct ip *);
2656 if (ip == NULL) goto bad;
2657 }
2658
2659 if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
2660 sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
2661 } else {
2662 if (hlen == sizeof(struct ip)) {
2663 sum = in_cksum_hdr(ip);
2664 } else {
2665 sum = in_cksum(m, hlen);
2666 }
2667 }
2668 if (sum) {
2669 ipstat.ips_badsum++;
2670 goto bad;
2671 }
2672
2673 /* Retrieve the packet length. */
2674 len = ntohs(ip->ip_len);
2675
2676 /*
2677 * Check for additional length bogosity
2678 */
2679 if (len < hlen) {
2680 ipstat.ips_badlen++;
2681 goto bad;
2682 }
2683
2684 /*
2685 * Check that the amount of data in the buffers
2686 * is as at least much as the IP header would have us expect.
2687 * Drop packet if shorter than we expect.
2688 */
2689 if (m->m_pkthdr.len < len) {
2690 ipstat.ips_tooshort++;
2691 goto bad;
2692 }
2693
2694 /* Checks out, proceed */
2695 *mp = m;
d217f5e5 2696 return (0);
ac93838f 2697
d217f5e5 2698bad:
ac93838f 2699 *mp = m;
d217f5e5 2700 return (-1);
ac93838f
SS
2701}
2702
d217f5e5 2703#ifdef INET6
ac93838f
SS
2704/*
2705 * Same as above, but for IPv6.
2706 * Cut-and-pasted from ip6_input.c.
2707 * XXX Should we update ip6stat, or not?
2708 */
2709static int
2710bridge_ip6_checkbasic(struct mbuf **mp)
2711{
2712 struct mbuf *m = *mp;
2713 struct ip6_hdr *ip6;
2714
2715 /*
2716 * If the IPv6 header is not aligned, slurp it up into a new
2717 * mbuf with space for link headers, in the event we forward
2718 * it. Otherwise, if it is aligned, make sure the entire base
2719 * IPv6 header is in the first mbuf of the chain.
2720 */
2721#if notyet
2722 if (IP6_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
2723 struct ifnet *inifp = m->m_pkthdr.rcvif;
2724 if ((m = m_copyup(m, sizeof(struct ip6_hdr),
2725 (max_linkhdr + 3) & ~3)) == NULL) {
2726 /* XXXJRT new stat, please */
2727 ip6stat.ip6s_toosmall++;
2728 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2729 goto bad;
2730 }
2731 } else
2732#endif
d217f5e5 2733 if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) {
ac93838f
SS
2734 struct ifnet *inifp = m->m_pkthdr.rcvif;
2735 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
2736 ip6stat.ip6s_toosmall++;
2737 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
2738 goto bad;
2739 }
2740 }
2741
2742 ip6 = mtod(m, struct ip6_hdr *);
2743
2744 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
2745 ip6stat.ip6s_badvers++;
2746 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
2747 goto bad;
2748 }
2749
2750 /* Checks out, proceed */
2751 *mp = m;
d217f5e5 2752 return (0);
ac93838f 2753
d217f5e5 2754bad:
ac93838f 2755 *mp = m;
d217f5e5
SU
2756 return (-1);
2757}
2758#endif /* INET6 */
2759
2760/*
2761 * bridge_fragment:
2762 *
2763 * Return a fragmented mbuf chain.
2764 */
2765static int
2766bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
2767 int snap, struct llc *llc)
2768{
2769 struct mbuf *m0;
2770 struct ip *ip;
2771 int error = -1;
2772
2773 if (m->m_len < sizeof(struct ip) &&
2774 (m = m_pullup(m, sizeof(struct ip))) == NULL)
2775 goto out;
2776 ip = mtod(m, struct ip *);
2777
2778 error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist,
2779 CSUM_DELAY_IP);
2780 if (error)
2781 goto out;
2782
2783 /* walk the chain and re-add the Ethernet header */
2784 for (m0 = m; m0; m0 = m0->m_nextpkt) {
2785 if (error == 0) {
2786 if (snap) {
2787 M_PREPEND(m0, sizeof(struct llc), MB_DONTWAIT);
2788 if (m0 == NULL) {
2789 error = ENOBUFS;
2790 continue;
2791 }
2792 bcopy(llc, mtod(m0, caddr_t),
2793 sizeof(struct llc));
2794 }
2795 M_PREPEND(m0, ETHER_HDR_LEN, MB_DONTWAIT);
2796 if (m0 == NULL) {
2797 error = ENOBUFS;
2798 continue;
2799 }
2800 bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN);
2801 } else
2802 m_freem(m);
2803 }
2804
2805 if (error == 0)
2806 ipstat.ips_fragmented++;
2807
2808 return (error);
2809
2810out:
2811 if (m != NULL)
2812 m_freem(m);
2813 return (error);
ac93838f 2814}