]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if_bridge.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / bsd / net / if_bridge.c
CommitLineData
6d2010ae 1/*
5ba3f43e 2 * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
6d2010ae
A
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
316670eb 29/* $NetBSD: if_bridge.c,v 1.31 2005/06/01 19:45:34 jdc Exp $ */
6d2010ae
A
30/*
31 * Copyright 2001 Wasabi Systems, Inc.
32 * All rights reserved.
33 *
34 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed for the NetBSD Project by
47 * Wasabi Systems, Inc.
48 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
49 * or promote products derived from this software without specific prior
50 * written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
54 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
56 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 * POSSIBILITY OF SUCH DAMAGE.
63 */
64
65/*
66 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
67 * All rights reserved.
68 *
69 * Redistribution and use in source and binary forms, with or without
70 * modification, are permitted provided that the following conditions
71 * are met:
72 * 1. Redistributions of source code must retain the above copyright
73 * notice, this list of conditions and the following disclaimer.
74 * 2. Redistributions in binary form must reproduce the above copyright
75 * notice, this list of conditions and the following disclaimer in the
76 * documentation and/or other materials provided with the distribution.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
79 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
80 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
81 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
82 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
83 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
84 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
86 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
87 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
88 * POSSIBILITY OF SUCH DAMAGE.
89 *
90 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
91 */
92
93/*
94 * Network interface bridge support.
95 *
96 * TODO:
97 *
98 * - Currently only supports Ethernet-like interfaces (Ethernet,
99 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
100 * to bridge other types of interfaces (FDDI-FDDI, and maybe
101 * consider heterogenous bridges).
39236c6e
A
102 *
103 * - GIF isn't handled due to the lack of IPPROTO_ETHERIP support.
6d2010ae
A
104 */
105
106#include <sys/cdefs.h>
6d2010ae 107
39236c6e 108#define BRIDGE_DEBUG 1
6d2010ae
A
109
110#include <sys/param.h>
111#include <sys/mbuf.h>
112#include <sys/malloc.h>
113#include <sys/protosw.h>
114#include <sys/systm.h>
115#include <sys/time.h>
116#include <sys/socket.h> /* for net/if.h */
117#include <sys/sockio.h>
6d2010ae
A
118#include <sys/kernel.h>
119#include <sys/random.h>
120#include <sys/syslog.h>
121#include <sys/sysctl.h>
6d2010ae
A
122#include <sys/proc.h>
123#include <sys/lock.h>
6d2010ae
A
124#include <sys/mcache.h>
125
126#include <sys/kauth.h>
127
39236c6e
A
128#include <kern/thread_call.h>
129
6d2010ae
A
130#include <libkern/libkern.h>
131
132#include <kern/zalloc.h>
133
134#if NBPFILTER > 0
135#include <net/bpf.h>
136#endif
137#include <net/if.h>
6d2010ae
A
138#include <net/if_dl.h>
139#include <net/if_types.h>
140#include <net/if_var.h>
39236c6e 141#include <net/if_media.h>
5ba3f43e 142#include <net/net_api_stats.h>
6d2010ae
A
143
144#include <netinet/in.h> /* for struct arpcom */
145#include <netinet/in_systm.h>
146#include <netinet/in_var.h>
fe8ab488 147#define _IP_VHL
6d2010ae
A
148#include <netinet/ip.h>
149#include <netinet/ip_var.h>
39236c6e 150#if INET6
6d2010ae
A
151#include <netinet/ip6.h>
152#include <netinet6/ip6_var.h>
153#endif
154#ifdef DEV_CARP
155#include <netinet/ip_carp.h>
156#endif
6d2010ae
A
157#include <netinet/if_ether.h> /* for struct arpcom */
158#include <net/bridgestp.h>
159#include <net/if_bridgevar.h>
160#include <net/if_llc.h>
316670eb 161#if NVLAN > 0
6d2010ae 162#include <net/if_vlan_var.h>
316670eb 163#endif /* NVLAN > 0 */
6d2010ae
A
164
165#include <net/if_ether.h>
166#include <net/dlil.h>
167#include <net/kpi_interfacefilter.h>
168
169#include <net/route.h>
170#ifdef PFIL_HOOKS
171#include <netinet/ip_fw2.h>
172#include <netinet/ip_dummynet.h>
173#endif /* PFIL_HOOKS */
39236c6e
A
174#include <dev/random/randomdev.h>
175
fe8ab488
A
176#include <netinet/bootp.h>
177#include <netinet/dhcp.h>
178
5ba3f43e 179
39236c6e
A
180#if BRIDGE_DEBUG
181#define BR_DBGF_LIFECYCLE 0x0001
182#define BR_DBGF_INPUT 0x0002
5ba3f43e 183#define BR_DBGF_OUTPUT 0x0004
39236c6e
A
184#define BR_DBGF_RT_TABLE 0x0008
185#define BR_DBGF_DELAYED_CALL 0x0010
186#define BR_DBGF_IOCTL 0x0020
187#define BR_DBGF_MBUF 0x0040
188#define BR_DBGF_MCAST 0x0080
fe8ab488 189#define BR_DBGF_HOSTFILTER 0x0100
39236c6e
A
190#endif /* BRIDGE_DEBUG */
191
192#define _BRIDGE_LOCK(_sc) lck_mtx_lock(&(_sc)->sc_mtx)
193#define _BRIDGE_UNLOCK(_sc) lck_mtx_unlock(&(_sc)->sc_mtx)
194#define BRIDGE_LOCK_ASSERT_HELD(_sc) \
5ba3f43e 195 LCK_MTX_ASSERT(&(_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED)
39236c6e 196#define BRIDGE_LOCK_ASSERT_NOTHELD(_sc) \
5ba3f43e 197 LCK_MTX_ASSERT(&(_sc)->sc_mtx, LCK_MTX_ASSERT_NOTOWNED)
6d2010ae
A
198
199#if BRIDGE_DEBUG
200
39236c6e 201#define BR_LCKDBG_MAX 4
6d2010ae 202
39236c6e
A
203#define BRIDGE_LOCK(_sc) bridge_lock(_sc)
204#define BRIDGE_UNLOCK(_sc) bridge_unlock(_sc)
6d2010ae 205#define BRIDGE_LOCK2REF(_sc, _err) _err = bridge_lock2ref(_sc)
316670eb
A
206#define BRIDGE_UNREF(_sc) bridge_unref(_sc)
207#define BRIDGE_XLOCK(_sc) bridge_xlock(_sc)
208#define BRIDGE_XDROP(_sc) bridge_xdrop(_sc)
6d2010ae 209
39236c6e 210#else /* !BRIDGE_DEBUG */
6d2010ae 211
39236c6e
A
212#define BRIDGE_LOCK(_sc) _BRIDGE_LOCK(_sc)
213#define BRIDGE_UNLOCK(_sc) _BRIDGE_UNLOCK(_sc)
316670eb 214#define BRIDGE_LOCK2REF(_sc, _err) do { \
39236c6e 215 BRIDGE_LOCK_ASSERT_HELD(_sc); \
316670eb
A
216 if ((_sc)->sc_iflist_xcnt > 0) \
217 (_err) = EBUSY; \
218 else \
219 (_sc)->sc_iflist_ref++; \
39236c6e 220 _BRIDGE_UNLOCK(_sc); \
6d2010ae
A
221} while (0)
222#define BRIDGE_UNREF(_sc) do { \
39236c6e 223 _BRIDGE_LOCK(_sc); \
6d2010ae
A
224 (_sc)->sc_iflist_ref--; \
225 if (((_sc)->sc_iflist_xcnt > 0) && ((_sc)->sc_iflist_ref == 0)) { \
39236c6e 226 _BRIDGE_UNLOCK(_sc); \
316670eb
A
227 wakeup(&(_sc)->sc_cv); \
228 } else \
39236c6e 229 _BRIDGE_UNLOCK(_sc); \
6d2010ae 230} while (0)
316670eb 231#define BRIDGE_XLOCK(_sc) do { \
39236c6e 232 BRIDGE_LOCK_ASSERT_HELD(_sc); \
316670eb
A
233 (_sc)->sc_iflist_xcnt++; \
234 while ((_sc)->sc_iflist_ref > 0) \
39236c6e 235 msleep(&(_sc)->sc_cv, &(_sc)->sc_mtx, PZERO, \
316670eb 236 "BRIDGE_XLOCK", NULL); \
6d2010ae 237} while (0)
316670eb 238#define BRIDGE_XDROP(_sc) do { \
39236c6e 239 BRIDGE_LOCK_ASSERT_HELD(_sc); \
316670eb 240 (_sc)->sc_iflist_xcnt--; \
6d2010ae
A
241} while (0)
242
243#endif /* BRIDGE_DEBUG */
244
245#if NBPFILTER > 0
39236c6e 246#define BRIDGE_BPF_MTAP_INPUT(sc, m) \
316670eb 247 if (sc->sc_bpf_input) \
6d2010ae
A
248 bridge_bpf_input(sc->sc_ifp, m)
249#else /* NBPFILTER */
39236c6e 250#define BRIDGE_BPF_MTAP_INPUT(ifp, m)
6d2010ae
A
251#endif /* NBPFILTER */
252
253/*
39236c6e 254 * Initial size of the route hash table. Must be a power of two.
6d2010ae 255 */
6d2010ae 256#ifndef BRIDGE_RTHASH_SIZE
39236c6e 257#define BRIDGE_RTHASH_SIZE 16
6d2010ae
A
258#endif
259
39236c6e
A
260/*
261 * Maximum size of the routing hash table
262 */
263#define BRIDGE_RTHASH_SIZE_MAX 2048
6d2010ae 264
39236c6e 265#define BRIDGE_RTHASH_MASK(sc) ((sc)->sc_rthash_size - 1)
6d2010ae
A
266
267/*
268 * Maximum number of addresses to cache.
269 */
270#ifndef BRIDGE_RTABLE_MAX
271#define BRIDGE_RTABLE_MAX 100
272#endif
273
274
275/*
276 * Timeout (in seconds) for entries learned dynamically.
277 */
278#ifndef BRIDGE_RTABLE_TIMEOUT
279#define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
280#endif
281
282/*
283 * Number of seconds between walks of the route list.
284 */
285#ifndef BRIDGE_RTABLE_PRUNE_PERIOD
286#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
287#endif
288
289/*
290 * List of capabilities to possibly mask on the member interface.
291 */
292#define BRIDGE_IFCAPS_MASK (IFCAP_TOE|IFCAP_TSO|IFCAP_TXCSUM)
293/*
294 * List of capabilities to disable on the member interface.
295 */
296#define BRIDGE_IFCAPS_STRIP IFCAP_LRO
297
298/*
299 * Bridge interface list entry.
300 */
301struct bridge_iflist {
302 TAILQ_ENTRY(bridge_iflist) bif_next;
303 struct ifnet *bif_ifp; /* member if */
304 struct bstp_port bif_stp; /* STP state */
39236c6e 305 uint32_t bif_ifflags; /* member if flags */
316670eb
A
306 int bif_savedcaps; /* saved capabilities */
307 uint32_t bif_addrmax; /* max # of addresses */
308 uint32_t bif_addrcnt; /* cur. # of addresses */
39236c6e 309 uint32_t bif_addrexceeded; /* # of address violations */
316670eb
A
310
311 interface_filter_t bif_iff_ref;
312 struct bridge_softc *bif_sc;
39236c6e 313 uint32_t bif_flags;
fe8ab488
A
314
315 struct in_addr bif_hf_ipsrc;
316 uint8_t bif_hf_hwsrc[ETHER_ADDR_LEN];
6d2010ae
A
317};
318
39236c6e
A
319#define BIFF_PROMISC 0x01 /* promiscuous mode set */
320#define BIFF_PROTO_ATTACHED 0x02 /* protocol attached */
321#define BIFF_FILTER_ATTACHED 0x04 /* interface filter attached */
322#define BIFF_MEDIA_ACTIVE 0x08 /* interface media active */
fe8ab488
A
323#define BIFF_HOST_FILTER 0x10 /* host filter enabled */
324#define BIFF_HF_HWSRC 0x20 /* host filter source MAC is set */
325#define BIFF_HF_IPSRC 0x40 /* host filter source IP is set */
39236c6e 326
6d2010ae
A
327/*
328 * Bridge route node.
329 */
330struct bridge_rtnode {
331 LIST_ENTRY(bridge_rtnode) brt_hash; /* hash table linkage */
332 LIST_ENTRY(bridge_rtnode) brt_list; /* list linkage */
333 struct bridge_iflist *brt_dst; /* destination if */
316670eb
A
334 unsigned long brt_expire; /* expiration time */
335 uint8_t brt_flags; /* address flags */
336 uint8_t brt_addr[ETHER_ADDR_LEN];
337 uint16_t brt_vlan; /* vlan id */
6d2010ae
A
338
339};
340#define brt_ifp brt_dst->bif_ifp
341
39236c6e
A
342/*
343 * Bridge delayed function call context
344 */
345typedef void (*bridge_delayed_func_t)(struct bridge_softc *);
346
347struct bridge_delayed_call {
348 struct bridge_softc *bdc_sc;
349 bridge_delayed_func_t bdc_func; /* Function to call */
350 struct timespec bdc_ts; /* Time to call */
351 u_int32_t bdc_flags;
fe8ab488 352 thread_call_t bdc_thread_call;
39236c6e
A
353};
354
355#define BDCF_OUTSTANDING 0x01 /* Delayed call has been scheduled */
356#define BDCF_CANCELLING 0x02 /* May be waiting for call completion */
357
5ba3f43e 358
6d2010ae
A
359/*
360 * Software state for each bridge.
361 */
39236c6e
A
362LIST_HEAD(_bridge_rtnode_list, bridge_rtnode);
363
5ba3f43e
A
364typedef struct {
365 struct _bridge_rtnode_list *bb_rthash; /* our forwarding table */
366 struct _bridge_rtnode_list bb_rtlist; /* list version of above */
367 uint32_t bb_rthash_key; /* key for hash */
368 uint32_t bb_rthash_size; /* size of the hash table */
369 struct bridge_delayed_call bb_aging_timer;
370 struct bridge_delayed_call bb_resize_call;
371 TAILQ_HEAD(, bridge_iflist) bb_spanlist; /* span ports list */
372 struct bstp_state bb_stp; /* STP state */
373 bpf_packet_func bb_bpf_input;
374 bpf_packet_func bb_bpf_output;
375} bridge_bsd, *bridge_bsd_t;
376
377#define sc_rthash sc_u.scu_bsd.bb_rthash
378#define sc_rtlist sc_u.scu_bsd.bb_rtlist
379#define sc_rthash_key sc_u.scu_bsd.bb_rthash_key
380#define sc_rthash_size sc_u.scu_bsd.bb_rthash_size
381#define sc_aging_timer sc_u.scu_bsd.bb_aging_timer
382#define sc_resize_call sc_u.scu_bsd.bb_resize_call
383#define sc_spanlist sc_u.scu_bsd.bb_spanlist
384#define sc_stp sc_u.scu_bsd.bb_stp
385#define sc_bpf_input sc_u.scu_bsd.bb_bpf_input
386#define sc_bpf_output sc_u.scu_bsd.bb_bpf_output
387
6d2010ae 388struct bridge_softc {
316670eb 389 struct ifnet *sc_ifp; /* make this an interface */
5ba3f43e
A
390 u_int32_t sc_flags;
391 union {
392 bridge_bsd scu_bsd;
393 } sc_u;
316670eb 394 LIST_ENTRY(bridge_softc) sc_list;
39236c6e 395 decl_lck_mtx_data(, sc_mtx);
316670eb
A
396 void *sc_cv;
397 uint32_t sc_brtmax; /* max # of addresses */
398 uint32_t sc_brtcnt; /* cur. # of addresses */
399 uint32_t sc_brttimeout; /* rt timeout in seconds */
400 uint32_t sc_iflist_ref; /* refcount for sc_iflist */
401 uint32_t sc_iflist_xcnt; /* refcount for sc_iflist */
402 TAILQ_HEAD(, bridge_iflist) sc_iflist; /* member interface list */
316670eb
A
403 uint32_t sc_brtexceeded; /* # of cache drops */
404 uint32_t sc_filter_flags; /* ipf and flags */
39236c6e
A
405 struct ifnet *sc_ifaddr; /* member mac copied from */
406 u_char sc_defaddr[6]; /* Default MAC address */
316670eb 407 char sc_if_xname[IFNAMSIZ];
6d2010ae
A
408
409#if BRIDGE_DEBUG
39236c6e
A
410 /*
411 * Locking and unlocking calling history
412 */
413 void *lock_lr[BR_LCKDBG_MAX];
316670eb 414 int next_lock_lr;
39236c6e 415 void *unlock_lr[BR_LCKDBG_MAX];
316670eb 416 int next_unlock_lr;
6d2010ae
A
417#endif /* BRIDGE_DEBUG */
418};
419
39236c6e
A
420#define SCF_DETACHING 0x01
421#define SCF_RESIZING 0x02
422#define SCF_MEDIA_ACTIVE 0x04
5ba3f43e
A
423#define SCF_BSD_MODE 0x08
424
425static inline void
426bridge_set_bsd_mode(struct bridge_softc * sc)
427{
428 sc->sc_flags |= SCF_BSD_MODE;
429}
430
431static inline boolean_t
432bridge_in_bsd_mode(const struct bridge_softc * sc)
433{
434 return ((sc->sc_flags & SCF_BSD_MODE) != 0);
435}
6d2010ae 436
fe8ab488
A
437struct bridge_hostfilter_stats bridge_hostfilter_stats;
438
39236c6e 439decl_lck_mtx_data(static, bridge_list_mtx);
6d2010ae 440
39236c6e 441static int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
6d2010ae 442
39236c6e 443static zone_t bridge_rtnode_pool = NULL;
6d2010ae
A
444
445static int bridge_clone_create(struct if_clone *, uint32_t, void *);
446static int bridge_clone_destroy(struct ifnet *);
447
448static errno_t bridge_ioctl(struct ifnet *, u_long, void *);
449#if HAS_IF_CAP
450static void bridge_mutecaps(struct bridge_softc *);
451static void bridge_set_ifcap(struct bridge_softc *, struct bridge_iflist *,
452 int);
453#endif
39236c6e 454static errno_t bridge_set_tso(struct bridge_softc *);
6d2010ae
A
455__private_extern__ void bridge_ifdetach(struct bridge_iflist *, struct ifnet *);
456static int bridge_init(struct ifnet *);
457#if HAS_BRIDGE_DUMMYNET
458static void bridge_dummynet(struct mbuf *, struct ifnet *);
459#endif
316670eb
A
460static void bridge_ifstop(struct ifnet *, int);
461static int bridge_output(struct ifnet *, struct mbuf *);
39236c6e 462static void bridge_finalize_cksum(struct ifnet *, struct mbuf *);
316670eb 463static void bridge_start(struct ifnet *);
6d2010ae
A
464__private_extern__ errno_t bridge_input(struct ifnet *, struct mbuf *, void *);
465#if BRIDGE_MEMBER_OUT_FILTER
39236c6e
A
466static errno_t bridge_iff_output(void *, ifnet_t, protocol_family_t,
467 mbuf_t *);
316670eb
A
468static int bridge_member_output(struct ifnet *, struct mbuf *,
469 struct sockaddr *, struct rtentry *);
6d2010ae 470#endif
316670eb 471static int bridge_enqueue(struct bridge_softc *, struct ifnet *,
6d2010ae
A
472 struct mbuf *);
473static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp, int);
474
475static void bridge_forward(struct bridge_softc *, struct bridge_iflist *,
39236c6e 476 struct mbuf *);
6d2010ae 477
39236c6e 478static void bridge_aging_timer(struct bridge_softc *sc);
6d2010ae
A
479
480static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
481 struct mbuf *, int);
482static void bridge_span(struct bridge_softc *, struct mbuf *);
483
484static int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
485 uint16_t, struct bridge_iflist *, int, uint8_t);
486static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *,
487 uint16_t);
488static void bridge_rttrim(struct bridge_softc *);
489static void bridge_rtage(struct bridge_softc *);
490static void bridge_rtflush(struct bridge_softc *, int);
491static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *,
492 uint16_t);
493
494static int bridge_rtable_init(struct bridge_softc *);
495static void bridge_rtable_fini(struct bridge_softc *);
496
39236c6e
A
497static void bridge_rthash_resize(struct bridge_softc *);
498
6d2010ae
A
499static int bridge_rtnode_addr_cmp(const uint8_t *, const uint8_t *);
500static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
501 const uint8_t *, uint16_t);
39236c6e
A
502static int bridge_rtnode_hash(struct bridge_softc *,
503 struct bridge_rtnode *);
6d2010ae
A
504static int bridge_rtnode_insert(struct bridge_softc *,
505 struct bridge_rtnode *);
506static void bridge_rtnode_destroy(struct bridge_softc *,
507 struct bridge_rtnode *);
316670eb 508#if BRIDGESTP
6d2010ae
A
509static void bridge_rtable_expire(struct ifnet *, int);
510static void bridge_state_change(struct ifnet *, int);
316670eb 511#endif /* BRIDGESTP */
6d2010ae
A
512
513static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
514 const char *name);
515static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
516 struct ifnet *ifp);
517static void bridge_delete_member(struct bridge_softc *,
518 struct bridge_iflist *, int);
519static void bridge_delete_span(struct bridge_softc *,
520 struct bridge_iflist *);
521
522static int bridge_ioctl_add(struct bridge_softc *, void *);
523static int bridge_ioctl_del(struct bridge_softc *, void *);
524static int bridge_ioctl_gifflags(struct bridge_softc *, void *);
525static int bridge_ioctl_sifflags(struct bridge_softc *, void *);
526static int bridge_ioctl_scache(struct bridge_softc *, void *);
527static int bridge_ioctl_gcache(struct bridge_softc *, void *);
528static int bridge_ioctl_gifs32(struct bridge_softc *, void *);
529static int bridge_ioctl_gifs64(struct bridge_softc *, void *);
530static int bridge_ioctl_rts32(struct bridge_softc *, void *);
531static int bridge_ioctl_rts64(struct bridge_softc *, void *);
532static int bridge_ioctl_saddr32(struct bridge_softc *, void *);
533static int bridge_ioctl_saddr64(struct bridge_softc *, void *);
534static int bridge_ioctl_sto(struct bridge_softc *, void *);
535static int bridge_ioctl_gto(struct bridge_softc *, void *);
536static int bridge_ioctl_daddr32(struct bridge_softc *, void *);
537static int bridge_ioctl_daddr64(struct bridge_softc *, void *);
538static int bridge_ioctl_flush(struct bridge_softc *, void *);
539static int bridge_ioctl_gpri(struct bridge_softc *, void *);
540static int bridge_ioctl_spri(struct bridge_softc *, void *);
541static int bridge_ioctl_ght(struct bridge_softc *, void *);
542static int bridge_ioctl_sht(struct bridge_softc *, void *);
543static int bridge_ioctl_gfd(struct bridge_softc *, void *);
544static int bridge_ioctl_sfd(struct bridge_softc *, void *);
545static int bridge_ioctl_gma(struct bridge_softc *, void *);
546static int bridge_ioctl_sma(struct bridge_softc *, void *);
547static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
548static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
549static int bridge_ioctl_sifmaxaddr(struct bridge_softc *, void *);
550static int bridge_ioctl_addspan(struct bridge_softc *, void *);
551static int bridge_ioctl_delspan(struct bridge_softc *, void *);
552static int bridge_ioctl_gbparam32(struct bridge_softc *, void *);
553static int bridge_ioctl_gbparam64(struct bridge_softc *, void *);
554static int bridge_ioctl_grte(struct bridge_softc *, void *);
555static int bridge_ioctl_gifsstp32(struct bridge_softc *, void *);
556static int bridge_ioctl_gifsstp64(struct bridge_softc *, void *);
557static int bridge_ioctl_sproto(struct bridge_softc *, void *);
558static int bridge_ioctl_stxhc(struct bridge_softc *, void *);
39236c6e 559static int bridge_ioctl_purge(struct bridge_softc *sc, void *);
6d2010ae
A
560static int bridge_ioctl_gfilt(struct bridge_softc *, void *);
561static int bridge_ioctl_sfilt(struct bridge_softc *, void *);
fe8ab488
A
562static int bridge_ioctl_ghostfilter(struct bridge_softc *, void *);
563static int bridge_ioctl_shostfilter(struct bridge_softc *, void *);
6d2010ae
A
564#ifdef PFIL_HOOKS
565static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *,
566 int);
39236c6e 567static int bridge_ip_checkbasic(struct mbuf **);
6d2010ae 568#ifdef INET6
39236c6e 569static int bridge_ip6_checkbasic(struct mbuf **);
6d2010ae
A
570#endif /* INET6 */
571static int bridge_fragment(struct ifnet *, struct mbuf *,
572 struct ether_header *, int, struct llc *);
573#endif /* PFIL_HOOKS */
574
39236c6e
A
575static errno_t bridge_set_bpf_tap(ifnet_t, bpf_tap_mode, bpf_packet_func);
576__private_extern__ errno_t bridge_bpf_input(ifnet_t, struct mbuf *);
577__private_extern__ errno_t bridge_bpf_output(ifnet_t, struct mbuf *);
6d2010ae 578
39236c6e
A
579static void bridge_detach(ifnet_t);
580static void bridge_link_event(struct ifnet *, u_int32_t);
581static void bridge_iflinkevent(struct ifnet *);
582static u_int32_t bridge_updatelinkstatus(struct bridge_softc *);
583static int interface_media_active(struct ifnet *);
584static void bridge_schedule_delayed_call(struct bridge_delayed_call *);
585static void bridge_cancel_delayed_call(struct bridge_delayed_call *);
fe8ab488
A
586static void bridge_cleanup_delayed_call(struct bridge_delayed_call *);
587static int bridge_host_filter(struct bridge_iflist *, struct mbuf *);
6d2010ae 588
5ba3f43e 589
39236c6e 590#define m_copypacket(m, how) m_copym(m, 0, M_COPYALL, how)
6d2010ae
A
591
592/* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */
593#define VLANTAGOF(_m) 0
594
316670eb 595u_int8_t bstp_etheraddr[ETHER_ADDR_LEN] =
39236c6e 596 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
316670eb 597
fe8ab488
A
598static u_int8_t ethernulladdr[ETHER_ADDR_LEN] =
599 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
600
316670eb 601#if BRIDGESTP
6d2010ae
A
602static struct bstp_cb_ops bridge_ops = {
603 .bcb_state = bridge_state_change,
604 .bcb_rtage = bridge_rtable_expire
605};
316670eb 606#endif /* BRIDGESTP */
6d2010ae
A
607
608SYSCTL_DECL(_net_link);
316670eb 609SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
39236c6e
A
610 "Bridge");
611
612static int bridge_inherit_mac = 0; /* share MAC with first bridge member */
613SYSCTL_INT(_net_link_bridge, OID_AUTO, inherit_mac,
614 CTLFLAG_RW|CTLFLAG_LOCKED,
615 &bridge_inherit_mac, 0,
616 "Inherit MAC address from the first bridge member");
617
618SYSCTL_INT(_net_link_bridge, OID_AUTO, rtable_prune_period,
619 CTLFLAG_RW|CTLFLAG_LOCKED,
620 &bridge_rtable_prune_period, 0,
621 "Interval between pruning of routing table");
622
623static unsigned int bridge_rtable_hash_size_max = BRIDGE_RTHASH_SIZE_MAX;
624SYSCTL_UINT(_net_link_bridge, OID_AUTO, rtable_hash_size_max,
625 CTLFLAG_RW|CTLFLAG_LOCKED,
626 &bridge_rtable_hash_size_max, 0,
627 "Maximum size of the routing hash table");
628
629#if BRIDGE_DEBUG_DELAYED_CALLBACK
630static int bridge_delayed_callback_delay = 0;
631SYSCTL_INT(_net_link_bridge, OID_AUTO, delayed_callback_delay,
632 CTLFLAG_RW|CTLFLAG_LOCKED,
633 &bridge_delayed_callback_delay, 0,
634 "Delay before calling delayed function");
635#endif
6d2010ae 636
5ba3f43e
A
637static int bridge_bsd_mode = 1;
638#if (DEVELOPMENT || DEBUG)
639SYSCTL_INT(_net_link_bridge, OID_AUTO, bsd_mode,
640 CTLFLAG_RW|CTLFLAG_LOCKED,
641 &bridge_bsd_mode, 0,
642 "Bridge using bsd mode");
643#endif /* (DEVELOPMENT || DEBUG) */
644
fe8ab488
A
645SYSCTL_STRUCT(_net_link_bridge, OID_AUTO,
646 hostfilterstats, CTLFLAG_RD | CTLFLAG_LOCKED,
647 &bridge_hostfilter_stats, bridge_hostfilter_stats, "");
648
6d2010ae
A
649#if defined(PFIL_HOOKS)
650static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */
651static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */
652static int pfil_member = 1; /* run pfil hooks on the member interface */
653static int pfil_ipfw = 0; /* layer2 filter with ipfw */
654static int pfil_ipfw_arp = 0; /* layer2 filter with ipfw */
39236c6e
A
655static int pfil_local_phys = 0; /* run pfil hooks on the physical interface */
656 /* for locally destined packets */
316670eb 657SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW|CTLFLAG_LOCKED,
39236c6e 658 &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled");
316670eb 659SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW|CTLFLAG_LOCKED,
39236c6e 660 &pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2");
316670eb 661SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW|CTLFLAG_LOCKED,
39236c6e 662 &pfil_bridge, 0, "Packet filter on the bridge interface");
316670eb 663SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW|CTLFLAG_LOCKED,
39236c6e 664 &pfil_member, 0, "Packet filter on the member interface");
316670eb 665SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_local_phys,
39236c6e
A
666 CTLFLAG_RW|CTLFLAG_LOCKED, &pfil_local_phys, 0,
667 "Packet filter on the physical interface for locally destined packets");
6d2010ae
A
668#endif /* PFIL_HOOKS */
669
316670eb 670#if BRIDGESTP
6d2010ae
A
671static int log_stp = 0; /* log STP state changes */
672SYSCTL_INT(_net_link_bridge, OID_AUTO, log_stp, CTLFLAG_RW,
39236c6e 673 &log_stp, 0, "Log STP state changes");
316670eb 674#endif /* BRIDGESTP */
6d2010ae
A
675
676struct bridge_control {
316670eb 677 int (*bc_func)(struct bridge_softc *, void *);
6d2010ae
A
678 unsigned int bc_argsize;
679 unsigned int bc_flags;
680};
681
682#define BC_F_COPYIN 0x01 /* copy arguments in */
683#define BC_F_COPYOUT 0x02 /* copy arguments out */
684#define BC_F_SUSER 0x04 /* do super-user check */
685
686static const struct bridge_control bridge_control_table32[] = {
fe8ab488 687 { bridge_ioctl_add, sizeof (struct ifbreq), /* 0 */
316670eb
A
688 BC_F_COPYIN|BC_F_SUSER },
689 { bridge_ioctl_del, sizeof (struct ifbreq),
690 BC_F_COPYIN|BC_F_SUSER },
691
692 { bridge_ioctl_gifflags, sizeof (struct ifbreq),
693 BC_F_COPYIN|BC_F_COPYOUT },
694 { bridge_ioctl_sifflags, sizeof (struct ifbreq),
695 BC_F_COPYIN|BC_F_SUSER },
696
697 { bridge_ioctl_scache, sizeof (struct ifbrparam),
698 BC_F_COPYIN|BC_F_SUSER },
699 { bridge_ioctl_gcache, sizeof (struct ifbrparam),
700 BC_F_COPYOUT },
701
702 { bridge_ioctl_gifs32, sizeof (struct ifbifconf32),
703 BC_F_COPYIN|BC_F_COPYOUT },
704 { bridge_ioctl_rts32, sizeof (struct ifbaconf32),
705 BC_F_COPYIN|BC_F_COPYOUT },
706
707 { bridge_ioctl_saddr32, sizeof (struct ifbareq32),
708 BC_F_COPYIN|BC_F_SUSER },
709
710 { bridge_ioctl_sto, sizeof (struct ifbrparam),
711 BC_F_COPYIN|BC_F_SUSER },
fe8ab488 712 { bridge_ioctl_gto, sizeof (struct ifbrparam), /* 10 */
316670eb
A
713 BC_F_COPYOUT },
714
715 { bridge_ioctl_daddr32, sizeof (struct ifbareq32),
716 BC_F_COPYIN|BC_F_SUSER },
717
718 { bridge_ioctl_flush, sizeof (struct ifbreq),
719 BC_F_COPYIN|BC_F_SUSER },
720
721 { bridge_ioctl_gpri, sizeof (struct ifbrparam),
722 BC_F_COPYOUT },
723 { bridge_ioctl_spri, sizeof (struct ifbrparam),
724 BC_F_COPYIN|BC_F_SUSER },
725
726 { bridge_ioctl_ght, sizeof (struct ifbrparam),
727 BC_F_COPYOUT },
728 { bridge_ioctl_sht, sizeof (struct ifbrparam),
729 BC_F_COPYIN|BC_F_SUSER },
730
731 { bridge_ioctl_gfd, sizeof (struct ifbrparam),
732 BC_F_COPYOUT },
733 { bridge_ioctl_sfd, sizeof (struct ifbrparam),
734 BC_F_COPYIN|BC_F_SUSER },
735
736 { bridge_ioctl_gma, sizeof (struct ifbrparam),
737 BC_F_COPYOUT },
fe8ab488 738 { bridge_ioctl_sma, sizeof (struct ifbrparam), /* 20 */
316670eb
A
739 BC_F_COPYIN|BC_F_SUSER },
740
741 { bridge_ioctl_sifprio, sizeof (struct ifbreq),
742 BC_F_COPYIN|BC_F_SUSER },
743
744 { bridge_ioctl_sifcost, sizeof (struct ifbreq),
745 BC_F_COPYIN|BC_F_SUSER },
746
747 { bridge_ioctl_gfilt, sizeof (struct ifbrparam),
748 BC_F_COPYOUT },
749 { bridge_ioctl_sfilt, sizeof (struct ifbrparam),
750 BC_F_COPYIN|BC_F_SUSER },
751
752 { bridge_ioctl_purge, sizeof (struct ifbreq),
753 BC_F_COPYIN|BC_F_SUSER },
754
755 { bridge_ioctl_addspan, sizeof (struct ifbreq),
6d2010ae 756 BC_F_COPYIN|BC_F_SUSER },
316670eb 757 { bridge_ioctl_delspan, sizeof (struct ifbreq),
6d2010ae 758 BC_F_COPYIN|BC_F_SUSER },
6d2010ae 759
316670eb
A
760 { bridge_ioctl_gbparam32, sizeof (struct ifbropreq32),
761 BC_F_COPYOUT },
6d2010ae 762
316670eb
A
763 { bridge_ioctl_grte, sizeof (struct ifbrparam),
764 BC_F_COPYOUT },
765
fe8ab488 766 { bridge_ioctl_gifsstp32, sizeof (struct ifbpstpconf32), /* 30 */
316670eb
A
767 BC_F_COPYIN|BC_F_COPYOUT },
768
769 { bridge_ioctl_sproto, sizeof (struct ifbrparam),
770 BC_F_COPYIN|BC_F_SUSER },
771
772 { bridge_ioctl_stxhc, sizeof (struct ifbrparam),
773 BC_F_COPYIN|BC_F_SUSER },
774
775 { bridge_ioctl_sifmaxaddr, sizeof (struct ifbreq),
776 BC_F_COPYIN|BC_F_SUSER },
fe8ab488
A
777
778 { bridge_ioctl_ghostfilter, sizeof (struct ifbrhostfilter),
779 BC_F_COPYIN|BC_F_COPYOUT },
780 { bridge_ioctl_shostfilter, sizeof (struct ifbrhostfilter),
781 BC_F_COPYIN|BC_F_SUSER },
6d2010ae
A
782};
783
784static const struct bridge_control bridge_control_table64[] = {
fe8ab488 785 { bridge_ioctl_add, sizeof (struct ifbreq), /* 0 */
316670eb
A
786 BC_F_COPYIN|BC_F_SUSER },
787 { bridge_ioctl_del, sizeof (struct ifbreq),
788 BC_F_COPYIN|BC_F_SUSER },
6d2010ae 789
316670eb
A
790 { bridge_ioctl_gifflags, sizeof (struct ifbreq),
791 BC_F_COPYIN|BC_F_COPYOUT },
792 { bridge_ioctl_sifflags, sizeof (struct ifbreq),
793 BC_F_COPYIN|BC_F_SUSER },
6d2010ae 794
316670eb
A
795 { bridge_ioctl_scache, sizeof (struct ifbrparam),
796 BC_F_COPYIN|BC_F_SUSER },
797 { bridge_ioctl_gcache, sizeof (struct ifbrparam),
798 BC_F_COPYOUT },
799
800 { bridge_ioctl_gifs64, sizeof (struct ifbifconf64),
801 BC_F_COPYIN|BC_F_COPYOUT },
802 { bridge_ioctl_rts64, sizeof (struct ifbaconf64),
803 BC_F_COPYIN|BC_F_COPYOUT },
804
805 { bridge_ioctl_saddr64, sizeof (struct ifbareq64),
806 BC_F_COPYIN|BC_F_SUSER },
807
808 { bridge_ioctl_sto, sizeof (struct ifbrparam),
809 BC_F_COPYIN|BC_F_SUSER },
fe8ab488 810 { bridge_ioctl_gto, sizeof (struct ifbrparam), /* 10 */
316670eb
A
811 BC_F_COPYOUT },
812
813 { bridge_ioctl_daddr64, sizeof (struct ifbareq64),
814 BC_F_COPYIN|BC_F_SUSER },
815
816 { bridge_ioctl_flush, sizeof (struct ifbreq),
817 BC_F_COPYIN|BC_F_SUSER },
818
819 { bridge_ioctl_gpri, sizeof (struct ifbrparam),
820 BC_F_COPYOUT },
821 { bridge_ioctl_spri, sizeof (struct ifbrparam),
822 BC_F_COPYIN|BC_F_SUSER },
823
824 { bridge_ioctl_ght, sizeof (struct ifbrparam),
825 BC_F_COPYOUT },
826 { bridge_ioctl_sht, sizeof (struct ifbrparam),
827 BC_F_COPYIN|BC_F_SUSER },
828
829 { bridge_ioctl_gfd, sizeof (struct ifbrparam),
830 BC_F_COPYOUT },
831 { bridge_ioctl_sfd, sizeof (struct ifbrparam),
832 BC_F_COPYIN|BC_F_SUSER },
833
834 { bridge_ioctl_gma, sizeof (struct ifbrparam),
835 BC_F_COPYOUT },
fe8ab488 836 { bridge_ioctl_sma, sizeof (struct ifbrparam), /* 20 */
316670eb
A
837 BC_F_COPYIN|BC_F_SUSER },
838
839 { bridge_ioctl_sifprio, sizeof (struct ifbreq),
840 BC_F_COPYIN|BC_F_SUSER },
841
842 { bridge_ioctl_sifcost, sizeof (struct ifbreq),
843 BC_F_COPYIN|BC_F_SUSER },
844
845 { bridge_ioctl_gfilt, sizeof (struct ifbrparam),
846 BC_F_COPYOUT },
847 { bridge_ioctl_sfilt, sizeof (struct ifbrparam),
848 BC_F_COPYIN|BC_F_SUSER },
849
850 { bridge_ioctl_purge, sizeof (struct ifbreq),
851 BC_F_COPYIN|BC_F_SUSER },
852
853 { bridge_ioctl_addspan, sizeof (struct ifbreq),
854 BC_F_COPYIN|BC_F_SUSER },
855 { bridge_ioctl_delspan, sizeof (struct ifbreq),
856 BC_F_COPYIN|BC_F_SUSER },
857
858 { bridge_ioctl_gbparam64, sizeof (struct ifbropreq64),
859 BC_F_COPYOUT },
860
861 { bridge_ioctl_grte, sizeof (struct ifbrparam),
862 BC_F_COPYOUT },
863
fe8ab488 864 { bridge_ioctl_gifsstp64, sizeof (struct ifbpstpconf64), /* 30 */
316670eb
A
865 BC_F_COPYIN|BC_F_COPYOUT },
866
867 { bridge_ioctl_sproto, sizeof (struct ifbrparam),
868 BC_F_COPYIN|BC_F_SUSER },
869
870 { bridge_ioctl_stxhc, sizeof (struct ifbrparam),
871 BC_F_COPYIN|BC_F_SUSER },
872
873 { bridge_ioctl_sifmaxaddr, sizeof (struct ifbreq),
874 BC_F_COPYIN|BC_F_SUSER },
fe8ab488
A
875
876 { bridge_ioctl_ghostfilter, sizeof (struct ifbrhostfilter),
877 BC_F_COPYIN|BC_F_COPYOUT },
878 { bridge_ioctl_shostfilter, sizeof (struct ifbrhostfilter),
879 BC_F_COPYIN|BC_F_SUSER },
6d2010ae
A
880};
881
882static const unsigned int bridge_control_table_size =
39236c6e 883 sizeof (bridge_control_table32) / sizeof (bridge_control_table32[0]);
6d2010ae 884
316670eb 885static LIST_HEAD(, bridge_softc) bridge_list =
39236c6e 886 LIST_HEAD_INITIALIZER(bridge_list);
6d2010ae
A
887
888static lck_grp_t *bridge_lock_grp = NULL;
889static lck_attr_t *bridge_lock_attr = NULL;
890
891static if_clone_t bridge_cloner = NULL;
892
316670eb
A
893static int if_bridge_txstart = 0;
894SYSCTL_INT(_net_link_bridge, OID_AUTO, txstart, CTLFLAG_RW | CTLFLAG_LOCKED,
39236c6e 895 &if_bridge_txstart, 0, "Bridge interface uses TXSTART model");
6d2010ae
A
896
897#if BRIDGE_DEBUG
316670eb
A
898static int if_bridge_debug = 0;
899SYSCTL_INT(_net_link_bridge, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_LOCKED,
39236c6e 900 &if_bridge_debug, 0, "Bridge debug");
6d2010ae 901
39236c6e
A
902static void printf_ether_header(struct ether_header *);
903static void printf_mbuf_data(mbuf_t, size_t, size_t);
904static void printf_mbuf_pkthdr(mbuf_t, const char *, const char *);
905static void printf_mbuf(mbuf_t, const char *, const char *);
5ba3f43e 906static void link_print(struct bridge_softc * sc);
6d2010ae
A
907
908static void bridge_lock(struct bridge_softc *);
909static void bridge_unlock(struct bridge_softc *);
910static int bridge_lock2ref(struct bridge_softc *);
911static void bridge_unref(struct bridge_softc *);
912static void bridge_xlock(struct bridge_softc *);
913static void bridge_xdrop(struct bridge_softc *);
914
316670eb
A
915static void
916bridge_lock(struct bridge_softc *sc)
6d2010ae
A
917{
918 void *lr_saved = __builtin_return_address(0);
316670eb 919
39236c6e 920 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
6d2010ae 921
39236c6e 922 _BRIDGE_LOCK(sc);
316670eb 923
6d2010ae
A
924 sc->lock_lr[sc->next_lock_lr] = lr_saved;
925 sc->next_lock_lr = (sc->next_lock_lr+1) % SO_LCKDBG_MAX;
926}
927
316670eb
A
928static void
929bridge_unlock(struct bridge_softc *sc)
6d2010ae
A
930{
931 void *lr_saved = __builtin_return_address(0);
316670eb 932
39236c6e 933 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
934
935 sc->unlock_lr[sc->next_unlock_lr] = lr_saved;
936 sc->next_unlock_lr = (sc->next_unlock_lr+1) % SO_LCKDBG_MAX;
316670eb 937
39236c6e 938 _BRIDGE_UNLOCK(sc);
6d2010ae
A
939}
940
316670eb
A
941static int
942bridge_lock2ref(struct bridge_softc *sc)
6d2010ae
A
943{
944 int error = 0;
945 void *lr_saved = __builtin_return_address(0);
316670eb 946
39236c6e 947 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
948
949 if (sc->sc_iflist_xcnt > 0)
950 error = EBUSY;
951 else
952 sc->sc_iflist_ref++;
953
954 sc->unlock_lr[sc->next_unlock_lr] = lr_saved;
955 sc->next_unlock_lr = (sc->next_unlock_lr+1) % SO_LCKDBG_MAX;
39236c6e
A
956
957 _BRIDGE_UNLOCK(sc);
316670eb
A
958
959 return (error);
6d2010ae
A
960}
961
316670eb
A
962static void
963bridge_unref(struct bridge_softc *sc)
6d2010ae
A
964{
965 void *lr_saved = __builtin_return_address(0);
966
39236c6e 967 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
6d2010ae 968
39236c6e 969 _BRIDGE_LOCK(sc);
6d2010ae
A
970 sc->lock_lr[sc->next_lock_lr] = lr_saved;
971 sc->next_lock_lr = (sc->next_lock_lr+1) % SO_LCKDBG_MAX;
972
973 sc->sc_iflist_ref--;
316670eb 974
6d2010ae
A
975 sc->unlock_lr[sc->next_unlock_lr] = lr_saved;
976 sc->next_unlock_lr = (sc->next_unlock_lr+1) % SO_LCKDBG_MAX;
316670eb 977 if ((sc->sc_iflist_xcnt > 0) && (sc->sc_iflist_ref == 0)) {
39236c6e 978 _BRIDGE_UNLOCK(sc);
6d2010ae
A
979 wakeup(&sc->sc_cv);
980 } else
39236c6e 981 _BRIDGE_UNLOCK(sc);
6d2010ae
A
982}
983
316670eb
A
984static void
985bridge_xlock(struct bridge_softc *sc)
6d2010ae
A
986{
987 void *lr_saved = __builtin_return_address(0);
988
39236c6e 989 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
990
991 sc->sc_iflist_xcnt++;
992 while (sc->sc_iflist_ref > 0) {
993 sc->unlock_lr[sc->next_unlock_lr] = lr_saved;
994 sc->next_unlock_lr = (sc->next_unlock_lr+1) % SO_LCKDBG_MAX;
316670eb 995
39236c6e 996 msleep(&sc->sc_cv, &sc->sc_mtx, PZERO, "BRIDGE_XLOCK", NULL);
6d2010ae
A
997
998 sc->lock_lr[sc->next_lock_lr] = lr_saved;
999 sc->next_lock_lr = (sc->next_lock_lr+1) % SO_LCKDBG_MAX;
1000 }
1001}
1002
316670eb
A
1003static void
1004bridge_xdrop(struct bridge_softc *sc)
6d2010ae 1005{
39236c6e 1006 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
1007
1008 sc->sc_iflist_xcnt--;
1009}
1010
1011void
1012printf_mbuf_pkthdr(mbuf_t m, const char *prefix, const char *suffix)
1013{
1014 if (m)
39236c6e
A
1015 printf("%spktlen: %u rcvif: 0x%llx header: 0x%llx "
1016 "nextpkt: 0x%llx%s",
316670eb 1017 prefix ? prefix : "", (unsigned int)mbuf_pkthdr_len(m),
39236c6e
A
1018 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_pkthdr_rcvif(m)),
1019 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_pkthdr_header(m)),
1020 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_nextpkt(m)),
1021 suffix ? suffix : "");
6d2010ae
A
1022 else
1023 printf("%s<NULL>%s\n", prefix, suffix);
1024}
1025
1026void
1027printf_mbuf(mbuf_t m, const char *prefix, const char *suffix)
1028{
1029 if (m) {
39236c6e
A
1030 printf("%s0x%llx type: %u flags: 0x%x len: %u data: 0x%llx "
1031 "maxlen: %u datastart: 0x%llx next: 0x%llx%s",
1032 prefix ? prefix : "", (uint64_t)VM_KERNEL_ADDRPERM(m),
1033 mbuf_type(m), mbuf_flags(m), (unsigned int)mbuf_len(m),
1034 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_data(m)),
1035 (unsigned int)mbuf_maxlen(m),
1036 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_datastart(m)),
1037 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_next(m)),
316670eb 1038 !suffix || (mbuf_flags(m) & MBUF_PKTHDR) ? "" : suffix);
6d2010ae
A
1039 if ((mbuf_flags(m) & MBUF_PKTHDR))
1040 printf_mbuf_pkthdr(m, " ", suffix);
1041 } else
1042 printf("%s<NULL>%s\n", prefix, suffix);
1043}
1044
1045void
1046printf_mbuf_data(mbuf_t m, size_t offset, size_t len)
1047{
1048 mbuf_t n;
1049 size_t i, j;
1050 size_t pktlen, mlen, maxlen;
1051 unsigned char *ptr;
316670eb 1052
6d2010ae 1053 pktlen = mbuf_pkthdr_len(m);
316670eb 1054
6d2010ae
A
1055 if (offset > pktlen)
1056 return;
316670eb 1057
fe8ab488 1058 maxlen = (pktlen - offset > len) ? len : pktlen - offset;
6d2010ae
A
1059 n = m;
1060 mlen = mbuf_len(n);
1061 ptr = mbuf_data(n);
1062 for (i = 0, j = 0; i < maxlen; i++, j++) {
1063 if (j >= mlen) {
1064 n = mbuf_next(n);
1065 if (n == 0)
1066 break;
1067 ptr = mbuf_data(n);
1068 mlen = mbuf_len(n);
1069 j = 0;
1070 }
1071 if (i >= offset) {
1072 printf("%02x%s", ptr[j], i % 2 ? " " : "");
1073 }
1074 }
6d2010ae
A
1075}
1076
1077static void
1078printf_ether_header(struct ether_header *eh)
1079{
316670eb
A
1080 printf("%02x:%02x:%02x:%02x:%02x:%02x > "
1081 "%02x:%02x:%02x:%02x:%02x:%02x 0x%04x ",
1082 eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],
1083 eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5],
1084 eh->ether_dhost[0], eh->ether_dhost[1], eh->ether_dhost[2],
1085 eh->ether_dhost[3], eh->ether_dhost[4], eh->ether_dhost[5],
39236c6e 1086 ntohs(eh->ether_type));
6d2010ae
A
1087}
1088
1089static void
5ba3f43e 1090link_print(struct bridge_softc * sc)
6d2010ae
A
1091{
1092 int i;
5ba3f43e
A
1093 uint32_t sdl_buffer[offsetof(struct sockaddr_dl, sdl_data) +
1094 IFNAMSIZ + ETHER_ADDR_LEN];
1095 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sdl_buffer;
1096
1097 memset(sdl, 0, sizeof (sdl_buffer));
1098 sdl->sdl_family = AF_LINK;
1099 sdl->sdl_nlen = strlen(sc->sc_if_xname);
1100 sdl->sdl_alen = ETHER_ADDR_LEN;
1101 sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data);
1102 memcpy(sdl->sdl_data, sc->sc_if_xname, sdl->sdl_nlen);
1103 memcpy(LLADDR(sdl), sc->sc_defaddr, ETHER_ADDR_LEN);
316670eb 1104
6d2010ae
A
1105#if 1
1106 printf("sdl len %d index %d family %d type 0x%x nlen %d alen %d"
5ba3f43e
A
1107 " slen %d addr ", sdl->sdl_len, sdl->sdl_index,
1108 sdl->sdl_family, sdl->sdl_type, sdl->sdl_nlen,
1109 sdl->sdl_alen, sdl->sdl_slen);
6d2010ae 1110#endif
5ba3f43e
A
1111 for (i = 0; i < sdl->sdl_alen; i++)
1112 printf("%s%x", i ? ":" : "", (CONST_LLADDR(sdl))[i]);
6d2010ae 1113 printf("\n");
6d2010ae
A
1114}
1115
1116#endif /* BRIDGE_DEBUG */
1117
1118/*
1119 * bridgeattach:
1120 *
1121 * Pseudo-device attach routine.
1122 */
1123__private_extern__ int
39236c6e 1124bridgeattach(int n)
6d2010ae 1125{
39236c6e 1126#pragma unused(n)
6d2010ae
A
1127 int error;
1128 lck_grp_attr_t *lck_grp_attr = NULL;
1129 struct ifnet_clone_params ifnet_clone_params;
316670eb
A
1130
1131 bridge_rtnode_pool = zinit(sizeof (struct bridge_rtnode),
1132 1024 * sizeof (struct bridge_rtnode), 0, "bridge_rtnode");
6d2010ae
A
1133 zone_change(bridge_rtnode_pool, Z_CALLERACCT, FALSE);
1134
1135 lck_grp_attr = lck_grp_attr_alloc_init();
316670eb 1136
6d2010ae 1137 bridge_lock_grp = lck_grp_alloc_init("if_bridge", lck_grp_attr);
316670eb 1138
6d2010ae 1139 bridge_lock_attr = lck_attr_alloc_init();
316670eb 1140
6d2010ae
A
1141#if BRIDGE_DEBUG
1142 lck_attr_setdebug(bridge_lock_attr);
1143#endif
1144
39236c6e 1145 lck_mtx_init(&bridge_list_mtx, bridge_lock_grp, bridge_lock_attr);
316670eb
A
1146
1147 /* can free the attributes once we've allocated the group lock */
6d2010ae 1148 lck_grp_attr_free(lck_grp_attr);
316670eb 1149
6d2010ae 1150 LIST_INIT(&bridge_list);
316670eb
A
1151
1152#if BRIDGESTP
6d2010ae 1153 bstp_sys_init();
316670eb
A
1154#endif /* BRIDGESTP */
1155
6d2010ae
A
1156 ifnet_clone_params.ifc_name = "bridge";
1157 ifnet_clone_params.ifc_create = bridge_clone_create;
1158 ifnet_clone_params.ifc_destroy = bridge_clone_destroy;
316670eb 1159
6d2010ae
A
1160 error = ifnet_clone_attach(&ifnet_clone_params, &bridge_cloner);
1161 if (error != 0)
316670eb 1162 printf("%s: ifnet_clone_attach failed %d\n", __func__, error);
6d2010ae 1163
316670eb 1164 return (error);
6d2010ae
A
1165}
1166
1167#if defined(PFIL_HOOKS)
1168/*
1169 * handler for net.link.bridge.pfil_ipfw
1170 */
1171static int
1172sysctl_pfil_ipfw SYSCTL_HANDLER_ARGS
1173{
316670eb 1174#pragma unused(arg1, arg2)
6d2010ae
A
1175 int enable = pfil_ipfw;
1176 int error;
1177
1178 error = sysctl_handle_int(oidp, &enable, 0, req);
1179 enable = (enable) ? 1 : 0;
1180
1181 if (enable != pfil_ipfw) {
1182 pfil_ipfw = enable;
1183
1184 /*
1185 * Disable pfil so that ipfw doesnt run twice, if the user
1186 * really wants both then they can re-enable pfil_bridge and/or
1187 * pfil_member. Also allow non-ip packets as ipfw can filter by
1188 * layer2 type.
1189 */
1190 if (pfil_ipfw) {
1191 pfil_onlyip = 0;
1192 pfil_bridge = 0;
1193 pfil_member = 0;
1194 }
1195 }
1196
1197 return (error);
1198}
316670eb 1199
6d2010ae
A
1200SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW,
1201 &pfil_ipfw, 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW");
1202#endif /* PFIL_HOOKS */
1203
5ba3f43e
A
1204static errno_t
1205bridge_ifnet_set_attrs(struct ifnet * ifp)
1206{
1207 errno_t error;
1208
1209 error = ifnet_set_mtu(ifp, ETHERMTU);
1210 if (error != 0) {
1211 printf("%s: ifnet_set_mtu failed %d\n", __func__, error);
1212 goto done;
1213 }
1214 error = ifnet_set_addrlen(ifp, ETHER_ADDR_LEN);
1215 if (error != 0) {
1216 printf("%s: ifnet_set_addrlen failed %d\n", __func__, error);
1217 goto done;
1218 }
1219 error = ifnet_set_hdrlen(ifp, ETHER_HDR_LEN);
1220 if (error != 0) {
1221 printf("%s: ifnet_set_hdrlen failed %d\n", __func__, error);
1222 goto done;
1223 }
1224 error = ifnet_set_flags(ifp,
1225 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST,
1226 0xffff);
1227
1228 if (error != 0) {
1229 printf("%s: ifnet_set_flags failed %d\n", __func__, error);
1230 goto done;
1231 }
1232 done:
1233 return (error);
1234}
1235
6d2010ae
A
1236/*
1237 * bridge_clone_create:
1238 *
1239 * Create a new bridge instance.
1240 */
1241static int
39236c6e 1242bridge_clone_create(struct if_clone *ifc, uint32_t unit, void *params)
6d2010ae 1243{
39236c6e 1244#pragma unused(params)
6d2010ae 1245 struct ifnet *ifp = NULL;
39236c6e 1246 struct bridge_softc *sc, *sc2;
316670eb 1247 struct ifnet_init_eparams init_params;
6d2010ae 1248 errno_t error = 0;
39236c6e
A
1249 uint8_t eth_hostid[ETHER_ADDR_LEN];
1250 int fb, retry, has_hostid;
6d2010ae 1251
39236c6e 1252 sc = _MALLOC(sizeof (*sc), M_DEVBUF, M_WAITOK | M_ZERO);
6d2010ae 1253
39236c6e 1254 lck_mtx_init(&sc->sc_mtx, bridge_lock_grp, bridge_lock_attr);
6d2010ae
A
1255 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
1256 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
1257 sc->sc_filter_flags = IFBF_FILT_DEFAULT;
1258#ifndef BRIDGE_IPF
1259 /*
1260 * For backwards compatibility with previous behaviour...
1261 * Switch off filtering on the bridge itself if BRIDGE_IPF is
1262 * not defined.
1263 */
1264 sc->sc_filter_flags &= ~IFBF_FILT_USEIPF;
1265#endif
1266
5ba3f43e
A
1267 if (bridge_bsd_mode != 0) {
1268 bridge_set_bsd_mode(sc);
6d2010ae 1269 }
316670eb 1270
6d2010ae 1271 TAILQ_INIT(&sc->sc_iflist);
6d2010ae
A
1272
1273 /* use the interface name as the unique id for ifp recycle */
316670eb 1274 snprintf(sc->sc_if_xname, sizeof (sc->sc_if_xname), "%s%d",
39236c6e 1275 ifc->ifc_name, unit);
316670eb
A
1276 bzero(&init_params, sizeof (init_params));
1277 init_params.ver = IFNET_INIT_CURRENT_VERSION;
1278 init_params.len = sizeof (init_params);
5ba3f43e
A
1279 if (bridge_in_bsd_mode(sc)) {
1280 /* Initialize our routing table. */
1281 error = bridge_rtable_init(sc);
1282 if (error != 0) {
1283 printf("%s: bridge_rtable_init failed %d\n",
1284 __func__, error);
1285 goto done;
1286 }
1287 TAILQ_INIT(&sc->sc_spanlist);
1288 if (if_bridge_txstart) {
1289 init_params.start = bridge_start;
1290 } else {
1291 init_params.flags = IFNET_INIT_LEGACY;
1292 init_params.output = bridge_output;
1293 }
1294 init_params.set_bpf_tap = bridge_set_bpf_tap;
316670eb
A
1295 }
1296 init_params.uniqueid = sc->sc_if_xname;
1297 init_params.uniqueid_len = strlen(sc->sc_if_xname);
1298 init_params.sndq_maxlen = IFQ_MAXLEN;
1299 init_params.name = ifc->ifc_name;
1300 init_params.unit = unit;
1301 init_params.family = IFNET_FAMILY_ETHERNET;
1302 init_params.type = IFT_BRIDGE;
1303 init_params.demux = ether_demux;
1304 init_params.add_proto = ether_add_proto;
1305 init_params.del_proto = ether_del_proto;
1306 init_params.check_multi = ether_check_multi;
39236c6e 1307 init_params.framer_extended = ether_frameout_extended;
316670eb
A
1308 init_params.softc = sc;
1309 init_params.ioctl = bridge_ioctl;
316670eb
A
1310 init_params.detach = bridge_detach;
1311 init_params.broadcast_addr = etherbroadcastaddr;
1312 init_params.broadcast_len = ETHER_ADDR_LEN;
316670eb 1313
5ba3f43e
A
1314 if (bridge_in_bsd_mode(sc)) {
1315 error = ifnet_allocate_extended(&init_params, &ifp);
1316 if (error != 0) {
1317 printf("%s: ifnet_allocate failed %d\n",
1318 __func__, error);
1319 goto done;
1320 }
1321 sc->sc_ifp = ifp;
1322 error = bridge_ifnet_set_attrs(ifp);
1323 if (error != 0) {
1324 printf("%s: bridge_ifnet_set_attrs failed %d\n",
1325 __func__, error);
1326 goto done;
1327 }
6d2010ae
A
1328 }
1329
6d2010ae 1330 /*
39236c6e 1331 * Generate an ethernet address with a locally administered address.
6d2010ae
A
1332 *
1333 * Since we are using random ethernet addresses for the bridge, it is
1334 * possible that we might have address collisions, so make sure that
1335 * this hardware address isn't already in use on another bridge.
5ba3f43e 1336 * The first try uses the "hostid" and falls back to read_frandom();
39236c6e
A
1337 * for "hostid", we use the MAC address of the first-encountered
1338 * Ethernet-type interface that is currently configured.
6d2010ae 1339 */
39236c6e
A
1340 fb = 0;
1341 has_hostid = (uuid_get_ethernet(&eth_hostid[0]) == 0);
1342 for (retry = 1; retry != 0; ) {
1343 if (fb || has_hostid == 0) {
5ba3f43e 1344 read_frandom(&sc->sc_defaddr, ETHER_ADDR_LEN);
39236c6e
A
1345 sc->sc_defaddr[0] &= ~1; /* clear multicast bit */
1346 sc->sc_defaddr[0] |= 2; /* set the LAA bit */
1347 } else {
1348 bcopy(&eth_hostid[0], &sc->sc_defaddr,
1349 ETHER_ADDR_LEN);
1350 sc->sc_defaddr[0] &= ~1; /* clear multicast bit */
1351 sc->sc_defaddr[0] |= 2; /* set the LAA bit */
1352 sc->sc_defaddr[3] = /* stir it up a bit */
1353 ((sc->sc_defaddr[3] & 0x0f) << 4) |
1354 ((sc->sc_defaddr[3] & 0xf0) >> 4);
1355 /*
1356 * Mix in the LSB as it's actually pretty significant,
1357 * see rdar://14076061
1358 */
1359 sc->sc_defaddr[4] =
1360 (((sc->sc_defaddr[4] & 0x0f) << 4) |
fe8ab488 1361 ((sc->sc_defaddr[4] & 0xf0) >> 4)) ^
39236c6e
A
1362 sc->sc_defaddr[5];
1363 sc->sc_defaddr[5] = ifp->if_unit & 0xff;
6d2010ae 1364 }
316670eb 1365
39236c6e
A
1366 fb = 1;
1367 retry = 0;
1368 lck_mtx_lock(&bridge_list_mtx);
1369 LIST_FOREACH(sc2, &bridge_list, sc_list) {
1370 if (memcmp(sc->sc_defaddr,
1371 IF_LLADDR(sc2->sc_ifp), ETHER_ADDR_LEN) == 0)
1372 retry = 1;
1373 }
1374 lck_mtx_unlock(&bridge_list_mtx);
6d2010ae 1375 }
6d2010ae 1376
39236c6e 1377 sc->sc_flags &= ~SCF_MEDIA_ACTIVE;
316670eb 1378
6d2010ae 1379#if BRIDGE_DEBUG
39236c6e 1380 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
5ba3f43e 1381 link_print(sc);
6d2010ae 1382#endif
5ba3f43e
A
1383 if (bridge_in_bsd_mode(sc)) {
1384 error = ifnet_attach(ifp, NULL);
1385 if (error != 0) {
1386 printf("%s: ifnet_attach failed %d\n", __func__, error);
1387 goto done;
1388 }
6d2010ae 1389 }
316670eb 1390
39236c6e 1391 error = ifnet_set_lladdr_and_type(ifp, sc->sc_defaddr, ETHER_ADDR_LEN,
316670eb 1392 IFT_ETHER);
6d2010ae 1393 if (error != 0) {
316670eb
A
1394 printf("%s: ifnet_set_lladdr_and_type failed %d\n", __func__,
1395 error);
6d2010ae
A
1396 goto done;
1397 }
316670eb 1398
5ba3f43e
A
1399 if (bridge_in_bsd_mode(sc)) {
1400 ifnet_set_offload(ifp,
1401 IFNET_CSUM_IP | IFNET_CSUM_TCP | IFNET_CSUM_UDP |
1402 IFNET_CSUM_TCPIPV6 | IFNET_CSUM_UDPIPV6 | IFNET_MULTIPAGES);
1403 error = bridge_set_tso(sc);
1404 if (error != 0) {
1405 printf("%s: bridge_set_tso failed %d\n",
1406 __func__, error);
1407 goto done;
1408 }
316670eb 1409#if BRIDGESTP
5ba3f43e 1410 bstp_attach(&sc->sc_stp, &bridge_ops);
316670eb 1411#endif /* BRIDGESTP */
5ba3f43e 1412 }
6d2010ae 1413
39236c6e 1414 lck_mtx_lock(&bridge_list_mtx);
6d2010ae 1415 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
39236c6e 1416 lck_mtx_unlock(&bridge_list_mtx);
6d2010ae
A
1417
1418 /* attach as ethernet */
316670eb
A
1419 error = bpf_attach(ifp, DLT_EN10MB, sizeof (struct ether_header),
1420 NULL, NULL);
6d2010ae
A
1421
1422done:
1423 if (error != 0) {
316670eb 1424 printf("%s failed error %d\n", __func__, error);
6d2010ae
A
1425 /* Cleanup TBD */
1426 }
316670eb
A
1427
1428 return (error);
6d2010ae
A
1429}
1430
1431/*
1432 * bridge_clone_destroy:
1433 *
1434 * Destroy a bridge instance.
1435 */
1436static int
1437bridge_clone_destroy(struct ifnet *ifp)
1438{
1439 struct bridge_softc *sc = ifp->if_softc;
1440 struct bridge_iflist *bif;
1441 errno_t error;
1442
1443 BRIDGE_LOCK(sc);
1444 if ((sc->sc_flags & SCF_DETACHING)) {
1445 BRIDGE_UNLOCK(sc);
316670eb 1446 return (0);
6d2010ae
A
1447 }
1448 sc->sc_flags |= SCF_DETACHING;
1449
316670eb 1450 bridge_ifstop(ifp, 1);
6d2010ae 1451
5ba3f43e
A
1452 if (bridge_in_bsd_mode(sc)) {
1453 bridge_cancel_delayed_call(&sc->sc_resize_call);
39236c6e 1454
5ba3f43e
A
1455 bridge_cleanup_delayed_call(&sc->sc_resize_call);
1456 bridge_cleanup_delayed_call(&sc->sc_aging_timer);
1457 }
fe8ab488 1458
6d2010ae
A
1459 error = ifnet_set_flags(ifp, 0, IFF_UP);
1460 if (error != 0) {
316670eb 1461 printf("%s: ifnet_set_flags failed %d\n", __func__, error);
6d2010ae
A
1462 }
1463
1464 while ((bif = TAILQ_FIRST(&sc->sc_iflist)) != NULL)
1465 bridge_delete_member(sc, bif, 0);
1466
5ba3f43e
A
1467 if (bridge_in_bsd_mode(sc)) {
1468 while ((bif = TAILQ_FIRST(&sc->sc_spanlist)) != NULL) {
1469 bridge_delete_span(sc, bif);
1470 }
1471 BRIDGE_UNLOCK(sc);
6d2010ae
A
1472 }
1473
6d2010ae
A
1474 error = ifnet_detach(ifp);
1475 if (error != 0) {
5ba3f43e
A
1476 panic("%s: ifnet_detach(%p) failed %d\n",
1477 __func__, ifp, error);
6d2010ae 1478 }
316670eb 1479 return (0);
6d2010ae
A
1480}
1481
39236c6e 1482#define DRVSPEC do { \
316670eb
A
1483 if (ifd->ifd_cmd >= bridge_control_table_size) { \
1484 error = EINVAL; \
1485 break; \
1486 } \
1487 bc = &bridge_control_table[ifd->ifd_cmd]; \
1488 \
1489 if (cmd == SIOCGDRVSPEC && \
1490 (bc->bc_flags & BC_F_COPYOUT) == 0) { \
1491 error = EINVAL; \
1492 break; \
1493 } else if (cmd == SIOCSDRVSPEC && \
1494 (bc->bc_flags & BC_F_COPYOUT) != 0) { \
1495 error = EINVAL; \
1496 break; \
1497 } \
1498 \
1499 if (bc->bc_flags & BC_F_SUSER) { \
1500 error = kauth_authorize_generic(kauth_cred_get(), \
1501 KAUTH_GENERIC_ISSUSER); \
1502 if (error) \
1503 break; \
1504 } \
1505 \
1506 if (ifd->ifd_len != bc->bc_argsize || \
1507 ifd->ifd_len > sizeof (args)) { \
1508 error = EINVAL; \
1509 break; \
1510 } \
1511 \
1512 bzero(&args, sizeof (args)); \
1513 if (bc->bc_flags & BC_F_COPYIN) { \
1514 error = copyin(ifd->ifd_data, &args, ifd->ifd_len); \
1515 if (error) \
1516 break; \
1517 } \
1518 \
1519 BRIDGE_LOCK(sc); \
1520 error = (*bc->bc_func)(sc, &args); \
1521 BRIDGE_UNLOCK(sc); \
1522 if (error) \
1523 break; \
1524 \
1525 if (bc->bc_flags & BC_F_COPYOUT) \
1526 error = copyout(&args, ifd->ifd_data, ifd->ifd_len); \
6d2010ae
A
1527} while (0)
1528
6d2010ae
A
1529/*
1530 * bridge_ioctl:
1531 *
1532 * Handle a control request from the operator.
1533 */
1534static errno_t
1535bridge_ioctl(struct ifnet *ifp, u_long cmd, void *data)
1536{
1537 struct bridge_softc *sc = ifp->if_softc;
316670eb 1538 struct ifreq *ifr = (struct ifreq *)data;
39236c6e 1539 struct bridge_iflist *bif;
6d2010ae
A
1540 int error = 0;
1541
39236c6e 1542 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
6d2010ae
A
1543
1544#if BRIDGE_DEBUG
39236c6e
A
1545 if (if_bridge_debug & BR_DBGF_IOCTL)
1546 printf("%s: ifp %s cmd 0x%08lx (%c%c [%lu] %c %lu)\n",
1547 __func__, ifp->if_xname, cmd, (cmd & IOC_IN) ? 'I' : ' ',
316670eb
A
1548 (cmd & IOC_OUT) ? 'O' : ' ', IOCPARM_LEN(cmd),
1549 (char)IOCGROUP(cmd), cmd & 0xff);
39236c6e 1550#endif /* BRIDGE_DEBUG */
316670eb 1551
6d2010ae 1552 switch (cmd) {
316670eb 1553
6d2010ae
A
1554 case SIOCSIFADDR:
1555 case SIOCAIFADDR:
1556 ifnet_set_flags(ifp, IFF_UP, IFF_UP);
1557 break;
1558
1559 case SIOCGIFMEDIA32:
39236c6e
A
1560 case SIOCGIFMEDIA64: {
1561 struct ifmediareq *ifmr = (struct ifmediareq *)data;
1562 user_addr_t user_addr;
1563
1564 user_addr = (cmd == SIOCGIFMEDIA64) ?
1565 ((struct ifmediareq64 *)ifmr)->ifmu_ulist :
1566 CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
1567
1568 ifmr->ifm_status = IFM_AVALID;
1569 ifmr->ifm_mask = 0;
1570 ifmr->ifm_count = 1;
1571
1572 BRIDGE_LOCK(sc);
1573 if (!(sc->sc_flags & SCF_DETACHING) &&
1574 (sc->sc_flags & SCF_MEDIA_ACTIVE)) {
1575 ifmr->ifm_status |= IFM_ACTIVE;
1576 ifmr->ifm_active = ifmr->ifm_current =
1577 IFM_ETHER | IFM_AUTO;
1578 } else {
1579 ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
1580 }
1581 BRIDGE_UNLOCK(sc);
1582
1583 if (user_addr != USER_ADDR_NULL) {
1584 error = copyout(&ifmr->ifm_current, user_addr,
1585 sizeof (int));
1586 }
6d2010ae 1587 break;
39236c6e 1588 }
6d2010ae
A
1589
1590 case SIOCADDMULTI:
1591 case SIOCDELMULTI:
1592 break;
1593
1594 case SIOCSDRVSPEC32:
1595 case SIOCGDRVSPEC32: {
1596 union {
1597 struct ifbreq ifbreq;
1598 struct ifbifconf32 ifbifconf;
1599 struct ifbareq32 ifbareq;
1600 struct ifbaconf32 ifbaconf;
1601 struct ifbrparam ifbrparam;
1602 struct ifbropreq32 ifbropreq;
1603 } args;
316670eb
A
1604 struct ifdrv32 *ifd = (struct ifdrv32 *)data;
1605 const struct bridge_control *bridge_control_table =
1606 bridge_control_table32, *bc;
1607
6d2010ae
A
1608 DRVSPEC;
1609
1610 break;
1611 }
1612 case SIOCSDRVSPEC64:
1613 case SIOCGDRVSPEC64: {
1614 union {
1615 struct ifbreq ifbreq;
1616 struct ifbifconf64 ifbifconf;
1617 struct ifbareq64 ifbareq;
1618 struct ifbaconf64 ifbaconf;
1619 struct ifbrparam ifbrparam;
1620 struct ifbropreq64 ifbropreq;
1621 } args;
316670eb
A
1622 struct ifdrv64 *ifd = (struct ifdrv64 *)data;
1623 const struct bridge_control *bridge_control_table =
1624 bridge_control_table64, *bc;
1625
6d2010ae 1626 DRVSPEC;
316670eb 1627
6d2010ae
A
1628 break;
1629 }
1630
1631 case SIOCSIFFLAGS:
1632 if (!(ifp->if_flags & IFF_UP) &&
1633 (ifp->if_flags & IFF_RUNNING)) {
1634 /*
1635 * If interface is marked down and it is running,
1636 * then stop and disable it.
1637 */
1638 BRIDGE_LOCK(sc);
316670eb 1639 bridge_ifstop(ifp, 1);
6d2010ae
A
1640 BRIDGE_UNLOCK(sc);
1641 } else if ((ifp->if_flags & IFF_UP) &&
1642 !(ifp->if_flags & IFF_RUNNING)) {
1643 /*
1644 * If interface is marked up and it is stopped, then
1645 * start it.
1646 */
1647 BRIDGE_LOCK(sc);
1648 error = bridge_init(ifp);
1649 BRIDGE_UNLOCK(sc);
1650 }
1651 break;
1652
1653 case SIOCSIFLLADDR:
316670eb
A
1654 error = ifnet_set_lladdr(ifp, ifr->ifr_addr.sa_data,
1655 ifr->ifr_addr.sa_len);
6d2010ae 1656 if (error != 0)
39236c6e 1657 printf("%s: SIOCSIFLLADDR error %d\n", ifp->if_xname,
316670eb 1658 error);
6d2010ae
A
1659 break;
1660
1661 case SIOCSIFMTU:
39236c6e
A
1662 if (ifr->ifr_mtu < 576) {
1663 error = EINVAL;
1664 break;
1665 }
1666 BRIDGE_LOCK(sc);
1667 if (TAILQ_EMPTY(&sc->sc_iflist)) {
1668 sc->sc_ifp->if_mtu = ifr->ifr_mtu;
1669 BRIDGE_UNLOCK(sc);
1670 break;
1671 }
1672 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1673 if (bif->bif_ifp->if_mtu != (unsigned)ifr->ifr_mtu) {
1674 printf("%s: invalid MTU: %u(%s) != %d\n",
1675 sc->sc_ifp->if_xname,
1676 bif->bif_ifp->if_mtu,
1677 bif->bif_ifp->if_xname, ifr->ifr_mtu);
1678 error = EINVAL;
1679 break;
1680 }
1681 }
1682 if (!error)
1683 sc->sc_ifp->if_mtu = ifr->ifr_mtu;
1684 BRIDGE_UNLOCK(sc);
6d2010ae
A
1685 break;
1686
1687 default:
6d2010ae
A
1688 error = ether_ioctl(ifp, cmd, data);
1689#if BRIDGE_DEBUG
316670eb 1690 if (error != 0 && error != EOPNOTSUPP)
39236c6e 1691 printf("%s: ifp %s cmd 0x%08lx "
316670eb 1692 "(%c%c [%lu] %c %lu) failed error: %d\n",
39236c6e
A
1693 __func__, ifp->if_xname, cmd,
1694 (cmd & IOC_IN) ? 'I' : ' ',
316670eb
A
1695 (cmd & IOC_OUT) ? 'O' : ' ',
1696 IOCPARM_LEN(cmd), (char)IOCGROUP(cmd),
1697 cmd & 0xff, error);
6d2010ae
A
1698#endif /* BRIDGE_DEBUG */
1699 break;
1700 }
39236c6e 1701 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
6d2010ae
A
1702
1703 return (error);
1704}
1705
1706#if HAS_IF_CAP
1707/*
1708 * bridge_mutecaps:
1709 *
1710 * Clear or restore unwanted capabilities on the member interface
1711 */
1712static void
1713bridge_mutecaps(struct bridge_softc *sc)
1714{
1715 struct bridge_iflist *bif;
1716 int enabled, mask;
1717
1718 /* Initial bitmask of capabilities to test */
1719 mask = BRIDGE_IFCAPS_MASK;
1720
1721 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1722 /* Every member must support it or its disabled */
1723 mask &= bif->bif_savedcaps;
1724 }
1725
1726 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1727 enabled = bif->bif_ifp->if_capenable;
1728 enabled &= ~BRIDGE_IFCAPS_STRIP;
1729 /* strip off mask bits and enable them again if allowed */
1730 enabled &= ~BRIDGE_IFCAPS_MASK;
1731 enabled |= mask;
1732
1733 bridge_set_ifcap(sc, bif, enabled);
1734 }
1735
1736}
1737
1738static void
1739bridge_set_ifcap(struct bridge_softc *sc, struct bridge_iflist *bif, int set)
1740{
1741 struct ifnet *ifp = bif->bif_ifp;
1742 struct ifreq ifr;
1743 int error;
1744
316670eb 1745 bzero(&ifr, sizeof (ifr));
6d2010ae
A
1746 ifr.ifr_reqcap = set;
1747
1748 if (ifp->if_capenable != set) {
1749 IFF_LOCKGIANT(ifp);
1750 error = (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr);
1751 IFF_UNLOCKGIANT(ifp);
1752 if (error)
39236c6e
A
1753 printf("%s: %s error setting interface capabilities "
1754 "on %s\n", __func__, sc->sc_ifp->if_xname,
1755 ifp->if_xname);
6d2010ae
A
1756 }
1757}
1758#endif /* HAS_IF_CAP */
1759
39236c6e
A
1760static errno_t
1761bridge_set_tso(struct bridge_softc *sc)
1762{
1763 struct bridge_iflist *bif;
1764 u_int32_t tso_v4_mtu;
1765 u_int32_t tso_v6_mtu;
1766 ifnet_offload_t offload;
1767 errno_t error = 0;
1768
1769 /* By default, support TSO */
1770 offload = sc->sc_ifp->if_hwassist | IFNET_TSO_IPV4 | IFNET_TSO_IPV6;
1771 tso_v4_mtu = IP_MAXPACKET;
1772 tso_v6_mtu = IP_MAXPACKET;
1773
1774 /* Use the lowest common denominator of the members */
1775 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1776 ifnet_t ifp = bif->bif_ifp;
1777
1778 if (ifp == NULL)
1779 continue;
1780
1781 if (offload & IFNET_TSO_IPV4) {
1782 if (ifp->if_hwassist & IFNET_TSO_IPV4) {
1783 if (tso_v4_mtu > ifp->if_tso_v4_mtu)
1784 tso_v4_mtu = ifp->if_tso_v4_mtu;
1785 } else {
1786 offload &= ~IFNET_TSO_IPV4;
1787 tso_v4_mtu = 0;
1788 }
1789 }
1790 if (offload & IFNET_TSO_IPV6) {
1791 if (ifp->if_hwassist & IFNET_TSO_IPV6) {
1792 if (tso_v6_mtu > ifp->if_tso_v6_mtu)
1793 tso_v6_mtu = ifp->if_tso_v6_mtu;
1794 } else {
1795 offload &= ~IFNET_TSO_IPV6;
1796 tso_v6_mtu = 0;
1797 }
1798 }
1799 }
1800
1801 if (offload != sc->sc_ifp->if_hwassist) {
1802 error = ifnet_set_offload(sc->sc_ifp, offload);
1803 if (error != 0) {
1804#if BRIDGE_DEBUG
1805 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
1806 printf("%s: ifnet_set_offload(%s, 0x%x) "
1807 "failed %d\n", __func__,
1808 sc->sc_ifp->if_xname, offload, error);
1809#endif /* BRIDGE_DEBUG */
1810 goto done;
1811 }
1812 /*
1813 * For ifnet_set_tso_mtu() sake, the TSO MTU must be at least
1814 * as large as the interface MTU
1815 */
1816 if (sc->sc_ifp->if_hwassist & IFNET_TSO_IPV4) {
1817 if (tso_v4_mtu < sc->sc_ifp->if_mtu)
1818 tso_v4_mtu = sc->sc_ifp->if_mtu;
1819 error = ifnet_set_tso_mtu(sc->sc_ifp, AF_INET,
1820 tso_v4_mtu);
1821 if (error != 0) {
1822#if BRIDGE_DEBUG
1823 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
1824 printf("%s: ifnet_set_tso_mtu(%s, "
1825 "AF_INET, %u) failed %d\n",
1826 __func__, sc->sc_ifp->if_xname,
1827 tso_v4_mtu, error);
1828#endif /* BRIDGE_DEBUG */
1829 goto done;
1830 }
1831 }
1832 if (sc->sc_ifp->if_hwassist & IFNET_TSO_IPV6) {
1833 if (tso_v6_mtu < sc->sc_ifp->if_mtu)
1834 tso_v6_mtu = sc->sc_ifp->if_mtu;
1835 error = ifnet_set_tso_mtu(sc->sc_ifp, AF_INET6,
1836 tso_v6_mtu);
1837 if (error != 0) {
1838#if BRIDGE_DEBUG
1839 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
1840 printf("%s: ifnet_set_tso_mtu(%s, "
1841 "AF_INET6, %u) failed %d\n",
1842 __func__, sc->sc_ifp->if_xname,
1843 tso_v6_mtu, error);
1844#endif /* BRIDGE_DEBUG */
1845 goto done;
1846 }
1847 }
1848 }
1849done:
1850 return (error);
1851}
1852
6d2010ae
A
1853/*
1854 * bridge_lookup_member:
1855 *
1856 * Lookup a bridge member interface.
1857 */
1858static struct bridge_iflist *
1859bridge_lookup_member(struct bridge_softc *sc, const char *name)
1860{
1861 struct bridge_iflist *bif;
1862 struct ifnet *ifp;
6d2010ae 1863
39236c6e 1864 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
1865
1866 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1867 ifp = bif->bif_ifp;
39236c6e 1868 if (strcmp(ifp->if_xname, name) == 0)
6d2010ae
A
1869 return (bif);
1870 }
1871
1872 return (NULL);
1873}
1874
1875/*
1876 * bridge_lookup_member_if:
1877 *
1878 * Lookup a bridge member interface by ifnet*.
1879 */
1880static struct bridge_iflist *
1881bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp)
1882{
1883 struct bridge_iflist *bif;
1884
39236c6e 1885 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
1886
1887 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
1888 if (bif->bif_ifp == member_ifp)
1889 return (bif);
1890 }
1891
1892 return (NULL);
1893}
1894
316670eb 1895static errno_t
39236c6e
A
1896bridge_iff_input(void *cookie, ifnet_t ifp, protocol_family_t protocol,
1897 mbuf_t *data, char **frame_ptr)
6d2010ae 1898{
39236c6e 1899#pragma unused(protocol)
6d2010ae
A
1900 errno_t error = 0;
1901 struct bridge_iflist *bif = (struct bridge_iflist *)cookie;
1902 struct bridge_softc *sc = bif->bif_sc;
1903 int included = 0;
1904 size_t frmlen = 0;
1905 mbuf_t m = *data;
1906
1907 if ((m->m_flags & M_PROTO1))
1908 goto out;
316670eb
A
1909
1910 if (*frame_ptr >= (char *)mbuf_datastart(m) &&
1911 *frame_ptr <= (char *)mbuf_data(m)) {
6d2010ae
A
1912 included = 1;
1913 frmlen = (char *)mbuf_data(m) - *frame_ptr;
1914 }
1915#if BRIDGE_DEBUG
39236c6e
A
1916 if (if_bridge_debug & BR_DBGF_INPUT) {
1917 printf("%s: %s from %s m 0x%llx data 0x%llx frame 0x%llx %s "
1918 "frmlen %lu\n", __func__, sc->sc_ifp->if_xname,
1919 ifp->if_xname, (uint64_t)VM_KERNEL_ADDRPERM(m),
1920 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_data(m)),
1921 (uint64_t)VM_KERNEL_ADDRPERM(*frame_ptr),
316670eb
A
1922 included ? "inside" : "outside", frmlen);
1923
39236c6e 1924 if (if_bridge_debug & BR_DBGF_MBUF) {
6d2010ae 1925 printf_mbuf(m, "bridge_iff_input[", "\n");
316670eb
A
1926 printf_ether_header((struct ether_header *)
1927 (void *)*frame_ptr);
6d2010ae
A
1928 printf_mbuf_data(m, 0, 20);
1929 printf("\n");
1930 }
1931 }
1932#endif /* BRIDGE_DEBUG */
1933
1934 /* Move data pointer to start of frame to the link layer header */
1935 if (included) {
316670eb
A
1936 (void) mbuf_setdata(m, (char *)mbuf_data(m) - frmlen,
1937 mbuf_len(m) + frmlen);
6d2010ae
A
1938 (void) mbuf_pkthdr_adjustlen(m, frmlen);
1939 } else {
316670eb 1940 printf("%s: frame_ptr outside mbuf\n", __func__);
6d2010ae
A
1941 goto out;
1942 }
316670eb 1943
6d2010ae 1944 error = bridge_input(ifp, m, *frame_ptr);
316670eb 1945
6d2010ae
A
1946 /* Adjust packet back to original */
1947 if (error == 0) {
316670eb
A
1948 (void) mbuf_setdata(m, (char *)mbuf_data(m) + frmlen,
1949 mbuf_len(m) - frmlen);
6d2010ae
A
1950 (void) mbuf_pkthdr_adjustlen(m, -frmlen);
1951 }
1952#if BRIDGE_DEBUG
39236c6e
A
1953 if ((if_bridge_debug & BR_DBGF_INPUT) &&
1954 (if_bridge_debug & BR_DBGF_MBUF)) {
6d2010ae
A
1955 printf("\n");
1956 printf_mbuf(m, "bridge_iff_input]", "\n");
1957 }
1958#endif /* BRIDGE_DEBUG */
1959
1960out:
39236c6e 1961 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
316670eb
A
1962
1963 return (error);
6d2010ae
A
1964}
1965
6d2010ae
A
1966#if BRIDGE_MEMBER_OUT_FILTER
1967static errno_t
39236c6e
A
1968bridge_iff_output(void *cookie, ifnet_t ifp, protocol_family_t protocol,
1969 mbuf_t *data)
6d2010ae 1970{
39236c6e 1971#pragma unused(protocol)
6d2010ae
A
1972 errno_t error = 0;
1973 struct bridge_iflist *bif = (struct bridge_iflist *)cookie;
1974 struct bridge_softc *sc = bif->bif_sc;
1975 mbuf_t m = *data;
316670eb 1976
6d2010ae
A
1977 if ((m->m_flags & M_PROTO1))
1978 goto out;
316670eb 1979
6d2010ae 1980#if BRIDGE_DEBUG
5ba3f43e 1981 if (if_bridge_debug & BR_DBGF_OUTPUT) {
39236c6e
A
1982 printf("%s: %s from %s m 0x%llx data 0x%llx\n", __func__,
1983 sc->sc_ifp->if_xname, ifp->if_xname,
1984 (uint64_t)VM_KERNEL_ADDRPERM(m),
1985 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_data(m)));
6d2010ae
A
1986 }
1987#endif /* BRIDGE_DEBUG */
1988
316670eb 1989 error = bridge_member_output(sc, ifp, m);
6d2010ae 1990 if (error != 0) {
316670eb
A
1991 printf("%s: bridge_member_output failed error %d\n", __func__,
1992 error);
6d2010ae
A
1993 }
1994
316670eb 1995out:
39236c6e 1996 BRIDGE_LOCK_ASSERT_NOTHELD(sc);
6d2010ae 1997
316670eb 1998 return (error);
6d2010ae
A
1999}
2000#endif /* BRIDGE_MEMBER_OUT_FILTER */
2001
316670eb 2002static void
39236c6e
A
2003bridge_iff_event(void *cookie, ifnet_t ifp, protocol_family_t protocol,
2004 const struct kev_msg *event_msg)
6d2010ae 2005{
39236c6e 2006#pragma unused(protocol)
6d2010ae 2007 struct bridge_iflist *bif = (struct bridge_iflist *)cookie;
39236c6e 2008 struct bridge_softc *sc = bif->bif_sc;
316670eb
A
2009
2010 if (event_msg->vendor_code == KEV_VENDOR_APPLE &&
39236c6e
A
2011 event_msg->kev_class == KEV_NETWORK_CLASS &&
2012 event_msg->kev_subclass == KEV_DL_SUBCLASS) {
2013#if BRIDGE_DEBUG
2014 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
2015 printf("%s: %s event_code %u - %s\n", __func__,
2016 ifp->if_xname, event_msg->event_code,
2017 dlil_kev_dl_code_str(event_msg->event_code));
2018#endif /* BRIDGE_DEBUG */
2019
6d2010ae
A
2020 switch (event_msg->event_code) {
2021 case KEV_DL_IF_DETACHING:
39236c6e 2022 case KEV_DL_IF_DETACHED: {
6d2010ae
A
2023 bridge_ifdetach(bif, ifp);
2024 break;
39236c6e 2025 }
6d2010ae
A
2026 case KEV_DL_LINK_OFF:
2027 case KEV_DL_LINK_ON: {
39236c6e 2028 bridge_iflinkevent(ifp);
316670eb 2029#if BRIDGESTP
6d2010ae 2030 bstp_linkstate(ifp, event_msg->event_code);
316670eb 2031#endif /* BRIDGESTP */
6d2010ae
A
2032 break;
2033 }
6d2010ae 2034 case KEV_DL_SIFFLAGS: {
39236c6e 2035 if ((bif->bif_flags & BIFF_PROMISC) == 0 &&
316670eb 2036 (ifp->if_flags & IFF_UP)) {
39236c6e
A
2037 errno_t error;
2038
2039 error = ifnet_set_promiscuous(ifp, 1);
6d2010ae 2040 if (error != 0) {
316670eb 2041 printf("%s: "
39236c6e
A
2042 "ifnet_set_promiscuous (%s)"
2043 " failed %d\n",
2044 __func__, ifp->if_xname,
2045 error);
6d2010ae 2046 } else {
39236c6e 2047 bif->bif_flags |= BIFF_PROMISC;
6d2010ae
A
2048 }
2049 }
2050 break;
2051 }
39236c6e
A
2052 case KEV_DL_IFCAP_CHANGED: {
2053 BRIDGE_LOCK(sc);
2054 bridge_set_tso(sc);
2055 BRIDGE_UNLOCK(sc);
2056 break;
2057 }
6d2010ae
A
2058 default:
2059 break;
2060 }
316670eb 2061 }
6d2010ae
A
2062}
2063
2064/*
2065 * bridge_iff_detached:
2066 *
2067 * Detach an interface from a bridge. Called when a member
2068 * interface is detaching.
2069 */
316670eb 2070static void
39236c6e 2071bridge_iff_detached(void *cookie, ifnet_t ifp)
6d2010ae
A
2072{
2073 struct bridge_iflist *bif = (struct bridge_iflist *)cookie;
2074
316670eb 2075#if BRIDGE_DEBUG
39236c6e
A
2076 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
2077 printf("%s: %s\n", __func__, ifp->if_xname);
2078#endif /* BRIDGE_DEBUG */
6d2010ae
A
2079
2080 bridge_ifdetach(bif, ifp);
2081
2082 _FREE(bif, M_DEVBUF);
6d2010ae
A
2083}
2084
2085static errno_t
39236c6e
A
2086bridge_proto_input(ifnet_t ifp, protocol_family_t protocol, mbuf_t packet,
2087 char *header)
6d2010ae 2088{
39236c6e
A
2089#pragma unused(protocol, packet, header)
2090#if BRIDGE_DEBUG
2091 printf("%s: unexpected packet from %s\n", __func__,
2092 ifp->if_xname);
2093#endif /* BRIDGE_DEBUG */
316670eb 2094 return (0);
6d2010ae
A
2095}
2096
2097static int
2098bridge_attach_protocol(struct ifnet *ifp)
2099{
316670eb 2100 int error;
6d2010ae
A
2101 struct ifnet_attach_proto_param reg;
2102
39236c6e
A
2103#if BRIDGE_DEBUG
2104 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
2105 printf("%s: %s\n", __func__, ifp->if_xname);
2106#endif /* BRIDGE_DEBUG */
316670eb
A
2107
2108 bzero(&reg, sizeof (reg));
6d2010ae 2109 reg.input = bridge_proto_input;
316670eb 2110
6d2010ae
A
2111 error = ifnet_attach_protocol(ifp, PF_BRIDGE, &reg);
2112 if (error)
39236c6e
A
2113 printf("%s: ifnet_attach_protocol(%s) failed, %d\n",
2114 __func__, ifp->if_xname, error);
6d2010ae
A
2115
2116 return (error);
2117}
2118
2119static int
2120bridge_detach_protocol(struct ifnet *ifp)
2121{
39236c6e 2122 int error;
6d2010ae 2123
39236c6e
A
2124#if BRIDGE_DEBUG
2125 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
2126 printf("%s: %s\n", __func__, ifp->if_xname);
2127#endif /* BRIDGE_DEBUG */
6d2010ae
A
2128 error = ifnet_detach_protocol(ifp, PF_BRIDGE);
2129 if (error)
39236c6e
A
2130 printf("%s: ifnet_detach_protocol(%s) failed, %d\n",
2131 __func__, ifp->if_xname, error);
6d2010ae
A
2132
2133 return (error);
2134}
2135
2136/*
2137 * bridge_delete_member:
2138 *
2139 * Delete the specified member interface.
2140 */
2141static void
2142bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif,
39236c6e 2143 int gone)
6d2010ae 2144{
39236c6e
A
2145 struct ifnet *ifs = bif->bif_ifp, *bifp = sc->sc_ifp;
2146 int lladdr_changed = 0, error, filt_attached;
2147 uint8_t eaddr[ETHER_ADDR_LEN];
2148 u_int32_t event_code = 0;
5ba3f43e 2149 boolean_t bsd_mode;
6d2010ae 2150
39236c6e
A
2151 BRIDGE_LOCK_ASSERT_HELD(sc);
2152 VERIFY(ifs != NULL);
6d2010ae 2153
5ba3f43e
A
2154 bsd_mode = bridge_in_bsd_mode(sc);
2155
04b8595b
A
2156 /*
2157 * First, remove the member from the list first so it cannot be found anymore
2158 * when we release the bridge lock below
2159 */
2160 BRIDGE_XLOCK(sc);
2161 TAILQ_REMOVE(&sc->sc_iflist, bif, bif_next);
2162 BRIDGE_XDROP(sc);
2163
6d2010ae
A
2164 if (!gone) {
2165 switch (ifs->if_type) {
2166 case IFT_ETHER:
2167 case IFT_L2VLAN:
2168 /*
2169 * Take the interface out of promiscuous mode.
2170 */
04b8595b
A
2171 if (bif->bif_flags & BIFF_PROMISC) {
2172 /*
2173 * Unlock to prevent deadlock with bridge_iff_event() in
2174 * case the driver generates an interface event
2175 */
2176 BRIDGE_UNLOCK(sc);
6d2010ae 2177 (void) ifnet_set_promiscuous(ifs, 0);
04b8595b
A
2178 BRIDGE_LOCK(sc);
2179 }
6d2010ae
A
2180 break;
2181
2182 case IFT_GIF:
39236c6e
A
2183 /* currently not supported */
2184 /* FALLTHRU */
6d2010ae 2185 default:
39236c6e
A
2186 VERIFY(0);
2187 /* NOTREACHED */
6d2010ae
A
2188 }
2189
2190#if HAS_IF_CAP
2191 /* reneable any interface capabilities */
2192 bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
2193#endif
2194 }
2195
39236c6e 2196 if (bif->bif_flags & BIFF_PROTO_ATTACHED) {
6d2010ae
A
2197 /* Respect lock ordering with DLIL lock */
2198 BRIDGE_UNLOCK(sc);
2199 (void) bridge_detach_protocol(ifs);
2200 BRIDGE_LOCK(sc);
2201 }
316670eb 2202#if BRIDGESTP
5ba3f43e 2203 if (bsd_mode && (bif->bif_ifflags & IFBIF_STP) != 0) {
6d2010ae 2204 bstp_disable(&bif->bif_stp);
5ba3f43e 2205 }
316670eb 2206#endif /* BRIDGESTP */
6d2010ae 2207
39236c6e
A
2208 /*
2209 * If removing the interface that gave the bridge its mac address, set
2210 * the mac address of the bridge to the address of the next member, or
2211 * to its default address if no members are left.
2212 */
2213 if (bridge_inherit_mac && sc->sc_ifaddr == ifs) {
2214 ifnet_release(sc->sc_ifaddr);
2215 if (TAILQ_EMPTY(&sc->sc_iflist)) {
2216 bcopy(sc->sc_defaddr, eaddr, ETHER_ADDR_LEN);
2217 sc->sc_ifaddr = NULL;
2218 } else {
2219 struct ifnet *fif =
2220 TAILQ_FIRST(&sc->sc_iflist)->bif_ifp;
2221 bcopy(IF_LLADDR(fif), eaddr, ETHER_ADDR_LEN);
2222 sc->sc_ifaddr = fif;
2223 ifnet_reference(fif); /* for sc_ifaddr */
2224 }
2225 lladdr_changed = 1;
2226 }
6d2010ae
A
2227
2228#if HAS_IF_CAP
39236c6e 2229 bridge_mutecaps(sc); /* recalculate now this interface is removed */
6d2010ae 2230#endif /* HAS_IF_CAP */
39236c6e
A
2231
2232 error = bridge_set_tso(sc);
2233 if (error != 0) {
2234 printf("%s: bridge_set_tso failed %d\n", __func__, error);
2235 }
2236
5ba3f43e
A
2237 if (bsd_mode) {
2238 bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
2239 }
2240
6d2010ae
A
2241 KASSERT(bif->bif_addrcnt == 0,
2242 ("%s: %d bridge routes referenced", __func__, bif->bif_addrcnt));
2243
39236c6e
A
2244 filt_attached = bif->bif_flags & BIFF_FILTER_ATTACHED;
2245
2246 /*
2247 * Update link status of the bridge based on its remaining members
2248 */
2249 event_code = bridge_updatelinkstatus(sc);
2250
5ba3f43e
A
2251 if (bsd_mode) {
2252 BRIDGE_UNLOCK(sc);
2253 }
39236c6e
A
2254
2255 if (lladdr_changed &&
2256 (error = ifnet_set_lladdr(bifp, eaddr, ETHER_ADDR_LEN)) != 0)
2257 printf("%s: ifnet_set_lladdr failed %d\n", __func__, error);
2258
2259 if (event_code != 0)
2260 bridge_link_event(bifp, event_code);
2261
2262#if BRIDGESTP
5ba3f43e
A
2263 if (bsd_mode) {
2264 bstp_destroy(&bif->bif_stp); /* prepare to free */
2265 }
316670eb
A
2266#endif /* BRIDGESTP */
2267
39236c6e 2268 if (filt_attached)
6d2010ae 2269 iflt_detach(bif->bif_iff_ref);
39236c6e 2270 else
6d2010ae 2271 _FREE(bif, M_DEVBUF);
39236c6e
A
2272
2273 ifs->if_bridge = NULL;
2274 ifnet_release(ifs);
2275
2276 BRIDGE_LOCK(sc);
6d2010ae
A
2277}
2278
2279/*
2280 * bridge_delete_span:
2281 *
2282 * Delete the specified span interface.
2283 */
2284static void
2285bridge_delete_span(struct bridge_softc *sc, struct bridge_iflist *bif)
2286{
39236c6e 2287 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
2288
2289 KASSERT(bif->bif_ifp->if_bridge == NULL,
2290 ("%s: not a span interface", __func__));
2291
2292 ifnet_release(bif->bif_ifp);
2293
2294 TAILQ_REMOVE(&sc->sc_spanlist, bif, bif_next);
2295 _FREE(bif, M_DEVBUF);
2296}
2297
2298static int
2299bridge_ioctl_add(struct bridge_softc *sc, void *arg)
2300{
2301 struct ifbreq *req = arg;
2302 struct bridge_iflist *bif = NULL;
39236c6e
A
2303 struct ifnet *ifs, *bifp = sc->sc_ifp;
2304 int error = 0, lladdr_changed = 0;
2305 uint8_t eaddr[ETHER_ADDR_LEN];
6d2010ae 2306 struct iff_filter iff;
39236c6e 2307 u_int32_t event_code = 0;
5ba3f43e 2308 boolean_t bsd_mode = bridge_in_bsd_mode(sc);
6d2010ae
A
2309
2310 ifs = ifunit(req->ifbr_ifsname);
2311 if (ifs == NULL)
2312 return (ENOENT);
2313 if (ifs->if_ioctl == NULL) /* must be supported */
2314 return (EINVAL);
2315
5ba3f43e
A
2316 if (bsd_mode) {
2317 /* If it's in the span list, it can't be a member. */
2318 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next)
2319 if (ifs == bif->bif_ifp)
2320 return (EBUSY);
2321 }
6d2010ae 2322
6d2010ae
A
2323 if (ifs->if_bridge == sc)
2324 return (EEXIST);
2325
2326 if (ifs->if_bridge != NULL)
2327 return (EBUSY);
2328
39236c6e
A
2329 switch (ifs->if_type) {
2330 case IFT_ETHER:
2331 case IFT_L2VLAN:
2332 /* permitted interface types */
2333 break;
2334 case IFT_GIF:
2335 /* currently not supported */
2336 /* FALLTHRU */
2337 default:
2338 return (EINVAL);
2339 }
2340
5ba3f43e 2341 bif = _MALLOC(sizeof (*bif), M_DEVBUF, M_WAITOK | M_ZERO);
6d2010ae
A
2342 if (bif == NULL)
2343 return (ENOMEM);
2344
2345 bif->bif_ifp = ifs;
39236c6e
A
2346 ifnet_reference(ifs);
2347 bif->bif_ifflags = IFBIF_LEARNING | IFBIF_DISCOVER;
6d2010ae
A
2348#if HAS_IF_CAP
2349 bif->bif_savedcaps = ifs->if_capenable;
2350#endif /* HAS_IF_CAP */
2351 bif->bif_sc = sc;
2352
39236c6e
A
2353 /* Allow the first Ethernet member to define the MTU */
2354 if (TAILQ_EMPTY(&sc->sc_iflist))
2355 sc->sc_ifp->if_mtu = ifs->if_mtu;
2356 else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
2357 printf("%s: %s: invalid MTU for %s", __func__,
2358 sc->sc_ifp->if_xname,
2359 ifs->if_xname);
2360 return (EINVAL);
2361 }
2362
2363 /*
2364 * Assign the interface's MAC address to the bridge if it's the first
2365 * member and the MAC address of the bridge has not been changed from
2366 * the default (randomly) generated one.
2367 */
2368 if (bridge_inherit_mac && TAILQ_EMPTY(&sc->sc_iflist) &&
2369 !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) {
2370 bcopy(IF_LLADDR(ifs), eaddr, ETHER_ADDR_LEN);
2371 sc->sc_ifaddr = ifs;
2372 ifnet_reference(ifs); /* for sc_ifaddr */
2373 lladdr_changed = 1;
2374 }
6d2010ae
A
2375
2376 ifs->if_bridge = sc;
316670eb 2377#if BRIDGESTP
5ba3f43e
A
2378 if (bsd_mode) {
2379 bstp_create(&sc->sc_stp, &bif->bif_stp, bif->bif_ifp);
2380 }
316670eb 2381#endif /* BRIDGESTP */
39236c6e 2382
6d2010ae
A
2383 /*
2384 * XXX: XLOCK HERE!?!
2385 */
2386 TAILQ_INSERT_TAIL(&sc->sc_iflist, bif, bif_next);
2387
2388#if HAS_IF_CAP
2389 /* Set interface capabilities to the intersection set of all members */
2390 bridge_mutecaps(sc);
2391#endif /* HAS_IF_CAP */
2392
39236c6e
A
2393 bridge_set_tso(sc);
2394
316670eb 2395
39236c6e
A
2396 /*
2397 * Place the interface into promiscuous mode.
2398 */
6d2010ae
A
2399 switch (ifs->if_type) {
2400 case IFT_ETHER:
2401 case IFT_L2VLAN:
6d2010ae
A
2402 error = ifnet_set_promiscuous(ifs, 1);
2403 if (error) {
2404 /* Ignore error when device is not up */
2405 if (error != ENETDOWN)
2406 goto out;
2407 error = 0;
2408 } else {
39236c6e 2409 bif->bif_flags |= BIFF_PROMISC;
6d2010ae
A
2410 }
2411 break;
2412
6d2010ae 2413 default:
39236c6e 2414 break;
6d2010ae
A
2415 }
2416
39236c6e
A
2417 /*
2418 * The new member may change the link status of the bridge interface
2419 */
2420 if (interface_media_active(ifs))
2421 bif->bif_flags |= BIFF_MEDIA_ACTIVE;
2422 else
2423 bif->bif_flags &= ~BIFF_MEDIA_ACTIVE;
2424
2425 event_code = bridge_updatelinkstatus(sc);
2426
2427 /*
6d2010ae
A
2428 * Respect lock ordering with DLIL lock for the following operations
2429 */
5ba3f43e
A
2430 if (bsd_mode) {
2431 BRIDGE_UNLOCK(sc);
2432 }
6d2010ae
A
2433
2434 /*
2435 * install an interface filter
2436 */
316670eb 2437 memset(&iff, 0, sizeof (struct iff_filter));
6d2010ae
A
2438 iff.iff_cookie = bif;
2439 iff.iff_name = "com.apple.kernel.bsd.net.if_bridge";
5ba3f43e
A
2440 if (bsd_mode) {
2441 iff.iff_input = bridge_iff_input;
6d2010ae 2442#if BRIDGE_MEMBER_OUT_FILTER
5ba3f43e 2443 iff.iff_output = bridge_iff_output;
6d2010ae 2444#endif /* BRIDGE_MEMBER_OUT_FILTER */
5ba3f43e 2445 }
6d2010ae
A
2446 iff.iff_event = bridge_iff_event;
2447 iff.iff_detached = bridge_iff_detached;
5ba3f43e
A
2448 error = dlil_attach_filter(ifs, &iff, &bif->bif_iff_ref,
2449 DLIL_IFF_TSO | DLIL_IFF_INTERNAL);
6d2010ae 2450 if (error != 0) {
316670eb 2451 printf("%s: iflt_attach failed %d\n", __func__, error);
6d2010ae
A
2452 BRIDGE_LOCK(sc);
2453 goto out;
2454 }
39236c6e 2455 bif->bif_flags |= BIFF_FILTER_ATTACHED;
6d2010ae
A
2456
2457 /*
2458 * install an dummy "bridge" protocol
2459 */
2460 if ((error = bridge_attach_protocol(ifs)) != 0) {
2461 if (error != 0) {
316670eb
A
2462 printf("%s: bridge_attach_protocol failed %d\n",
2463 __func__, error);
6d2010ae
A
2464 BRIDGE_LOCK(sc);
2465 goto out;
2466 }
2467 }
39236c6e
A
2468 bif->bif_flags |= BIFF_PROTO_ATTACHED;
2469
2470 if (lladdr_changed &&
2471 (error = ifnet_set_lladdr(bifp, eaddr, ETHER_ADDR_LEN)) != 0)
2472 printf("%s: ifnet_set_lladdr failed %d\n", __func__, error);
2473
2474 if (event_code != 0)
2475 bridge_link_event(bifp, event_code);
6d2010ae
A
2476
2477 BRIDGE_LOCK(sc);
2478
2479out:
2480 if (error && bif != NULL)
2481 bridge_delete_member(sc, bif, 1);
316670eb 2482
6d2010ae
A
2483 return (error);
2484}
2485
2486static int
2487bridge_ioctl_del(struct bridge_softc *sc, void *arg)
2488{
2489 struct ifbreq *req = arg;
2490 struct bridge_iflist *bif;
2491
2492 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
2493 if (bif == NULL)
2494 return (ENOENT);
2495
2496 bridge_delete_member(sc, bif, 0);
2497
2498 return (0);
2499}
2500
2501static int
39236c6e 2502bridge_ioctl_purge(struct bridge_softc *sc, void *arg)
316670eb 2503{
39236c6e 2504#pragma unused(sc, arg)
6d2010ae
A
2505 return (0);
2506}
2507
2508static int
2509bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
2510{
2511 struct ifbreq *req = arg;
2512 struct bridge_iflist *bif;
6d2010ae
A
2513
2514 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
2515 if (bif == NULL)
2516 return (ENOENT);
2517
5ba3f43e
A
2518 if (bridge_in_bsd_mode(sc)) {
2519 struct bstp_port *bp;
2520
2521 bp = &bif->bif_stp;
2522 req->ifbr_state = bp->bp_state;
2523 req->ifbr_priority = bp->bp_priority;
2524 req->ifbr_path_cost = bp->bp_path_cost;
2525 req->ifbr_proto = bp->bp_protover;
2526 req->ifbr_role = bp->bp_role;
2527 req->ifbr_stpflags = bp->bp_flags;
2528 /* Copy STP state options as flags */
2529 if (bp->bp_operedge)
2530 req->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
2531 if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
2532 req->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
2533 if (bp->bp_ptp_link)
2534 req->ifbr_ifsflags |= IFBIF_BSTP_PTP;
2535 if (bp->bp_flags & BSTP_PORT_AUTOPTP)
2536 req->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
2537 if (bp->bp_flags & BSTP_PORT_ADMEDGE)
2538 req->ifbr_ifsflags |= IFBIF_BSTP_ADMEDGE;
2539 if (bp->bp_flags & BSTP_PORT_ADMCOST)
2540 req->ifbr_ifsflags |= IFBIF_BSTP_ADMCOST;
2541 }
39236c6e 2542 req->ifbr_ifsflags = bif->bif_ifflags;
6d2010ae 2543 req->ifbr_portno = bif->bif_ifp->if_index & 0xfff;
6d2010ae
A
2544 req->ifbr_addrcnt = bif->bif_addrcnt;
2545 req->ifbr_addrmax = bif->bif_addrmax;
2546 req->ifbr_addrexceeded = bif->bif_addrexceeded;
2547
6d2010ae
A
2548 return (0);
2549}
2550
2551static int
2552bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
2553{
2554 struct ifbreq *req = arg;
2555 struct bridge_iflist *bif;
316670eb 2556#if BRIDGESTP
6d2010ae
A
2557 struct bstp_port *bp;
2558 int error;
316670eb 2559#endif /* BRIDGESTP */
6d2010ae 2560
5ba3f43e
A
2561 if (!bridge_in_bsd_mode(sc)) {
2562 return (EINVAL);
2563 }
2564
6d2010ae
A
2565 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
2566 if (bif == NULL)
2567 return (ENOENT);
6d2010ae
A
2568
2569 if (req->ifbr_ifsflags & IFBIF_SPAN)
2570 /* SPAN is readonly */
2571 return (EINVAL);
2572
316670eb
A
2573
2574#if BRIDGESTP
6d2010ae 2575 if (req->ifbr_ifsflags & IFBIF_STP) {
39236c6e 2576 if ((bif->bif_ifflags & IFBIF_STP) == 0) {
6d2010ae
A
2577 error = bstp_enable(&bif->bif_stp);
2578 if (error)
2579 return (error);
2580 }
2581 } else {
39236c6e 2582 if ((bif->bif_ifflags & IFBIF_STP) != 0)
6d2010ae
A
2583 bstp_disable(&bif->bif_stp);
2584 }
2585
2586 /* Pass on STP flags */
316670eb 2587 bp = &bif->bif_stp;
6d2010ae
A
2588 bstp_set_edge(bp, req->ifbr_ifsflags & IFBIF_BSTP_EDGE ? 1 : 0);
2589 bstp_set_autoedge(bp, req->ifbr_ifsflags & IFBIF_BSTP_AUTOEDGE ? 1 : 0);
2590 bstp_set_ptp(bp, req->ifbr_ifsflags & IFBIF_BSTP_PTP ? 1 : 0);
2591 bstp_set_autoptp(bp, req->ifbr_ifsflags & IFBIF_BSTP_AUTOPTP ? 1 : 0);
316670eb
A
2592#else /* !BRIDGESTP */
2593 if (req->ifbr_ifsflags & IFBIF_STP)
2594 return (EOPNOTSUPP);
2595#endif /* !BRIDGESTP */
6d2010ae
A
2596
2597 /* Save the bits relating to the bridge */
39236c6e 2598 bif->bif_ifflags = req->ifbr_ifsflags & IFBIFMASK;
6d2010ae
A
2599
2600
2601 return (0);
2602}
2603
2604static int
2605bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
2606{
2607 struct ifbrparam *param = arg;
2608
2609 sc->sc_brtmax = param->ifbrp_csize;
5ba3f43e
A
2610 if (bridge_in_bsd_mode(sc)) {
2611 bridge_rttrim(sc);
2612 }
6d2010ae
A
2613 return (0);
2614}
2615
2616static int
2617bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
2618{
2619 struct ifbrparam *param = arg;
2620
2621 param->ifbrp_csize = sc->sc_brtmax;
2622
2623 return (0);
2624}
2625
39236c6e 2626#define BRIDGE_IOCTL_GIFS do { \
316670eb
A
2627 struct bridge_iflist *bif; \
2628 struct ifbreq breq; \
2629 char *buf, *outbuf; \
2630 unsigned int count, buflen, len; \
2631 \
2632 count = 0; \
2633 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) \
2634 count++; \
5ba3f43e
A
2635 if (bridge_in_bsd_mode(sc)) { \
2636 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next) \
2637 count++; \
2638 } \
316670eb
A
2639 \
2640 buflen = sizeof (breq) * count; \
2641 if (bifc->ifbic_len == 0) { \
2642 bifc->ifbic_len = buflen; \
2643 return (0); \
2644 } \
2645 BRIDGE_UNLOCK(sc); \
2646 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
2647 BRIDGE_LOCK(sc); \
2648 \
2649 count = 0; \
2650 buf = outbuf; \
2651 len = min(bifc->ifbic_len, buflen); \
2652 bzero(&breq, sizeof (breq)); \
2653 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
2654 if (len < sizeof (breq)) \
2655 break; \
2656 \
2657 snprintf(breq.ifbr_ifsname, sizeof (breq.ifbr_ifsname), \
39236c6e 2658 "%s", bif->bif_ifp->if_xname); \
316670eb
A
2659 /* Fill in the ifbreq structure */ \
2660 error = bridge_ioctl_gifflags(sc, &breq); \
2661 if (error) \
2662 break; \
2663 memcpy(buf, &breq, sizeof (breq)); \
2664 count++; \
2665 buf += sizeof (breq); \
2666 len -= sizeof (breq); \
2667 } \
5ba3f43e
A
2668 if (bridge_in_bsd_mode(sc)) { \
2669 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next) { \
2670 if (len < sizeof (breq)) \
2671 break; \
316670eb 2672 \
5ba3f43e
A
2673 snprintf(breq.ifbr_ifsname, \
2674 sizeof (breq.ifbr_ifsname), \
2675 "%s", bif->bif_ifp->if_xname); \
2676 breq.ifbr_ifsflags = bif->bif_ifflags; \
2677 breq.ifbr_portno \
2678 = bif->bif_ifp->if_index & 0xfff; \
2679 memcpy(buf, &breq, sizeof (breq)); \
2680 count++; \
2681 buf += sizeof (breq); \
2682 len -= sizeof (breq); \
2683 } \
316670eb
A
2684 } \
2685 \
2686 BRIDGE_UNLOCK(sc); \
2687 bifc->ifbic_len = sizeof (breq) * count; \
2688 error = copyout(outbuf, bifc->ifbic_req, bifc->ifbic_len); \
2689 BRIDGE_LOCK(sc); \
2690 _FREE(outbuf, M_TEMP); \
6d2010ae
A
2691} while (0)
2692
2693static int
2694bridge_ioctl_gifs64(struct bridge_softc *sc, void *arg)
2695{
2696 struct ifbifconf64 *bifc = arg;
2697 int error = 0;
316670eb 2698
6d2010ae
A
2699 BRIDGE_IOCTL_GIFS;
2700
2701 return (error);
2702}
2703
2704static int
2705bridge_ioctl_gifs32(struct bridge_softc *sc, void *arg)
2706{
2707 struct ifbifconf32 *bifc = arg;
2708 int error = 0;
2709
2710 BRIDGE_IOCTL_GIFS;
2711
2712 return (error);
2713}
2714
39236c6e 2715#define BRIDGE_IOCTL_RTS do { \
316670eb 2716 struct bridge_rtnode *brt; \
5ba3f43e
A
2717 char *buf; \
2718 char *outbuf = NULL; \
316670eb 2719 unsigned int count, buflen, len; \
39236c6e 2720 unsigned long now; \
316670eb
A
2721 \
2722 if (bac->ifbac_len == 0) \
2723 return (0); \
2724 \
5ba3f43e 2725 bzero(&bareq, sizeof (bareq)); \
316670eb 2726 count = 0; \
5ba3f43e
A
2727 if (!bridge_in_bsd_mode(sc)) { \
2728 goto out; \
2729 } \
316670eb
A
2730 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) \
2731 count++; \
2732 buflen = sizeof (bareq) * count; \
2733 \
2734 BRIDGE_UNLOCK(sc); \
2735 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
2736 BRIDGE_LOCK(sc); \
2737 \
2738 count = 0; \
2739 buf = outbuf; \
2740 len = min(bac->ifbac_len, buflen); \
316670eb
A
2741 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { \
2742 if (len < sizeof (bareq)) \
2743 goto out; \
39236c6e 2744 snprintf(bareq.ifba_ifsname, sizeof (bareq.ifba_ifsname), \
5ba3f43e 2745 "%s", brt->brt_ifp->if_xname); \
316670eb
A
2746 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof (brt->brt_addr)); \
2747 bareq.ifba_vlan = brt->brt_vlan; \
2748 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { \
39236c6e
A
2749 now = (unsigned long) net_uptime(); \
2750 if (now < brt->brt_expire) \
316670eb 2751 bareq.ifba_expire = \
39236c6e 2752 brt->brt_expire - now; \
316670eb
A
2753 } else \
2754 bareq.ifba_expire = 0; \
2755 bareq.ifba_flags = brt->brt_flags; \
2756 \
2757 memcpy(buf, &bareq, sizeof (bareq)); \
2758 count++; \
2759 buf += sizeof (bareq); \
2760 len -= sizeof (bareq); \
2761 } \
2762out: \
39236c6e 2763 bac->ifbac_len = sizeof (bareq) * count; \
5ba3f43e
A
2764 if (outbuf != NULL) { \
2765 BRIDGE_UNLOCK(sc); \
2766 error = copyout(outbuf, bac->ifbac_req, bac->ifbac_len); \
2767 _FREE(outbuf, M_TEMP); \
2768 BRIDGE_LOCK(sc); \
2769 } \
316670eb 2770 return (error); \
6d2010ae
A
2771} while (0)
2772
2773static int
2774bridge_ioctl_rts64(struct bridge_softc *sc, void *arg)
2775{
2776 struct ifbaconf64 *bac = arg;
2777 struct ifbareq64 bareq;
2778 int error = 0;
316670eb 2779
6d2010ae 2780 BRIDGE_IOCTL_RTS;
6d2010ae
A
2781 return (error);
2782}
2783
2784static int
2785bridge_ioctl_rts32(struct bridge_softc *sc, void *arg)
2786{
2787 struct ifbaconf32 *bac = arg;
2788 struct ifbareq32 bareq;
2789 int error = 0;
316670eb 2790
6d2010ae 2791 BRIDGE_IOCTL_RTS;
6d2010ae
A
2792 return (error);
2793}
2794
2795static int
2796bridge_ioctl_saddr32(struct bridge_softc *sc, void *arg)
2797{
2798 struct ifbareq32 *req = arg;
2799 struct bridge_iflist *bif;
2800 int error;
2801
5ba3f43e
A
2802 if (!bridge_in_bsd_mode(sc)) {
2803 return (0);
2804 }
2805
6d2010ae
A
2806 bif = bridge_lookup_member(sc, req->ifba_ifsname);
2807 if (bif == NULL)
2808 return (ENOENT);
2809
2810 error = bridge_rtupdate(sc, req->ifba_dst, req->ifba_vlan, bif, 1,
2811 req->ifba_flags);
2812
2813 return (error);
2814}
2815
2816static int
2817bridge_ioctl_saddr64(struct bridge_softc *sc, void *arg)
2818{
2819 struct ifbareq64 *req = arg;
2820 struct bridge_iflist *bif;
2821 int error;
2822
5ba3f43e
A
2823 if (!bridge_in_bsd_mode(sc)) {
2824 return (0);
2825 }
2826
6d2010ae
A
2827 bif = bridge_lookup_member(sc, req->ifba_ifsname);
2828 if (bif == NULL)
2829 return (ENOENT);
2830
2831 error = bridge_rtupdate(sc, req->ifba_dst, req->ifba_vlan, bif, 1,
2832 req->ifba_flags);
2833
2834 return (error);
2835}
2836
2837static int
2838bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
2839{
2840 struct ifbrparam *param = arg;
2841
2842 sc->sc_brttimeout = param->ifbrp_ctime;
2843 return (0);
2844}
2845
2846static int
2847bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
2848{
2849 struct ifbrparam *param = arg;
2850
2851 param->ifbrp_ctime = sc->sc_brttimeout;
2852 return (0);
2853}
2854
2855static int
2856bridge_ioctl_daddr32(struct bridge_softc *sc, void *arg)
2857{
2858 struct ifbareq32 *req = arg;
2859
5ba3f43e
A
2860 if (!bridge_in_bsd_mode(sc)) {
2861 return (0);
2862 }
6d2010ae
A
2863 return (bridge_rtdaddr(sc, req->ifba_dst, req->ifba_vlan));
2864}
2865
2866static int
2867bridge_ioctl_daddr64(struct bridge_softc *sc, void *arg)
2868{
2869 struct ifbareq64 *req = arg;
2870
5ba3f43e
A
2871 if (!bridge_in_bsd_mode(sc)) {
2872 return (0);
2873 }
6d2010ae
A
2874 return (bridge_rtdaddr(sc, req->ifba_dst, req->ifba_vlan));
2875}
2876
2877static int
2878bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
2879{
2880 struct ifbreq *req = arg;
2881
5ba3f43e
A
2882 if (!bridge_in_bsd_mode(sc)) {
2883 return (0);
2884 }
6d2010ae
A
2885 bridge_rtflush(sc, req->ifbr_ifsflags);
2886 return (0);
2887}
2888
2889static int
2890bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
2891{
2892 struct ifbrparam *param = arg;
2893 struct bstp_state *bs = &sc->sc_stp;
2894
5ba3f43e
A
2895 if (!bridge_in_bsd_mode(sc)) {
2896 return (0);
2897 }
6d2010ae
A
2898 param->ifbrp_prio = bs->bs_bridge_priority;
2899 return (0);
2900}
2901
2902static int
2903bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
2904{
316670eb 2905#if BRIDGESTP
6d2010ae
A
2906 struct ifbrparam *param = arg;
2907
5ba3f43e
A
2908 if (!bridge_in_bsd_mode(sc)) {
2909 return (EOPNOTSUPP);
2910 }
6d2010ae 2911 return (bstp_set_priority(&sc->sc_stp, param->ifbrp_prio));
316670eb
A
2912#else /* !BRIDGESTP */
2913#pragma unused(sc, arg)
2914 return (EOPNOTSUPP);
2915#endif /* !BRIDGESTP */
6d2010ae
A
2916}
2917
2918static int
2919bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
2920{
2921 struct ifbrparam *param = arg;
2922 struct bstp_state *bs = &sc->sc_stp;
2923
5ba3f43e
A
2924 if (!bridge_in_bsd_mode(sc)) {
2925 return (0);
2926 }
6d2010ae
A
2927 param->ifbrp_hellotime = bs->bs_bridge_htime >> 8;
2928 return (0);
2929}
2930
2931static int
2932bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
2933{
316670eb 2934#if BRIDGESTP
6d2010ae
A
2935 struct ifbrparam *param = arg;
2936
5ba3f43e
A
2937 if (!bridge_in_bsd_mode(sc)) {
2938 return (EOPNOTSUPP);
2939 }
6d2010ae 2940 return (bstp_set_htime(&sc->sc_stp, param->ifbrp_hellotime));
316670eb
A
2941#else /* !BRIDGESTP */
2942#pragma unused(sc, arg)
2943 return (EOPNOTSUPP);
2944#endif /* !BRIDGESTP */
6d2010ae
A
2945}
2946
2947static int
2948bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
2949{
5ba3f43e
A
2950 struct ifbrparam *param;
2951 struct bstp_state *bs;
6d2010ae 2952
5ba3f43e
A
2953 if (!bridge_in_bsd_mode(sc)) {
2954 return (0);
2955 }
2956 param = arg;
2957 bs = &sc->sc_stp;
6d2010ae
A
2958 param->ifbrp_fwddelay = bs->bs_bridge_fdelay >> 8;
2959 return (0);
2960}
2961
2962static int
2963bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
2964{
316670eb 2965#if BRIDGESTP
6d2010ae
A
2966 struct ifbrparam *param = arg;
2967
5ba3f43e
A
2968 if (!bridge_in_bsd_mode(sc)) {
2969 return (EOPNOTSUPP);
2970 }
6d2010ae 2971 return (bstp_set_fdelay(&sc->sc_stp, param->ifbrp_fwddelay));
316670eb
A
2972#else /* !BRIDGESTP */
2973#pragma unused(sc, arg)
2974 return (EOPNOTSUPP);
2975#endif /* !BRIDGESTP */
6d2010ae
A
2976}
2977
2978static int
2979bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
2980{
5ba3f43e
A
2981 struct ifbrparam *param;
2982 struct bstp_state *bs;
6d2010ae 2983
5ba3f43e
A
2984 if (!bridge_in_bsd_mode(sc)) {
2985 return (EOPNOTSUPP);
2986 }
2987 param = arg;
2988 bs = &sc->sc_stp;
6d2010ae
A
2989 param->ifbrp_maxage = bs->bs_bridge_max_age >> 8;
2990 return (0);
2991}
2992
2993static int
2994bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
2995{
316670eb 2996#if BRIDGESTP
6d2010ae
A
2997 struct ifbrparam *param = arg;
2998
5ba3f43e
A
2999 if (!bridge_in_bsd_mode(sc)) {
3000 return (EOPNOTSUPP);
3001 }
6d2010ae 3002 return (bstp_set_maxage(&sc->sc_stp, param->ifbrp_maxage));
316670eb
A
3003#else /* !BRIDGESTP */
3004#pragma unused(sc, arg)
3005 return (EOPNOTSUPP);
3006#endif /* !BRIDGESTP */
6d2010ae
A
3007}
3008
3009static int
3010bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
3011{
316670eb 3012#if BRIDGESTP
6d2010ae
A
3013 struct ifbreq *req = arg;
3014 struct bridge_iflist *bif;
3015
5ba3f43e
A
3016 if (!bridge_in_bsd_mode(sc)) {
3017 return (EOPNOTSUPP);
3018 }
6d2010ae
A
3019 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
3020 if (bif == NULL)
3021 return (ENOENT);
3022
3023 return (bstp_set_port_priority(&bif->bif_stp, req->ifbr_priority));
316670eb
A
3024#else /* !BRIDGESTP */
3025#pragma unused(sc, arg)
3026 return (EOPNOTSUPP);
3027#endif /* !BRIDGESTP */
6d2010ae
A
3028}
3029
3030static int
3031bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg)
3032{
316670eb 3033#if BRIDGESTP
6d2010ae
A
3034 struct ifbreq *req = arg;
3035 struct bridge_iflist *bif;
3036
5ba3f43e
A
3037 if (!bridge_in_bsd_mode(sc)) {
3038 return (EOPNOTSUPP);
3039 }
6d2010ae
A
3040 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
3041 if (bif == NULL)
3042 return (ENOENT);
3043
3044 return (bstp_set_path_cost(&bif->bif_stp, req->ifbr_path_cost));
316670eb
A
3045#else /* !BRIDGESTP */
3046#pragma unused(sc, arg)
3047 return (EOPNOTSUPP);
3048#endif /* !BRIDGESTP */
6d2010ae
A
3049}
3050
3051static int
3052bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg)
3053{
3054 struct ifbrparam *param = arg;
3055
3056 param->ifbrp_filter = sc->sc_filter_flags;
3057
3058 return (0);
3059}
3060
3061static int
3062bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg)
3063{
3064 struct ifbrparam *param = arg;
3065
3066 if (param->ifbrp_filter & ~IFBF_FILT_MASK)
3067 return (EINVAL);
3068
3069#ifndef BRIDGE_IPF
3070 if (param->ifbrp_filter & IFBF_FILT_USEIPF)
3071 return (EINVAL);
3072#endif
3073
3074 sc->sc_filter_flags = param->ifbrp_filter;
3075
3076 return (0);
3077}
3078
3079static int
3080bridge_ioctl_sifmaxaddr(struct bridge_softc *sc, void *arg)
3081{
3082 struct ifbreq *req = arg;
3083 struct bridge_iflist *bif;
3084
3085 bif = bridge_lookup_member(sc, req->ifbr_ifsname);
3086 if (bif == NULL)
3087 return (ENOENT);
3088
3089 bif->bif_addrmax = req->ifbr_addrmax;
3090 return (0);
3091}
3092
3093static int
3094bridge_ioctl_addspan(struct bridge_softc *sc, void *arg)
3095{
3096 struct ifbreq *req = arg;
3097 struct bridge_iflist *bif = NULL;
3098 struct ifnet *ifs;
3099
5ba3f43e
A
3100 if (!bridge_in_bsd_mode(sc)) {
3101 return (EOPNOTSUPP);
3102 }
6d2010ae
A
3103 ifs = ifunit(req->ifbr_ifsname);
3104 if (ifs == NULL)
3105 return (ENOENT);
3106
3107 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next)
3108 if (ifs == bif->bif_ifp)
3109 return (EBUSY);
3110
3111 if (ifs->if_bridge != NULL)
3112 return (EBUSY);
3113
3114 switch (ifs->if_type) {
3115 case IFT_ETHER:
6d2010ae
A
3116 case IFT_L2VLAN:
3117 break;
39236c6e
A
3118 case IFT_GIF:
3119 /* currently not supported */
3120 /* FALLTHRU */
6d2010ae
A
3121 default:
3122 return (EINVAL);
3123 }
3124
5ba3f43e 3125 bif = _MALLOC(sizeof (*bif), M_DEVBUF, M_WAITOK | M_ZERO);
6d2010ae
A
3126 if (bif == NULL)
3127 return (ENOMEM);
3128
3129 bif->bif_ifp = ifs;
39236c6e 3130 bif->bif_ifflags = IFBIF_SPAN;
6d2010ae
A
3131
3132 ifnet_reference(bif->bif_ifp);
3133
3134 TAILQ_INSERT_HEAD(&sc->sc_spanlist, bif, bif_next);
3135
3136 return (0);
3137}
3138
3139static int
3140bridge_ioctl_delspan(struct bridge_softc *sc, void *arg)
3141{
3142 struct ifbreq *req = arg;
3143 struct bridge_iflist *bif;
3144 struct ifnet *ifs;
3145
5ba3f43e
A
3146 if (!bridge_in_bsd_mode(sc)) {
3147 return (EOPNOTSUPP);
3148 }
6d2010ae
A
3149 ifs = ifunit(req->ifbr_ifsname);
3150 if (ifs == NULL)
3151 return (ENOENT);
3152
3153 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next)
3154 if (ifs == bif->bif_ifp)
3155 break;
3156
3157 if (bif == NULL)
3158 return (ENOENT);
3159
3160 bridge_delete_span(sc, bif);
3161
3162 return (0);
3163}
3164
39236c6e 3165#define BRIDGE_IOCTL_GBPARAM do { \
316670eb
A
3166 struct bstp_state *bs = &sc->sc_stp; \
3167 struct bstp_port *root_port; \
3168 \
3169 req->ifbop_maxage = bs->bs_bridge_max_age >> 8; \
3170 req->ifbop_hellotime = bs->bs_bridge_htime >> 8; \
3171 req->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8; \
3172 \
3173 root_port = bs->bs_root_port; \
3174 if (root_port == NULL) \
3175 req->ifbop_root_port = 0; \
3176 else \
3177 req->ifbop_root_port = root_port->bp_ifp->if_index; \
3178 \
3179 req->ifbop_holdcount = bs->bs_txholdcount; \
3180 req->ifbop_priority = bs->bs_bridge_priority; \
3181 req->ifbop_protocol = bs->bs_protover; \
3182 req->ifbop_root_path_cost = bs->bs_root_pv.pv_cost; \
3183 req->ifbop_bridgeid = bs->bs_bridge_pv.pv_dbridge_id; \
3184 req->ifbop_designated_root = bs->bs_root_pv.pv_root_id; \
3185 req->ifbop_designated_bridge = bs->bs_root_pv.pv_dbridge_id; \
3186 req->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec; \
3187 req->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec; \
6d2010ae
A
3188} while (0)
3189
3190static int
3191bridge_ioctl_gbparam32(struct bridge_softc *sc, void *arg)
3192{
3193 struct ifbropreq32 *req = arg;
3194
5ba3f43e
A
3195 if (bridge_in_bsd_mode(sc)) {
3196 BRIDGE_IOCTL_GBPARAM;
3197 }
6d2010ae
A
3198 return (0);
3199}
3200
3201static int
3202bridge_ioctl_gbparam64(struct bridge_softc *sc, void *arg)
3203{
3204 struct ifbropreq64 *req = arg;
3205
5ba3f43e
A
3206 if (bridge_in_bsd_mode(sc)) {
3207 BRIDGE_IOCTL_GBPARAM;
3208 }
6d2010ae
A
3209 return (0);
3210}
3211
6d2010ae
A
3212static int
3213bridge_ioctl_grte(struct bridge_softc *sc, void *arg)
3214{
3215 struct ifbrparam *param = arg;
3216
3217 param->ifbrp_cexceeded = sc->sc_brtexceeded;
3218 return (0);
3219}
3220
39236c6e 3221#define BRIDGE_IOCTL_GIFSSTP do { \
316670eb
A
3222 struct bridge_iflist *bif; \
3223 struct bstp_port *bp; \
3224 struct ifbpstpreq bpreq; \
3225 char *buf, *outbuf; \
3226 unsigned int count, buflen, len; \
3227 \
3228 count = 0; \
3229 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
39236c6e 3230 if ((bif->bif_ifflags & IFBIF_STP) != 0) \
316670eb
A
3231 count++; \
3232 } \
3233 \
3234 buflen = sizeof (bpreq) * count; \
3235 if (bifstp->ifbpstp_len == 0) { \
3236 bifstp->ifbpstp_len = buflen; \
3237 return (0); \
3238 } \
3239 \
3240 BRIDGE_UNLOCK(sc); \
3241 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
3242 BRIDGE_LOCK(sc); \
3243 \
3244 count = 0; \
3245 buf = outbuf; \
3246 len = min(bifstp->ifbpstp_len, buflen); \
3247 bzero(&bpreq, sizeof (bpreq)); \
3248 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
3249 if (len < sizeof (bpreq)) \
3250 break; \
3251 \
39236c6e 3252 if ((bif->bif_ifflags & IFBIF_STP) == 0) \
316670eb
A
3253 continue; \
3254 \
3255 bp = &bif->bif_stp; \
3256 bpreq.ifbp_portno = bif->bif_ifp->if_index & 0xfff; \
3257 bpreq.ifbp_fwd_trans = bp->bp_forward_transitions; \
3258 bpreq.ifbp_design_cost = bp->bp_desg_pv.pv_cost; \
3259 bpreq.ifbp_design_port = bp->bp_desg_pv.pv_port_id; \
6d2010ae 3260 bpreq.ifbp_design_bridge = bp->bp_desg_pv.pv_dbridge_id; \
316670eb
A
3261 bpreq.ifbp_design_root = bp->bp_desg_pv.pv_root_id; \
3262 \
3263 memcpy(buf, &bpreq, sizeof (bpreq)); \
3264 count++; \
3265 buf += sizeof (bpreq); \
3266 len -= sizeof (bpreq); \
3267 } \
3268 \
3269 BRIDGE_UNLOCK(sc); \
3270 bifstp->ifbpstp_len = sizeof (bpreq) * count; \
6d2010ae 3271 error = copyout(outbuf, bifstp->ifbpstp_req, bifstp->ifbpstp_len); \
316670eb
A
3272 BRIDGE_LOCK(sc); \
3273 _FREE(outbuf, M_TEMP); \
3274 return (error); \
6d2010ae
A
3275} while (0)
3276
3277static int
3278bridge_ioctl_gifsstp32(struct bridge_softc *sc, void *arg)
3279{
3280 struct ifbpstpconf32 *bifstp = arg;
3281 int error = 0;
3282
5ba3f43e
A
3283 if (bridge_in_bsd_mode(sc)) {
3284 BRIDGE_IOCTL_GIFSSTP;
3285 }
6d2010ae
A
3286 return (error);
3287}
3288
3289static int
3290bridge_ioctl_gifsstp64(struct bridge_softc *sc, void *arg)
3291{
3292 struct ifbpstpconf64 *bifstp = arg;
3293 int error = 0;
3294
5ba3f43e
A
3295 if (bridge_in_bsd_mode(sc)) {
3296 BRIDGE_IOCTL_GIFSSTP;
3297 }
6d2010ae
A
3298 return (error);
3299}
3300
3301static int
3302bridge_ioctl_sproto(struct bridge_softc *sc, void *arg)
3303{
316670eb 3304#if BRIDGESTP
6d2010ae
A
3305 struct ifbrparam *param = arg;
3306
5ba3f43e
A
3307 if (!bridge_in_bsd_mode(sc)) {
3308 return (EOPNOTSUPP);
3309 }
6d2010ae 3310 return (bstp_set_protocol(&sc->sc_stp, param->ifbrp_proto));
316670eb
A
3311#else /* !BRIDGESTP */
3312#pragma unused(sc, arg)
3313 return (EOPNOTSUPP);
3314#endif /* !BRIDGESTP */
6d2010ae
A
3315}
3316
3317static int
3318bridge_ioctl_stxhc(struct bridge_softc *sc, void *arg)
3319{
316670eb 3320#if BRIDGESTP
6d2010ae
A
3321 struct ifbrparam *param = arg;
3322
5ba3f43e
A
3323 if (!bridge_in_bsd_mode(sc)) {
3324 return (EOPNOTSUPP);
3325 }
6d2010ae 3326 return (bstp_set_holdcount(&sc->sc_stp, param->ifbrp_txhc));
316670eb
A
3327#else /* !BRIDGESTP */
3328#pragma unused(sc, arg)
3329 return (EOPNOTSUPP);
3330#endif /* !BRIDGESTP */
6d2010ae
A
3331}
3332
fe8ab488
A
3333
3334static int
3335bridge_ioctl_ghostfilter(struct bridge_softc *sc, void *arg)
3336{
3337 struct ifbrhostfilter *req = arg;
3338 struct bridge_iflist *bif;
3339
3340 bif = bridge_lookup_member(sc, req->ifbrhf_ifsname);
3341 if (bif == NULL)
3342 return (ENOENT);
3343
3344 bzero(req, sizeof(struct ifbrhostfilter));
3345 if (bif->bif_flags & BIFF_HOST_FILTER) {
3346 req->ifbrhf_flags |= IFBRHF_ENABLED;
3347 bcopy(bif->bif_hf_hwsrc, req->ifbrhf_hwsrca,
3348 ETHER_ADDR_LEN);
3349 req->ifbrhf_ipsrc = bif->bif_hf_ipsrc.s_addr;
3350 }
3351 return (0);
3352}
3353
3354static int
3355bridge_ioctl_shostfilter(struct bridge_softc *sc, void *arg)
3356{
3357 struct ifbrhostfilter *req = arg;
3358 struct bridge_iflist *bif;
3359
3360 bif = bridge_lookup_member(sc, req->ifbrhf_ifsname);
3361 if (bif == NULL)
3362 return (ENOENT);
3363
5ba3f43e
A
3364 INC_ATOMIC_INT64_LIM(net_api_stats.nas_vmnet_total);
3365
fe8ab488
A
3366 if (req->ifbrhf_flags & IFBRHF_ENABLED) {
3367 bif->bif_flags |= BIFF_HOST_FILTER;
3368
3369 if (req->ifbrhf_flags & IFBRHF_HWSRC) {
3370 bcopy(req->ifbrhf_hwsrca, bif->bif_hf_hwsrc,
3371 ETHER_ADDR_LEN);
3372 if (bcmp(req->ifbrhf_hwsrca, ethernulladdr,
3373 ETHER_ADDR_LEN) != 0)
3374 bif->bif_flags |= BIFF_HF_HWSRC;
3375 else
3376 bif->bif_flags &= ~BIFF_HF_HWSRC;
3377 }
3378 if (req->ifbrhf_flags & IFBRHF_IPSRC) {
3379 bif->bif_hf_ipsrc.s_addr = req->ifbrhf_ipsrc;
3380 if (bif->bif_hf_ipsrc.s_addr != INADDR_ANY)
3381 bif->bif_flags |= BIFF_HF_IPSRC;
3382 else
3383 bif->bif_flags &= ~BIFF_HF_IPSRC;
3384 }
3385 } else {
3386 bif->bif_flags &= ~(BIFF_HOST_FILTER | BIFF_HF_HWSRC |
3387 BIFF_HF_IPSRC);
3388 bzero(bif->bif_hf_hwsrc, ETHER_ADDR_LEN);
3389 bif->bif_hf_ipsrc.s_addr = INADDR_ANY;
3390 }
3391
3392 return (0);
3393}
3394
3395
6d2010ae
A
3396/*
3397 * bridge_ifdetach:
3398 *
3399 * Detach an interface from a bridge. Called when a member
3400 * interface is detaching.
3401 */
3402__private_extern__ void
3403bridge_ifdetach(struct bridge_iflist *bif, struct ifnet *ifp)
3404{
3405 struct bridge_softc *sc = ifp->if_bridge;
3406
3407#if BRIDGE_DEBUG
39236c6e
A
3408 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
3409 printf("%s: %s\n", __func__, ifp->if_xname);
3410#endif /* BRIDGE_DEBUG */
6d2010ae
A
3411
3412 /* Check if the interface is a bridge member */
3413 if (sc != NULL) {
3414 BRIDGE_LOCK(sc);
6d2010ae
A
3415 bif = bridge_lookup_member_if(sc, ifp);
3416 if (bif != NULL)
3417 bridge_delete_member(sc, bif, 1);
6d2010ae
A
3418 BRIDGE_UNLOCK(sc);
3419 return;
3420 }
6d2010ae 3421 /* Check if the interface is a span port */
39236c6e 3422 lck_mtx_lock(&bridge_list_mtx);
6d2010ae 3423 LIST_FOREACH(sc, &bridge_list, sc_list) {
5ba3f43e
A
3424 if (bridge_in_bsd_mode(sc)) {
3425 BRIDGE_LOCK(sc);
3426 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next)
3427 if (ifp == bif->bif_ifp) {
3428 bridge_delete_span(sc, bif);
3429 break;
3430 }
3431 BRIDGE_UNLOCK(sc);
3432 }
6d2010ae 3433 }
39236c6e 3434 lck_mtx_unlock(&bridge_list_mtx);
6d2010ae
A
3435}
3436
3437/*
39236c6e 3438 * interface_media_active:
6d2010ae 3439 *
39236c6e 3440 * Tells if an interface media is active.
6d2010ae
A
3441 */
3442static int
39236c6e 3443interface_media_active(struct ifnet *ifp)
6d2010ae 3444{
39236c6e
A
3445 struct ifmediareq ifmr;
3446 int status = 0;
6d2010ae 3447
39236c6e
A
3448 bzero(&ifmr, sizeof(ifmr));
3449 if (ifnet_ioctl(ifp, 0, SIOCGIFMEDIA, &ifmr) == 0) {
3450 if ((ifmr.ifm_status & IFM_AVALID) && ifmr.ifm_count > 0)
3451 status = ifmr.ifm_status & IFM_ACTIVE ? 1 : 0;
3452 }
6d2010ae 3453
39236c6e 3454 return (status);
6d2010ae
A
3455}
3456
3457/*
39236c6e 3458 * bridge_updatelinkstatus:
6d2010ae 3459 *
39236c6e
A
3460 * Update the media active status of the bridge based on the
3461 * media active status of its member.
3462 * If changed, return the corresponding onf/off link event.
6d2010ae 3463 */
39236c6e
A
3464static u_int32_t
3465bridge_updatelinkstatus(struct bridge_softc *sc)
6d2010ae 3466{
39236c6e
A
3467 struct bridge_iflist *bif;
3468 int active_member = 0;
3469 u_int32_t event_code = 0;
6d2010ae 3470
39236c6e 3471 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae 3472
39236c6e
A
3473 /*
3474 * Find out if we have an active interface
3475 */
3476 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
3477 if (bif->bif_flags & BIFF_MEDIA_ACTIVE) {
3478 active_member = 1;
3479 break;
3480 }
3481 }
3482
3483 if (active_member && !(sc->sc_flags & SCF_MEDIA_ACTIVE)) {
3484 sc->sc_flags |= SCF_MEDIA_ACTIVE;
3485 event_code = KEV_DL_LINK_ON;
3486 } else if (!active_member && (sc->sc_flags & SCF_MEDIA_ACTIVE)) {
3487 sc->sc_flags &= ~SCF_MEDIA_ACTIVE;
3488 event_code = KEV_DL_LINK_OFF;
3489 }
3490
3491 return (event_code);
3492}
3493
3494/*
3495 * bridge_iflinkevent:
3496 */
3497static void
3498bridge_iflinkevent(struct ifnet *ifp)
3499{
3500 struct bridge_softc *sc = ifp->if_bridge;
3501 struct bridge_iflist *bif;
3502 u_int32_t event_code = 0;
3503
3504#if BRIDGE_DEBUG
3505 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
3506 printf("%s: %s\n", __func__, ifp->if_xname);
3507#endif /* BRIDGE_DEBUG */
3508
3509 /* Check if the interface is a bridge member */
3510 if (sc == NULL)
3511 return;
3512
3513 BRIDGE_LOCK(sc);
3514 bif = bridge_lookup_member_if(sc, ifp);
3515 if (bif != NULL) {
3516 if (interface_media_active(ifp))
3517 bif->bif_flags |= BIFF_MEDIA_ACTIVE;
3518 else
3519 bif->bif_flags &= ~BIFF_MEDIA_ACTIVE;
3520
3521 event_code = bridge_updatelinkstatus(sc);
3522 }
3523 BRIDGE_UNLOCK(sc);
3524
3525 if (event_code != 0)
3526 bridge_link_event(sc->sc_ifp, event_code);
3527}
3528
3529/*
3530 * bridge_delayed_callback:
3531 *
3532 * Makes a delayed call
3533 */
3534static void
3535bridge_delayed_callback(void *param)
3536{
3537 struct bridge_delayed_call *call = (struct bridge_delayed_call *)param;
3538 struct bridge_softc *sc = call->bdc_sc;
3539
3540#if BRIDGE_DEBUG_DELAYED_CALLBACK
3541 if (bridge_delayed_callback_delay > 0) {
3542 struct timespec ts;
3543
3544 ts.tv_sec = bridge_delayed_callback_delay;
3545 ts.tv_nsec = 0;
3546
3547 printf("%s: sleeping for %d seconds\n",
3548 __func__, bridge_delayed_callback_delay);
3549
3550 msleep(&bridge_delayed_callback_delay, NULL, PZERO,
3551 __func__, &ts);
3552
3553 printf("%s: awoken\n", __func__);
3554 }
3555#endif /* BRIDGE_DEBUG_DELAYED_CALLBACK */
3556
3557 BRIDGE_LOCK(sc);
3558
fe8ab488 3559#if BRIDGE_DEBUG_DELAYED_CALLBACK
39236c6e
A
3560 if (if_bridge_debug & BR_DBGF_DELAYED_CALL)
3561 printf("%s: %s call 0x%llx flags 0x%x\n", __func__,
3562 sc->sc_if_xname, (uint64_t)VM_KERNEL_ADDRPERM(call),
3563 call->bdc_flags);
fe8ab488 3564#endif /* BRIDGE_DEBUG_DELAYED_CALLBACK */
39236c6e 3565
fe8ab488 3566 if (call->bdc_flags & BDCF_CANCELLING) {
39236c6e
A
3567 wakeup(call);
3568 } else {
3569 if ((sc->sc_flags & SCF_DETACHING) == 0)
3570 (*call->bdc_func)(sc);
3571 }
3572 call->bdc_flags &= ~BDCF_OUTSTANDING;
3573 BRIDGE_UNLOCK(sc);
3574}
3575
3576/*
3577 * bridge_schedule_delayed_call:
3578 *
3579 * Schedule a function to be called on a separate thread
3580 * The actual call may be scheduled to run at a given time or ASAP.
3581 */
3582static void
3583bridge_schedule_delayed_call(struct bridge_delayed_call *call)
3584{
3585 uint64_t deadline = 0;
3586 struct bridge_softc *sc = call->bdc_sc;
3587
3588 BRIDGE_LOCK_ASSERT_HELD(sc);
3589
3590 if ((sc->sc_flags & SCF_DETACHING) ||
3591 (call->bdc_flags & (BDCF_OUTSTANDING | BDCF_CANCELLING)))
3592 return;
3593
3594 if (call->bdc_ts.tv_sec || call->bdc_ts.tv_nsec) {
3595 nanoseconds_to_absolutetime(
3596 (uint64_t)call->bdc_ts.tv_sec * NSEC_PER_SEC +
3597 call->bdc_ts.tv_nsec, &deadline);
3598 clock_absolutetime_interval_to_deadline(deadline, &deadline);
3599 }
3600
3601 call->bdc_flags = BDCF_OUTSTANDING;
3602
fe8ab488 3603#if BRIDGE_DEBUG_DELAYED_CALLBACK
39236c6e
A
3604 if (if_bridge_debug & BR_DBGF_DELAYED_CALL)
3605 printf("%s: %s call 0x%llx flags 0x%x\n", __func__,
3606 sc->sc_if_xname, (uint64_t)VM_KERNEL_ADDRPERM(call),
3607 call->bdc_flags);
fe8ab488 3608#endif /* BRIDGE_DEBUG_DELAYED_CALLBACK */
39236c6e 3609
fe8ab488
A
3610 if (call->bdc_ts.tv_sec || call->bdc_ts.tv_nsec)
3611 thread_call_func_delayed(
3612 (thread_call_func_t)bridge_delayed_callback,
3613 call, deadline);
3614 else {
3615 if (call->bdc_thread_call == NULL)
3616 call->bdc_thread_call = thread_call_allocate(
3617 (thread_call_func_t)bridge_delayed_callback,
3618 call);
3619 thread_call_enter(call->bdc_thread_call);
3620 }
39236c6e
A
3621}
3622
3623/*
3624 * bridge_cancel_delayed_call:
3625 *
3626 * Cancel a queued or running delayed call.
3627 * If call is running, does not return until the call is done to
3628 * prevent race condition with the brigde interface getting destroyed
3629 */
3630static void
3631bridge_cancel_delayed_call(struct bridge_delayed_call *call)
3632{
3633 boolean_t result;
3634 struct bridge_softc *sc = call->bdc_sc;
3635
3636 /*
3637 * The call was never scheduled
3638 */
3639 if (sc == NULL)
3640 return;
3641
3642 BRIDGE_LOCK_ASSERT_HELD(sc);
3643
3644 call->bdc_flags |= BDCF_CANCELLING;
3645
3646 while (call->bdc_flags & BDCF_OUTSTANDING) {
3647#if BRIDGE_DEBUG
3648 if (if_bridge_debug & BR_DBGF_DELAYED_CALL)
3649 printf("%s: %s call 0x%llx flags 0x%x\n", __func__,
3650 sc->sc_if_xname, (uint64_t)VM_KERNEL_ADDRPERM(call),
3651 call->bdc_flags);
3652#endif /* BRIDGE_DEBUG */
3653 result = thread_call_func_cancel(
3654 (thread_call_func_t)bridge_delayed_callback, call, FALSE);
3655
3656 if (result) {
3657 /*
3658 * We managed to dequeue the delayed call
3659 */
3660 call->bdc_flags &= ~BDCF_OUTSTANDING;
3661 } else {
3662 /*
3663 * Wait for delayed call do be done running
3664 */
3665 msleep(call, &sc->sc_mtx, PZERO, __func__, NULL);
3666 }
3667 }
3668 call->bdc_flags &= ~BDCF_CANCELLING;
3669}
3670
fe8ab488
A
3671/*
3672 * bridge_cleanup_delayed_call:
3673 *
3674 * Dispose resource allocated for a delayed call
3675 * Assume the delayed call is not queued or running .
3676 */
3677static void
3678bridge_cleanup_delayed_call(struct bridge_delayed_call *call)
3679{
3680 boolean_t result;
3681 struct bridge_softc *sc = call->bdc_sc;
3682
3683 /*
3684 * The call was never scheduled
3685 */
3686 if (sc == NULL)
3687 return;
3688
3689 BRIDGE_LOCK_ASSERT_HELD(sc);
3690
3691 VERIFY((call->bdc_flags & BDCF_OUTSTANDING) == 0);
3692 VERIFY((call->bdc_flags & BDCF_CANCELLING) == 0);
3693
3694 if (call->bdc_thread_call != NULL) {
3695 result = thread_call_free(call->bdc_thread_call);
3696 if (result == FALSE)
3697 panic("%s thread_call_free() failed for call %p",
3698 __func__, call);
3699 call->bdc_thread_call = NULL;
3700 }
3701}
3702
39236c6e
A
3703/*
3704 * bridge_init:
3705 *
3706 * Initialize a bridge interface.
3707 */
3708static int
3709bridge_init(struct ifnet *ifp)
3710{
3711 struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
3712 errno_t error;
3713
3714 BRIDGE_LOCK_ASSERT_HELD(sc);
3715
3716 if ((ifnet_flags(ifp) & IFF_RUNNING))
3717 return (0);
3718
3719 error = ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING);
3720
5ba3f43e
A
3721 if (bridge_in_bsd_mode(sc)) {
3722 /*
3723 * Calling bridge_aging_timer() is OK as there are no entries to
3724 * age so we're just going to arm the timer
3725 */
3726 bridge_aging_timer(sc);
39236c6e 3727#if BRIDGESTP
5ba3f43e
A
3728 if (error == 0)
3729 bstp_init(&sc->sc_stp); /* Initialize Spanning Tree */
39236c6e 3730#endif /* BRIDGESTP */
5ba3f43e 3731 }
39236c6e
A
3732 return (error);
3733}
3734
3735/*
3736 * bridge_ifstop:
3737 *
3738 * Stop the bridge interface.
3739 */
3740static void
3741bridge_ifstop(struct ifnet *ifp, int disable)
3742{
3743#pragma unused(disable)
3744 struct bridge_softc *sc = ifp->if_softc;
3745
3746 BRIDGE_LOCK_ASSERT_HELD(sc);
3747
3748 if ((ifnet_flags(ifp) & IFF_RUNNING) == 0)
3749 return;
3750
5ba3f43e
A
3751 if (bridge_in_bsd_mode(sc)) {
3752 bridge_cancel_delayed_call(&sc->sc_aging_timer);
39236c6e
A
3753
3754#if BRIDGESTP
5ba3f43e 3755 bstp_stop(&sc->sc_stp);
316670eb 3756#endif /* BRIDGESTP */
6d2010ae 3757
5ba3f43e
A
3758 bridge_rtflush(sc, IFBF_FLUSHDYN);
3759 }
6d2010ae
A
3760 (void) ifnet_set_flags(ifp, 0, IFF_RUNNING);
3761}
3762
3763/*
3764 * bridge_enqueue:
3765 *
3766 * Enqueue a packet on a bridge member interface.
3767 *
3768 */
316670eb 3769static int
6d2010ae
A
3770bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m)
3771{
3772 int len, error = 0;
3773 short mflags;
3774 struct mbuf *m0;
3775
316670eb
A
3776 VERIFY(dst_ifp != NULL);
3777
3778 /*
3779 * We may be sending a fragment so traverse the mbuf
3780 *
3781 * NOTE: bridge_fragment() is called only when PFIL_HOOKS is enabled.
3782 */
6d2010ae 3783 for (; m; m = m0) {
316670eb
A
3784 errno_t _error;
3785 struct flowadv adv = { FADV_SUCCESS };
3786
6d2010ae
A
3787 m0 = m->m_nextpkt;
3788 m->m_nextpkt = NULL;
3789
3790 len = m->m_pkthdr.len;
3791 mflags = m->m_flags;
316670eb 3792 m->m_flags |= M_PROTO1; /* set to avoid loops */
6d2010ae 3793
39236c6e
A
3794 bridge_finalize_cksum(dst_ifp, m);
3795
6d2010ae
A
3796#if HAS_IF_CAP
3797 /*
3798 * If underlying interface can not do VLAN tag insertion itself
3799 * then attach a packet tag that holds it.
3800 */
3801 if ((m->m_flags & M_VLANTAG) &&
3802 (dst_ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) {
3803 m = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
3804 if (m == NULL) {
39236c6e
A
3805 printf("%s: %s: unable to prepend VLAN "
3806 "header\n", __func__, dst_ifp->if_xname);
316670eb
A
3807 (void) ifnet_stat_increment_out(dst_ifp,
3808 0, 0, 1);
6d2010ae
A
3809 continue;
3810 }
3811 m->m_flags &= ~M_VLANTAG;
3812 }
3813#endif /* HAS_IF_CAP */
3814
316670eb
A
3815 _error = dlil_output(dst_ifp, 0, m, NULL, NULL, 1, &adv);
3816
3817 /* Preserve existing error value */
6d2010ae 3818 if (error == 0) {
316670eb
A
3819 if (_error != 0)
3820 error = _error;
3821 else if (adv.code == FADV_FLOW_CONTROLLED)
3822 error = EQFULL;
3823 else if (adv.code == FADV_SUSPENDED)
3824 error = EQSUSPENDED;
3825 }
3826
3827 if (_error == 0) {
6d2010ae
A
3828 (void) ifnet_stat_increment_out(sc->sc_ifp, 1, len, 0);
3829 } else {
3830 (void) ifnet_stat_increment_out(sc->sc_ifp, 0, 0, 1);
3831 }
3832 }
3833
316670eb 3834 return (error);
6d2010ae
A
3835}
3836
3837#if HAS_BRIDGE_DUMMYNET
3838/*
3839 * bridge_dummynet:
3840 *
316670eb
A
3841 * Receive a queued packet from dummynet and pass it on to the output
3842 * interface.
6d2010ae
A
3843 *
3844 * The mbuf has the Ethernet header already attached.
3845 */
3846static void
3847bridge_dummynet(struct mbuf *m, struct ifnet *ifp)
3848{
3849 struct bridge_softc *sc;
3850
3851 sc = ifp->if_bridge;
3852
3853 /*
3854 * The packet didnt originate from a member interface. This should only
3855 * ever happen if a member interface is removed while packets are
3856 * queued for it.
3857 */
3858 if (sc == NULL) {
3859 m_freem(m);
3860 return;
3861 }
3862
39236c6e 3863 if (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6) {
6d2010ae
A
3864 if (bridge_pfil(&m, sc->sc_ifp, ifp, PFIL_OUT) != 0)
3865 return;
3866 if (m == NULL)
3867 return;
3868 }
3869
316670eb 3870 (void) bridge_enqueue(sc, ifp, m);
6d2010ae
A
3871}
3872#endif /* HAS_BRIDGE_DUMMYNET */
3873
3874#if BRIDGE_MEMBER_OUT_FILTER
3875/*
316670eb 3876 * bridge_member_output:
6d2010ae
A
3877 *
3878 * Send output from a bridge member interface. This
3879 * performs the bridging function for locally originated
3880 * packets.
3881 *
3882 * The mbuf has the Ethernet header already attached. We must
3883 * enqueue or free the mbuf before returning.
3884 */
3885static int
39236c6e
A
3886bridge_member_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
3887 struct rtentry *rt)
6d2010ae 3888{
39236c6e 3889#pragma unused(sa, rt)
6d2010ae
A
3890 struct ether_header *eh;
3891 struct ifnet *dst_if;
3892 struct bridge_softc *sc;
3893 uint16_t vlan;
3894
3895#if BRIDGE_DEBUG
5ba3f43e 3896 if (if_bridge_debug & BR_DBGF_OUTPUT)
39236c6e 3897 printf("%s: ifp %s\n", __func__, ifp->if_xname);
6d2010ae 3898#endif /* BRIDGE_DEBUG */
316670eb 3899
6d2010ae
A
3900 if (m->m_len < ETHER_HDR_LEN) {
3901 m = m_pullup(m, ETHER_HDR_LEN);
3902 if (m == NULL)
3903 return (0);
3904 }
3905
3906 eh = mtod(m, struct ether_header *);
3907 sc = ifp->if_bridge;
3908 vlan = VLANTAGOF(m);
3909
3910 BRIDGE_LOCK(sc);
3911
316670eb
A
3912 /*
3913 * APPLE MODIFICATION
6d2010ae
A
3914 * If the packet is an 802.1X ethertype, then only send on the
3915 * original output interface.
3916 */
3917 if (eh->ether_type == htons(ETHERTYPE_PAE)) {
3918 dst_if = ifp;
3919 goto sendunicast;
3920 }
316670eb 3921
6d2010ae
A
3922 /*
3923 * If bridge is down, but the original output interface is up,
3924 * go ahead and send out that interface. Otherwise, the packet
3925 * is dropped below.
3926 */
3927 if ((sc->sc_ifp->if_flags & IFF_RUNNING) == 0) {
3928 dst_if = ifp;
3929 goto sendunicast;
3930 }
3931
3932 /*
3933 * If the packet is a multicast, or we don't know a better way to
3934 * get there, send to all interfaces.
3935 */
3936 if (ETHER_IS_MULTICAST(eh->ether_dhost))
3937 dst_if = NULL;
3938 else
3939 dst_if = bridge_rtlookup(sc, eh->ether_dhost, vlan);
3940 if (dst_if == NULL) {
3941 struct bridge_iflist *bif;
3942 struct mbuf *mc;
3943 int error = 0, used = 0;
3944
3945 bridge_span(sc, m);
3946
3947 BRIDGE_LOCK2REF(sc, error);
3948 if (error) {
3949 m_freem(m);
3950 return (0);
3951 }
3952
3953 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) {
3954 dst_if = bif->bif_ifp;
3955
3956 if (dst_if->if_type == IFT_GIF)
3957 continue;
3958 if ((dst_if->if_flags & IFF_RUNNING) == 0)
3959 continue;
3960
3961 /*
3962 * If this is not the original output interface,
3963 * and the interface is participating in spanning
3964 * tree, make sure the port is in a state that
3965 * allows forwarding.
3966 */
39236c6e 3967 if (dst_if != ifp && (bif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
3968 bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
3969 continue;
3970
3971 if (LIST_NEXT(bif, bif_next) == NULL) {
3972 used = 1;
3973 mc = m;
3974 } else {
3975 mc = m_copypacket(m, M_DONTWAIT);
3976 if (mc == NULL) {
316670eb
A
3977 (void) ifnet_stat_increment_out(
3978 sc->sc_ifp, 0, 0, 1);
6d2010ae
A
3979 continue;
3980 }
3981 }
3982
316670eb 3983 (void) bridge_enqueue(sc, dst_if, mc);
6d2010ae
A
3984 }
3985 if (used == 0)
3986 m_freem(m);
3987 BRIDGE_UNREF(sc);
3988 return (0);
3989 }
3990
3991sendunicast:
3992 /*
3993 * XXX Spanning tree consideration here?
3994 */
3995
3996 bridge_span(sc, m);
3997 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
3998 m_freem(m);
3999 BRIDGE_UNLOCK(sc);
4000 return (0);
4001 }
4002
4003 BRIDGE_UNLOCK(sc);
316670eb 4004 (void) bridge_enqueue(sc, dst_if, m);
6d2010ae
A
4005 return (0);
4006}
4007#endif /* BRIDGE_MEMBER_OUT_FILTER */
4008
6d2010ae 4009/*
316670eb 4010 * Output callback.
6d2010ae 4011 *
316670eb
A
4012 * This routine is called externally from above only when if_bridge_txstart
4013 * is disabled; otherwise it is called internally by bridge_start().
6d2010ae 4014 */
316670eb
A
4015static int
4016bridge_output(struct ifnet *ifp, struct mbuf *m)
6d2010ae
A
4017{
4018 struct bridge_softc *sc = ifnet_softc(ifp);
4019 struct ether_header *eh;
4020 struct ifnet *dst_if;
316670eb 4021 int error = 0;
6d2010ae
A
4022
4023 eh = mtod(m, struct ether_header *);
316670eb
A
4024 dst_if = NULL;
4025
6d2010ae 4026 BRIDGE_LOCK(sc);
5ba3f43e
A
4027 ASSERT(bridge_in_bsd_mode(sc));
4028
39236c6e 4029 if (!(m->m_flags & (M_BCAST|M_MCAST)))
316670eb 4030 dst_if = bridge_rtlookup(sc, eh->ether_dhost, 0);
316670eb 4031
39236c6e 4032 (void) ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
316670eb
A
4033
4034#if NBPFILTER > 0
4035 if (sc->sc_bpf_output)
4036 bridge_bpf_output(ifp, m);
6d2010ae 4037#endif
316670eb
A
4038
4039 if (dst_if == NULL) {
4040 /* callee will unlock */
6d2010ae 4041 bridge_broadcast(sc, ifp, m, 0);
316670eb
A
4042 } else {
4043 BRIDGE_UNLOCK(sc);
4044 error = bridge_enqueue(sc, dst_if, m);
6d2010ae 4045 }
6d2010ae 4046
316670eb
A
4047 return (error);
4048}
4049
39236c6e
A
4050static void
4051bridge_finalize_cksum(struct ifnet *ifp, struct mbuf *m)
4052{
4053 struct ether_header *eh = mtod(m, struct ether_header *);
4054 uint32_t sw_csum, hwcap;
4055
4056 if (ifp != NULL)
4057 hwcap = (ifp->if_hwassist | CSUM_DATA_VALID);
4058 else
4059 hwcap = 0;
4060
4061 /* do in software what the hardware cannot */
4062 sw_csum = m->m_pkthdr.csum_flags & ~IF_HWASSIST_CSUM_FLAGS(hwcap);
4063 sw_csum &= IF_HWASSIST_CSUM_MASK;
4064
4065 switch (ntohs(eh->ether_type)) {
4066 case ETHERTYPE_IP:
4067 if ((hwcap & CSUM_PARTIAL) && !(sw_csum & CSUM_DELAY_DATA) &&
4068 (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) {
4069 if (m->m_pkthdr.csum_flags & CSUM_TCP) {
4070 uint16_t start =
4071 sizeof (*eh) + sizeof (struct ip);
4072 uint16_t ulpoff =
4073 m->m_pkthdr.csum_data & 0xffff;
4074 m->m_pkthdr.csum_flags |=
4075 (CSUM_DATA_VALID | CSUM_PARTIAL);
4076 m->m_pkthdr.csum_tx_stuff = (ulpoff + start);
4077 m->m_pkthdr.csum_tx_start = start;
4078 } else {
4079 sw_csum |= (CSUM_DELAY_DATA &
4080 m->m_pkthdr.csum_flags);
4081 }
4082 }
4083 (void) in_finalize_cksum(m, sizeof (*eh), sw_csum);
4084 break;
4085
4086#if INET6
4087 case ETHERTYPE_IPV6:
4088 if ((hwcap & CSUM_PARTIAL) &&
4089 !(sw_csum & CSUM_DELAY_IPV6_DATA) &&
4090 (m->m_pkthdr.csum_flags & CSUM_DELAY_IPV6_DATA)) {
4091 if (m->m_pkthdr.csum_flags & CSUM_TCPIPV6) {
4092 uint16_t start =
4093 sizeof (*eh) + sizeof (struct ip6_hdr);
4094 uint16_t ulpoff =
4095 m->m_pkthdr.csum_data & 0xffff;
4096 m->m_pkthdr.csum_flags |=
4097 (CSUM_DATA_VALID | CSUM_PARTIAL);
4098 m->m_pkthdr.csum_tx_stuff = (ulpoff + start);
4099 m->m_pkthdr.csum_tx_start = start;
4100 } else {
4101 sw_csum |= (CSUM_DELAY_IPV6_DATA &
4102 m->m_pkthdr.csum_flags);
4103 }
4104 }
4105 (void) in6_finalize_cksum(m, sizeof (*eh), -1, -1, sw_csum);
4106 break;
4107#endif /* INET6 */
4108 }
4109}
4110
316670eb
A
4111/*
4112 * bridge_start:
4113 *
4114 * Start output on a bridge.
4115 *
4116 * This routine is invoked by the start worker thread; because we never call
4117 * it directly, there is no need do deploy any serialization mechanism other
4118 * than what's already used by the worker thread, i.e. this is already single
4119 * threaded.
4120 *
4121 * This routine is called only when if_bridge_txstart is enabled.
4122 */
4123static void
4124bridge_start(struct ifnet *ifp)
4125{
4126 struct mbuf *m;
4127
4128 for (;;) {
4129 if (ifnet_dequeue(ifp, &m) != 0)
4130 break;
4131
4132 (void) bridge_output(ifp, m);
4133 }
6d2010ae
A
4134}
4135
4136/*
4137 * bridge_forward:
4138 *
4139 * The forwarding function of the bridge.
4140 *
4141 * NOTE: Releases the lock on return.
4142 */
4143static void
4144bridge_forward(struct bridge_softc *sc, struct bridge_iflist *sbif,
39236c6e 4145 struct mbuf *m)
6d2010ae
A
4146{
4147 struct bridge_iflist *dbif;
4148 struct ifnet *src_if, *dst_if, *ifp;
4149 struct ether_header *eh;
4150 uint16_t vlan;
4151 uint8_t *dst;
4152 int error;
4153
39236c6e 4154 BRIDGE_LOCK_ASSERT_HELD(sc);
5ba3f43e 4155 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae
A
4156
4157#if BRIDGE_DEBUG
5ba3f43e 4158 if (if_bridge_debug & BR_DBGF_OUTPUT)
39236c6e
A
4159 printf("%s: %s m 0x%llx\n", __func__, sc->sc_ifp->if_xname,
4160 (uint64_t)VM_KERNEL_ADDRPERM(m));
6d2010ae 4161#endif /* BRIDGE_DEBUG */
316670eb 4162
6d2010ae
A
4163 src_if = m->m_pkthdr.rcvif;
4164 ifp = sc->sc_ifp;
4165
4166 (void) ifnet_stat_increment_in(ifp, 1, m->m_pkthdr.len, 0);
4167 vlan = VLANTAGOF(m);
4168
4169
39236c6e 4170 if ((sbif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
4171 sbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
4172 goto drop;
4173
4174 eh = mtod(m, struct ether_header *);
4175 dst = eh->ether_dhost;
4176
4177 /* If the interface is learning, record the address. */
39236c6e 4178 if (sbif->bif_ifflags & IFBIF_LEARNING) {
6d2010ae
A
4179 error = bridge_rtupdate(sc, eh->ether_shost, vlan,
4180 sbif, 0, IFBAF_DYNAMIC);
4181 /*
4182 * If the interface has addresses limits then deny any source
4183 * that is not in the cache.
4184 */
4185 if (error && sbif->bif_addrmax)
4186 goto drop;
4187 }
4188
39236c6e 4189 if ((sbif->bif_ifflags & IFBIF_STP) != 0 &&
6d2010ae
A
4190 sbif->bif_stp.bp_state == BSTP_IFSTATE_LEARNING)
4191 goto drop;
4192
4193 /*
4194 * At this point, the port either doesn't participate
4195 * in spanning tree or it is in the forwarding state.
4196 */
4197
4198 /*
4199 * If the packet is unicast, destined for someone on
4200 * "this" side of the bridge, drop it.
4201 */
4202 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
4203 dst_if = bridge_rtlookup(sc, dst, vlan);
4204 if (src_if == dst_if)
4205 goto drop;
4206 } else {
4207 /*
4208 * Check if its a reserved multicast address, any address
4209 * listed in 802.1D section 7.12.6 may not be forwarded by the
4210 * bridge.
4211 * This is currently 01-80-C2-00-00-00 to 01-80-C2-00-00-0F
4212 */
4213 if (dst[0] == 0x01 && dst[1] == 0x80 &&
4214 dst[2] == 0xc2 && dst[3] == 0x00 &&
4215 dst[4] == 0x00 && dst[5] <= 0x0f)
4216 goto drop;
4217
4218
4219 /* ...forward it to all interfaces. */
4220 atomic_add_64(&ifp->if_imcasts, 1);
4221 dst_if = NULL;
4222 }
4223
4224 /*
4225 * If we have a destination interface which is a member of our bridge,
4226 * OR this is a unicast packet, push it through the bpf(4) machinery.
4227 * For broadcast or multicast packets, don't bother because it will
4228 * be reinjected into ether_input. We do this before we pass the packets
4229 * through the pfil(9) framework, as it is possible that pfil(9) will
4230 * drop the packet, or possibly modify it, making it difficult to debug
4231 * firewall issues on the bridge.
4232 */
4233#if NBPFILTER > 0
4234 if (eh->ether_type == htons(ETHERTYPE_RSN_PREAUTH) ||
316670eb
A
4235 dst_if != NULL || (m->m_flags & (M_BCAST | M_MCAST)) == 0) {
4236 m->m_pkthdr.rcvif = ifp;
6d2010ae 4237 if (sc->sc_bpf_input)
316670eb 4238 bridge_bpf_input(ifp, m);
6d2010ae
A
4239 }
4240#endif /* NBPFILTER */
4241
4242#if defined(PFIL_HOOKS)
4243 /* run the packet filter */
39236c6e 4244 if (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6) {
6d2010ae
A
4245 BRIDGE_UNLOCK(sc);
4246 if (bridge_pfil(&m, ifp, src_if, PFIL_IN) != 0)
4247 return;
4248 if (m == NULL)
4249 return;
4250 BRIDGE_LOCK(sc);
4251 }
4252#endif /* PFIL_HOOKS */
4253
4254 if (dst_if == NULL) {
6d2010ae 4255 bridge_broadcast(sc, src_if, m, 1);
6d2010ae
A
4256 return;
4257 }
4258
4259 /*
4260 * At this point, we're dealing with a unicast frame
4261 * going to a different interface.
4262 */
4263 if ((dst_if->if_flags & IFF_RUNNING) == 0)
4264 goto drop;
4265
4266 dbif = bridge_lookup_member_if(sc, dst_if);
4267 if (dbif == NULL)
4268 /* Not a member of the bridge (anymore?) */
4269 goto drop;
4270
4271 /* Private segments can not talk to each other */
39236c6e 4272 if (sbif->bif_ifflags & dbif->bif_ifflags & IFBIF_PRIVATE)
6d2010ae
A
4273 goto drop;
4274
39236c6e 4275 if ((dbif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
4276 dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
4277 goto drop;
4278
4279#if HAS_DHCPRA_MASK
39236c6e 4280 /* APPLE MODIFICATION <rdar:6985737> */
6d2010ae
A
4281 if ((dst_if->if_extflags & IFEXTF_DHCPRA_MASK) != 0) {
4282 m = ip_xdhcpra_output(dst_if, m);
4283 if (!m) {
4284 ++sc->sc_sc.sc_ifp.if_xdhcpra;
4285 return;
4286 }
4287 }
4288#endif /* HAS_DHCPRA_MASK */
4289
4290 BRIDGE_UNLOCK(sc);
4291
4292#if defined(PFIL_HOOKS)
39236c6e 4293 if (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6) {
6d2010ae
A
4294 if (bridge_pfil(&m, ifp, dst_if, PFIL_OUT) != 0)
4295 return;
4296 if (m == NULL)
4297 return;
4298 }
4299#endif /* PFIL_HOOKS */
4300
316670eb 4301 (void) bridge_enqueue(sc, dst_if, m);
6d2010ae
A
4302 return;
4303
4304drop:
4305 BRIDGE_UNLOCK(sc);
4306 m_freem(m);
4307}
4308
4309#if BRIDGE_DEBUG
4310
316670eb 4311char *ether_ntop(char *, size_t, const u_char *);
6d2010ae
A
4312
4313__private_extern__ char *
4314ether_ntop(char *buf, size_t len, const u_char *ap)
4315{
316670eb
A
4316 snprintf(buf, len, "%02x:%02x:%02x:%02x:%02x:%02x",
4317 ap[0], ap[1], ap[2], ap[3], ap[4], ap[5]);
4318
4319 return (buf);
6d2010ae
A
4320}
4321
4322#endif /* BRIDGE_DEBUG */
4323
4324/*
4325 * bridge_input:
4326 *
4327 * Filter input from a member interface. Queue the packet for
4328 * bridging if it is not for us.
4329 */
4330__private_extern__ errno_t
39236c6e 4331bridge_input(struct ifnet *ifp, struct mbuf *m, void *frame_header)
6d2010ae
A
4332{
4333 struct bridge_softc *sc = ifp->if_bridge;
4334 struct bridge_iflist *bif, *bif2;
4335 struct ifnet *bifp;
4336 struct ether_header *eh;
4337 struct mbuf *mc, *mc2;
4338 uint16_t vlan;
4339 int error;
4340
5ba3f43e 4341 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae 4342#if BRIDGE_DEBUG
39236c6e
A
4343 if (if_bridge_debug & BR_DBGF_INPUT)
4344 printf("%s: %s from %s m 0x%llx data 0x%llx\n", __func__,
4345 sc->sc_ifp->if_xname, ifp->if_xname,
4346 (uint64_t)VM_KERNEL_ADDRPERM(m),
4347 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_data(m)));
6d2010ae
A
4348#endif /* BRIDGE_DEBUG */
4349
4350 if ((sc->sc_ifp->if_flags & IFF_RUNNING) == 0) {
4351#if BRIDGE_DEBUG
39236c6e
A
4352 if (if_bridge_debug & BR_DBGF_INPUT)
4353 printf("%s: %s not running passing along\n",
4354 __func__, sc->sc_ifp->if_xname);
6d2010ae 4355#endif /* BRIDGE_DEBUG */
316670eb 4356 return (0);
6d2010ae 4357 }
316670eb 4358
6d2010ae
A
4359 bifp = sc->sc_ifp;
4360 vlan = VLANTAGOF(m);
4361
4362#ifdef IFF_MONITOR
4363 /*
4364 * Implement support for bridge monitoring. If this flag has been
4365 * set on this interface, discard the packet once we push it through
4366 * the bpf(4) machinery, but before we do, increment the byte and
4367 * packet counters associated with this interface.
4368 */
4369 if ((bifp->if_flags & IFF_MONITOR) != 0) {
4370 m->m_pkthdr.rcvif = bifp;
4371 BRIDGE_BPF_MTAP_INPUT(sc, m);
4372 (void) ifnet_stat_increment_in(bifp, 1, m->m_pkthdr.len, 0);
4373 m_freem(m);
316670eb 4374 return (EJUSTRETURN);
6d2010ae
A
4375 }
4376#endif /* IFF_MONITOR */
4377
316670eb
A
4378 /*
4379 * Need to clear the promiscous flags otherwise it will be
4380 * dropped by DLIL after processing filters
6d2010ae
A
4381 */
4382 if ((mbuf_flags(m) & MBUF_PROMISC))
4383 mbuf_setflags_mask(m, 0, MBUF_PROMISC);
316670eb 4384
6d2010ae
A
4385 BRIDGE_LOCK(sc);
4386 bif = bridge_lookup_member_if(sc, ifp);
4387 if (bif == NULL) {
4388 BRIDGE_UNLOCK(sc);
4389#if BRIDGE_DEBUG
39236c6e
A
4390 if (if_bridge_debug & BR_DBGF_INPUT)
4391 printf("%s: %s bridge_lookup_member_if failed\n",
4392 __func__, sc->sc_ifp->if_xname);
6d2010ae 4393#endif /* BRIDGE_DEBUG */
316670eb 4394 return (0);
6d2010ae
A
4395 }
4396
fe8ab488
A
4397 if (bif->bif_flags & BIFF_HOST_FILTER) {
4398 error = bridge_host_filter(bif, m);
4399 if (error != 0) {
4400 if (if_bridge_debug & BR_DBGF_INPUT)
4401 printf("%s: %s bridge_host_filter failed\n",
4402 __func__, bif->bif_ifp->if_xname);
4403 BRIDGE_UNLOCK(sc);
4404 return (EJUSTRETURN);
4405 }
4406 }
4407
6d2010ae
A
4408 eh = mtod(m, struct ether_header *);
4409
4410 bridge_span(sc, m);
4411
4412 if (m->m_flags & (M_BCAST|M_MCAST)) {
4413
4414#if BRIDGE_DEBUG
39236c6e 4415 if (if_bridge_debug & BR_DBGF_MCAST)
6d2010ae 4416 if ((m->m_flags & M_MCAST))
39236c6e 4417 printf("%s: multicast: "
316670eb
A
4418 "%02x:%02x:%02x:%02x:%02x:%02x\n",
4419 __func__,
4420 eh->ether_dhost[0], eh->ether_dhost[1],
4421 eh->ether_dhost[2], eh->ether_dhost[3],
4422 eh->ether_dhost[4], eh->ether_dhost[5]);
6d2010ae
A
4423#endif /* BRIDGE_DEBUG */
4424
4425 /* Tap off 802.1D packets; they do not get forwarded. */
4426 if (memcmp(eh->ether_dhost, bstp_etheraddr,
4427 ETHER_ADDR_LEN) == 0) {
316670eb 4428#if BRIDGESTP
6d2010ae 4429 m = bstp_input(&bif->bif_stp, ifp, m);
316670eb
A
4430#else /* !BRIDGESTP */
4431 m_freem(m);
4432 m = NULL;
4433#endif /* !BRIDGESTP */
6d2010ae
A
4434 if (m == NULL) {
4435 BRIDGE_UNLOCK(sc);
316670eb 4436 return (EJUSTRETURN);
6d2010ae
A
4437 }
4438 }
4439
39236c6e 4440 if ((bif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
4441 bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
4442 BRIDGE_UNLOCK(sc);
316670eb 4443 return (0);
6d2010ae
A
4444 }
4445
4446 /*
4447 * Make a deep copy of the packet and enqueue the copy
4448 * for bridge processing; return the original packet for
4449 * local processing.
4450 */
4451 mc = m_dup(m, M_DONTWAIT);
4452 if (mc == NULL) {
4453 BRIDGE_UNLOCK(sc);
316670eb 4454 return (0);
6d2010ae
A
4455 }
4456
316670eb
A
4457 /*
4458 * Perform the bridge forwarding function with the copy.
6d2010ae
A
4459 *
4460 * Note that bridge_forward calls BRIDGE_UNLOCK
4461 */
4462 bridge_forward(sc, bif, mc);
316670eb 4463
6d2010ae
A
4464 /*
4465 * Reinject the mbuf as arriving on the bridge so we have a
4466 * chance at claiming multicast packets. We can not loop back
4467 * here from ether_input as a bridge is never a member of a
4468 * bridge.
4469 */
39236c6e 4470 VERIFY(bifp->if_bridge == NULL);
6d2010ae
A
4471 mc2 = m_dup(m, M_DONTWAIT);
4472 if (mc2 != NULL) {
4473 /* Keep the layer3 header aligned */
4474 int i = min(mc2->m_pkthdr.len, max_protohdr);
4475 mc2 = m_copyup(mc2, i, ETHER_ALIGN);
4476 }
4477 if (mc2 != NULL) {
39236c6e 4478 /* mark packet as arriving on the bridge */
6d2010ae 4479 mc2->m_pkthdr.rcvif = bifp;
39236c6e 4480 mc2->m_pkthdr.pkt_hdr = mbuf_data(mc2);
316670eb 4481
6d2010ae
A
4482#if NBPFILTER > 0
4483 if (sc->sc_bpf_input)
4484 bridge_bpf_input(bifp, mc2);
4485#endif /* NBPFILTER */
316670eb
A
4486 (void) mbuf_setdata(mc2,
4487 (char *)mbuf_data(mc2) + ETHER_HDR_LEN,
4488 mbuf_len(mc2) - ETHER_HDR_LEN);
6d2010ae 4489 (void) mbuf_pkthdr_adjustlen(mc2, - ETHER_HDR_LEN);
316670eb
A
4490
4491 (void) ifnet_stat_increment_in(bifp, 1,
4492 mbuf_pkthdr_len(mc2), 0);
4493
6d2010ae 4494#if BRIDGE_DEBUG
39236c6e
A
4495 if (if_bridge_debug & BR_DBGF_MCAST)
4496 printf("%s: %s mcast for us\n", __func__,
4497 sc->sc_ifp->if_xname);
6d2010ae 4498#endif /* BRIDGE_DEBUG */
316670eb 4499
6d2010ae
A
4500 dlil_input_packet_list(bifp, mc2);
4501 }
4502
4503 /* Return the original packet for local processing. */
316670eb 4504 return (0);
6d2010ae
A
4505 }
4506
39236c6e 4507 if ((bif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
4508 bif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING) {
4509 BRIDGE_UNLOCK(sc);
316670eb 4510 return (0);
6d2010ae
A
4511 }
4512
4513#ifdef DEV_CARP
39236c6e
A
4514#define CARP_CHECK_WE_ARE_DST(iface) \
4515 ((iface)->if_carp &&\
4516 carp_forus((iface)->if_carp, eh->ether_dhost))
4517#define CARP_CHECK_WE_ARE_SRC(iface) \
4518 ((iface)->if_carp &&\
4519 carp_forus((iface)->if_carp, eh->ether_shost))
6d2010ae 4520#else
39236c6e
A
4521#define CARP_CHECK_WE_ARE_DST(iface) 0
4522#define CARP_CHECK_WE_ARE_SRC(iface) 0
6d2010ae
A
4523#endif
4524
4525#ifdef INET6
39236c6e 4526#define PFIL_HOOKED_INET6 PFIL_HOOKED(&inet6_pfil_hook)
6d2010ae 4527#else
39236c6e 4528#define PFIL_HOOKED_INET6 0
6d2010ae
A
4529#endif
4530
4531#if defined(PFIL_HOOKS)
316670eb
A
4532#define PFIL_PHYS(sc, ifp, m) do { \
4533 if (pfil_local_phys && \
39236c6e 4534 (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6)) { \
316670eb
A
4535 if (bridge_pfil(&m, NULL, ifp, \
4536 PFIL_IN) != 0 || m == NULL) { \
4537 BRIDGE_UNLOCK(sc); \
4538 return (NULL); \
4539 } \
4540 } \
4541} while (0)
6d2010ae
A
4542#else /* PFIL_HOOKS */
4543#define PFIL_PHYS(sc, ifp, m)
4544#endif /* PFIL_HOOKS */
4545
316670eb
A
4546#define GRAB_OUR_PACKETS(iface) \
4547 if ((iface)->if_type == IFT_GIF) \
4548 continue; \
4549 /* It is destined for us. */ \
39236c6e
A
4550 if (memcmp(IF_LLADDR((iface)), eh->ether_dhost, \
4551 ETHER_ADDR_LEN) == 0 || CARP_CHECK_WE_ARE_DST((iface))) { \
6d2010ae
A
4552 if ((iface)->if_type == IFT_BRIDGE) { \
4553 BRIDGE_BPF_MTAP_INPUT(sc, m); \
4554 /* Filter on the physical interface. */ \
316670eb 4555 PFIL_PHYS(sc, iface, m); \
6d2010ae 4556 } \
39236c6e 4557 if (bif->bif_ifflags & IFBIF_LEARNING) { \
6d2010ae
A
4558 error = bridge_rtupdate(sc, eh->ether_shost, \
4559 vlan, bif, 0, IFBAF_DYNAMIC); \
4560 if (error && bif->bif_addrmax) { \
4561 BRIDGE_UNLOCK(sc); \
316670eb 4562 return (EJUSTRETURN); \
6d2010ae
A
4563 } \
4564 } \
4565 m->m_pkthdr.rcvif = iface; \
4566 BRIDGE_UNLOCK(sc); \
316670eb 4567 return (0); \
6d2010ae
A
4568 } \
4569 \
4570 /* We just received a packet that we sent out. */ \
39236c6e
A
4571 if (memcmp(IF_LLADDR((iface)), eh->ether_shost, \
4572 ETHER_ADDR_LEN) == 0 || CARP_CHECK_WE_ARE_SRC((iface))) { \
6d2010ae 4573 BRIDGE_UNLOCK(sc); \
316670eb 4574 return (EJUSTRETURN); \
6d2010ae
A
4575 }
4576
4577 /*
4578 * Unicast.
4579 */
4580 /*
4581 * If the packet is for us, set the packets source as the
4582 * bridge, and return the packet back to ether_input for
4583 * local processing.
4584 */
39236c6e
A
4585 if (memcmp(eh->ether_dhost, IF_LLADDR(bifp),
4586 ETHER_ADDR_LEN) == 0 || CARP_CHECK_WE_ARE_DST(bifp)) {
316670eb 4587
6d2010ae
A
4588 /* Mark the packet as arriving on the bridge interface */
4589 (void) mbuf_pkthdr_setrcvif(m, bifp);
4590 mbuf_pkthdr_setheader(m, frame_header);
316670eb 4591
6d2010ae
A
4592 /*
4593 * If the interface is learning, and the source
4594 * address is valid and not multicast, record
4595 * the address.
4596 */
39236c6e 4597 if (bif->bif_ifflags & IFBIF_LEARNING)
316670eb
A
4598 (void) bridge_rtupdate(sc, eh->ether_shost,
4599 vlan, bif, 0, IFBAF_DYNAMIC);
316670eb 4600
6d2010ae
A
4601 BRIDGE_BPF_MTAP_INPUT(sc, m);
4602
316670eb
A
4603 (void) mbuf_setdata(m, (char *)mbuf_data(m) + ETHER_HDR_LEN,
4604 mbuf_len(m) - ETHER_HDR_LEN);
6d2010ae 4605 (void) mbuf_pkthdr_adjustlen(m, - ETHER_HDR_LEN);
316670eb 4606
6d2010ae
A
4607 (void) ifnet_stat_increment_in(bifp, 1, mbuf_pkthdr_len(m), 0);
4608
4609 BRIDGE_UNLOCK(sc);
316670eb 4610
6d2010ae 4611#if BRIDGE_DEBUG
39236c6e
A
4612 if (if_bridge_debug & BR_DBGF_INPUT)
4613 printf("%s: %s packet for bridge\n", __func__,
4614 sc->sc_ifp->if_xname);
6d2010ae 4615#endif /* BRIDGE_DEBUG */
316670eb 4616
6d2010ae 4617 dlil_input_packet_list(bifp, m);
316670eb
A
4618
4619 return (EJUSTRETURN);
6d2010ae
A
4620 }
4621
4622 /*
316670eb 4623 * if the destination of the packet is for the MAC address of
6d2010ae
A
4624 * the member interface itself, then we don't need to forward
4625 * it -- just pass it back. Note that it'll likely just be
316670eb 4626 * dropped by the stack, but if something else is bound to
6d2010ae 4627 * the interface directly (for example, the wireless stats
316670eb 4628 * protocol -- although that actually uses BPF right now),
6d2010ae
A
4629 * then it will consume the packet
4630 *
316670eb 4631 * ALSO, note that we do this check AFTER checking for the
6d2010ae
A
4632 * bridge's own MAC address, because the bridge may be
4633 * using the SAME MAC address as one of its interfaces
4634 */
39236c6e 4635 if (memcmp(eh->ether_dhost, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0) {
316670eb 4636
6d2010ae 4637#ifdef VERY_VERY_VERY_DIAGNOSTIC
316670eb
A
4638 printf("%s: not forwarding packet bound for member "
4639 "interface\n", __func__);
6d2010ae
A
4640#endif
4641 BRIDGE_UNLOCK(sc);
316670eb 4642 return (0);
6d2010ae
A
4643 }
4644
4645 /* Now check the all bridge members. */
4646 TAILQ_FOREACH(bif2, &sc->sc_iflist, bif_next) {
4647 GRAB_OUR_PACKETS(bif2->bif_ifp)
4648 }
4649
39236c6e
A
4650#undef CARP_CHECK_WE_ARE_DST
4651#undef CARP_CHECK_WE_ARE_SRC
6d2010ae
A
4652#undef GRAB_OUR_PACKETS
4653
316670eb
A
4654 /*
4655 * Perform the bridge forwarding function.
6d2010ae
A
4656 *
4657 * Note that bridge_forward calls BRIDGE_UNLOCK
4658 */
4659 bridge_forward(sc, bif, m);
4660
316670eb 4661 return (EJUSTRETURN);
6d2010ae
A
4662}
4663
4664/*
4665 * bridge_broadcast:
4666 *
4667 * Send a frame to all interfaces that are members of
4668 * the bridge, except for the one on which the packet
4669 * arrived.
4670 *
4671 * NOTE: Releases the lock on return.
4672 */
4673static void
4674bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if,
39236c6e 4675 struct mbuf *m, int runfilt)
6d2010ae
A
4676{
4677#ifndef PFIL_HOOKS
4678#pragma unused(runfilt)
4679#endif
4680 struct bridge_iflist *dbif, *sbif;
4681 struct mbuf *mc;
4682 struct ifnet *dst_if;
4683 int error = 0, used = 0;
4684
4685 sbif = bridge_lookup_member_if(sc, src_if);
4686
4687 BRIDGE_LOCK2REF(sc, error);
4688 if (error) {
4689 m_freem(m);
4690 return;
4691 }
4692
4693#ifdef PFIL_HOOKS
4694 /* Filter on the bridge interface before broadcasting */
39236c6e 4695 if (runfilt && (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6)) {
6d2010ae
A
4696 if (bridge_pfil(&m, sc->sc_ifp, NULL, PFIL_OUT) != 0)
4697 goto out;
4698 if (m == NULL)
4699 goto out;
4700 }
4701#endif /* PFIL_HOOKS */
4702
4703 TAILQ_FOREACH(dbif, &sc->sc_iflist, bif_next) {
4704 dst_if = dbif->bif_ifp;
4705 if (dst_if == src_if)
4706 continue;
4707
4708 /* Private segments can not talk to each other */
39236c6e
A
4709 if (sbif &&
4710 (sbif->bif_ifflags & dbif->bif_ifflags & IFBIF_PRIVATE))
6d2010ae
A
4711 continue;
4712
39236c6e 4713 if ((dbif->bif_ifflags & IFBIF_STP) &&
6d2010ae
A
4714 dbif->bif_stp.bp_state == BSTP_IFSTATE_DISCARDING)
4715 continue;
4716
39236c6e 4717 if ((dbif->bif_ifflags & IFBIF_DISCOVER) == 0 &&
6d2010ae
A
4718 (m->m_flags & (M_BCAST|M_MCAST)) == 0)
4719 continue;
4720
4721 if ((dst_if->if_flags & IFF_RUNNING) == 0)
4722 continue;
4723
fe8ab488
A
4724 if (!(dbif->bif_flags & BIFF_MEDIA_ACTIVE)) {
4725 continue;
4726 }
4727
6d2010ae
A
4728 if (TAILQ_NEXT(dbif, bif_next) == NULL) {
4729 mc = m;
4730 used = 1;
4731 } else {
4732 mc = m_dup(m, M_DONTWAIT);
4733 if (mc == NULL) {
316670eb
A
4734 (void) ifnet_stat_increment_out(sc->sc_ifp,
4735 0, 0, 1);
6d2010ae
A
4736 continue;
4737 }
4738 }
4739
4740#ifdef PFIL_HOOKS
4741 /*
4742 * Filter on the output interface. Pass a NULL bridge interface
4743 * pointer so we do not redundantly filter on the bridge for
4744 * each interface we broadcast on.
4745 */
39236c6e
A
4746 if (runfilt &&
4747 (PFIL_HOOKED(&inet_pfil_hook) || PFIL_HOOKED_INET6)) {
6d2010ae
A
4748 if (used == 0) {
4749 /* Keep the layer3 header aligned */
4750 int i = min(mc->m_pkthdr.len, max_protohdr);
4751 mc = m_copyup(mc, i, ETHER_ALIGN);
4752 if (mc == NULL) {
316670eb
A
4753 (void) ifnet_stat_increment_out(
4754 sc->sc_ifp, 0, 0, 1);
6d2010ae
A
4755 continue;
4756 }
4757 }
4758 if (bridge_pfil(&mc, NULL, dst_if, PFIL_OUT) != 0)
4759 continue;
4760 if (mc == NULL)
4761 continue;
4762 }
4763#endif /* PFIL_HOOKS */
4764
316670eb 4765 (void) bridge_enqueue(sc, dst_if, mc);
6d2010ae
A
4766 }
4767 if (used == 0)
4768 m_freem(m);
4769
4770#ifdef PFIL_HOOKS
4771out:
4772#endif /* PFIL_HOOKS */
4773
4774 BRIDGE_UNREF(sc);
4775}
4776
4777/*
4778 * bridge_span:
4779 *
4780 * Duplicate a packet out one or more interfaces that are in span mode,
4781 * the original mbuf is unmodified.
4782 */
4783static void
4784bridge_span(struct bridge_softc *sc, struct mbuf *m)
4785{
4786 struct bridge_iflist *bif;
4787 struct ifnet *dst_if;
4788 struct mbuf *mc;
4789
4790 if (TAILQ_EMPTY(&sc->sc_spanlist))
4791 return;
4792
4793 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next) {
4794 dst_if = bif->bif_ifp;
4795
4796 if ((dst_if->if_flags & IFF_RUNNING) == 0)
4797 continue;
4798
4799 mc = m_copypacket(m, M_DONTWAIT);
4800 if (mc == NULL) {
4801 (void) ifnet_stat_increment_out(sc->sc_ifp, 0, 0, 1);
4802 continue;
4803 }
4804
316670eb 4805 (void) bridge_enqueue(sc, dst_if, mc);
6d2010ae
A
4806 }
4807}
4808
4809
6d2010ae
A
4810/*
4811 * bridge_rtupdate:
4812 *
4813 * Add a bridge routing entry.
4814 */
4815static int
4816bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan,
39236c6e 4817 struct bridge_iflist *bif, int setflags, uint8_t flags)
6d2010ae
A
4818{
4819 struct bridge_rtnode *brt;
4820 int error;
4821
39236c6e 4822 BRIDGE_LOCK_ASSERT_HELD(sc);
5ba3f43e 4823 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae
A
4824
4825 /* Check the source address is valid and not multicast. */
4826 if (ETHER_IS_MULTICAST(dst) ||
4827 (dst[0] == 0 && dst[1] == 0 && dst[2] == 0 &&
316670eb 4828 dst[3] == 0 && dst[4] == 0 && dst[5] == 0) != 0)
6d2010ae
A
4829 return (EINVAL);
4830
4831
4832 /* 802.1p frames map to vlan 1 */
4833 if (vlan == 0)
4834 vlan = 1;
4835
4836 /*
4837 * A route for this destination might already exist. If so,
4838 * update it, otherwise create a new one.
4839 */
4840 if ((brt = bridge_rtnode_lookup(sc, dst, vlan)) == NULL) {
4841 if (sc->sc_brtcnt >= sc->sc_brtmax) {
4842 sc->sc_brtexceeded++;
4843 return (ENOSPC);
4844 }
4845 /* Check per interface address limits (if enabled) */
4846 if (bif->bif_addrmax && bif->bif_addrcnt >= bif->bif_addrmax) {
4847 bif->bif_addrexceeded++;
4848 return (ENOSPC);
4849 }
4850
4851 /*
4852 * Allocate a new bridge forwarding node, and
4853 * initialize the expiration time and Ethernet
4854 * address.
4855 */
4856 brt = zalloc_noblock(bridge_rtnode_pool);
4857 if (brt == NULL)
4858 return (ENOMEM);
39236c6e 4859 bzero(brt, sizeof(struct bridge_rtnode));
6d2010ae 4860
39236c6e 4861 if (bif->bif_ifflags & IFBIF_STICKY)
6d2010ae
A
4862 brt->brt_flags = IFBAF_STICKY;
4863 else
4864 brt->brt_flags = IFBAF_DYNAMIC;
4865
4866 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN);
4867 brt->brt_vlan = vlan;
4868
4869
4870 if ((error = bridge_rtnode_insert(sc, brt)) != 0) {
4871 zfree(bridge_rtnode_pool, brt);
4872 return (error);
4873 }
4874 brt->brt_dst = bif;
4875 bif->bif_addrcnt++;
39236c6e
A
4876#if BRIDGE_DEBUG
4877 if (if_bridge_debug & BR_DBGF_RT_TABLE)
4878 printf("%s: added %02x:%02x:%02x:%02x:%02x:%02x "
4879 "on %s count %u hashsize %u\n", __func__,
4880 dst[0], dst[1], dst[2], dst[3], dst[4], dst[5],
4881 sc->sc_ifp->if_xname, sc->sc_brtcnt,
4882 sc->sc_rthash_size);
4883#endif
6d2010ae
A
4884 }
4885
4886 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC &&
4887 brt->brt_dst != bif) {
4888 brt->brt_dst->bif_addrcnt--;
4889 brt->brt_dst = bif;
4890 brt->brt_dst->bif_addrcnt++;
4891 }
4892
4893 if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
39236c6e 4894 unsigned long now;
316670eb 4895
39236c6e
A
4896 now = (unsigned long) net_uptime();
4897 brt->brt_expire = now + sc->sc_brttimeout;
6d2010ae
A
4898 }
4899 if (setflags)
4900 brt->brt_flags = flags;
4901
316670eb 4902
6d2010ae
A
4903 return (0);
4904}
4905
4906/*
4907 * bridge_rtlookup:
4908 *
4909 * Lookup the destination interface for an address.
4910 */
4911static struct ifnet *
4912bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr, uint16_t vlan)
4913{
4914 struct bridge_rtnode *brt;
4915
39236c6e 4916 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
4917
4918 if ((brt = bridge_rtnode_lookup(sc, addr, vlan)) == NULL)
4919 return (NULL);
4920
4921 return (brt->brt_ifp);
4922}
4923
4924/*
4925 * bridge_rttrim:
4926 *
4927 * Trim the routine table so that we have a number
4928 * of routing entries less than or equal to the
4929 * maximum number.
4930 */
4931static void
4932bridge_rttrim(struct bridge_softc *sc)
4933{
4934 struct bridge_rtnode *brt, *nbrt;
4935
39236c6e 4936 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
4937
4938 /* Make sure we actually need to do this. */
4939 if (sc->sc_brtcnt <= sc->sc_brtmax)
4940 return;
4941
4942 /* Force an aging cycle; this might trim enough addresses. */
4943 bridge_rtage(sc);
4944 if (sc->sc_brtcnt <= sc->sc_brtmax)
4945 return;
4946
4947 LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) {
4948 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
4949 bridge_rtnode_destroy(sc, brt);
4950 if (sc->sc_brtcnt <= sc->sc_brtmax)
4951 return;
4952 }
4953 }
4954}
4955
4956/*
39236c6e 4957 * bridge_aging_timer:
6d2010ae 4958 *
39236c6e 4959 * Aging periodic timer for the bridge routing table.
6d2010ae
A
4960 */
4961static void
39236c6e 4962bridge_aging_timer(struct bridge_softc *sc)
6d2010ae 4963{
39236c6e 4964 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
4965
4966 bridge_rtage(sc);
4967
39236c6e
A
4968 if ((sc->sc_ifp->if_flags & IFF_RUNNING) &&
4969 (sc->sc_flags & SCF_DETACHING) == 0) {
4970 sc->sc_aging_timer.bdc_sc = sc;
4971 sc->sc_aging_timer.bdc_func = bridge_aging_timer;
4972 sc->sc_aging_timer.bdc_ts.tv_sec = bridge_rtable_prune_period;
4973 bridge_schedule_delayed_call(&sc->sc_aging_timer);
6d2010ae
A
4974 }
4975}
4976
4977/*
4978 * bridge_rtage:
4979 *
4980 * Perform an aging cycle.
4981 */
4982static void
4983bridge_rtage(struct bridge_softc *sc)
4984{
4985 struct bridge_rtnode *brt, *nbrt;
39236c6e 4986 unsigned long now;
6d2010ae 4987
39236c6e
A
4988 BRIDGE_LOCK_ASSERT_HELD(sc);
4989
4990 now = (unsigned long) net_uptime();
6d2010ae
A
4991
4992 LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) {
4993 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
39236c6e 4994 if (now >= brt->brt_expire)
6d2010ae
A
4995 bridge_rtnode_destroy(sc, brt);
4996 }
4997 }
4998}
4999
5000/*
5001 * bridge_rtflush:
5002 *
5003 * Remove all dynamic addresses from the bridge.
5004 */
5005static void
5006bridge_rtflush(struct bridge_softc *sc, int full)
5007{
5008 struct bridge_rtnode *brt, *nbrt;
5009
39236c6e 5010 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
5011
5012 LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) {
5013 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
5014 bridge_rtnode_destroy(sc, brt);
5015 }
5016}
5017
5018/*
5019 * bridge_rtdaddr:
5020 *
5021 * Remove an address from the table.
5022 */
5023static int
5024bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr, uint16_t vlan)
5025{
5026 struct bridge_rtnode *brt;
5027 int found = 0;
5028
39236c6e 5029 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
5030
5031 /*
5032 * If vlan is zero then we want to delete for all vlans so the lookup
5033 * may return more than one.
5034 */
5035 while ((brt = bridge_rtnode_lookup(sc, addr, vlan)) != NULL) {
5036 bridge_rtnode_destroy(sc, brt);
5037 found = 1;
5038 }
5039
5040 return (found ? 0 : ENOENT);
5041}
5042
5043/*
5044 * bridge_rtdelete:
5045 *
5046 * Delete routes to a speicifc member interface.
5047 */
5048static void
5049bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp, int full)
5050{
5051 struct bridge_rtnode *brt, *nbrt;
5052
39236c6e 5053 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
5054
5055 LIST_FOREACH_SAFE(brt, &sc->sc_rtlist, brt_list, nbrt) {
5056 if (brt->brt_ifp == ifp && (full ||
316670eb 5057 (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC))
6d2010ae
A
5058 bridge_rtnode_destroy(sc, brt);
5059 }
5060}
5061
5062/*
5063 * bridge_rtable_init:
5064 *
5065 * Initialize the route table for this bridge.
5066 */
5067static int
5068bridge_rtable_init(struct bridge_softc *sc)
5069{
39236c6e 5070 u_int32_t i;
6d2010ae 5071
5ba3f43e
A
5072 ASSERT(bridge_in_bsd_mode(sc));
5073
316670eb 5074 sc->sc_rthash = _MALLOC(sizeof (*sc->sc_rthash) * BRIDGE_RTHASH_SIZE,
39236c6e
A
5075 M_DEVBUF, M_WAITOK | M_ZERO);
5076 if (sc->sc_rthash == NULL) {
5077 printf("%s: no memory\n", __func__);
6d2010ae 5078 return (ENOMEM);
39236c6e
A
5079 }
5080 sc->sc_rthash_size = BRIDGE_RTHASH_SIZE;
6d2010ae 5081
39236c6e 5082 for (i = 0; i < sc->sc_rthash_size; i++)
6d2010ae
A
5083 LIST_INIT(&sc->sc_rthash[i]);
5084
39236c6e 5085 sc->sc_rthash_key = RandomULong();
6d2010ae
A
5086
5087 LIST_INIT(&sc->sc_rtlist);
5088
5089 return (0);
5090}
5091
39236c6e
A
5092/*
5093 * bridge_rthash_delayed_resize:
5094 *
5095 * Resize the routing table hash on a delayed thread call.
5096 */
5097static void
5098bridge_rthash_delayed_resize(struct bridge_softc *sc)
5099{
5100 u_int32_t new_rthash_size;
5101 struct _bridge_rtnode_list *new_rthash = NULL;
5102 struct _bridge_rtnode_list *old_rthash = NULL;
5103 u_int32_t i;
5104 struct bridge_rtnode *brt;
5105 int error = 0;
5106
5107 BRIDGE_LOCK_ASSERT_HELD(sc);
5108
5109 /*
5110 * Four entries per hash bucket is our ideal load factor
5111 */
5112 if (sc->sc_brtcnt < sc->sc_rthash_size * 4)
5113 goto out;
5114
5115 /*
5116 * Doubling the number of hash buckets may be too simplistic
5117 * especially when facing a spike of new entries
5118 */
5119 new_rthash_size = sc->sc_rthash_size * 2;
5120
5121 sc->sc_flags |= SCF_RESIZING;
5122 BRIDGE_UNLOCK(sc);
5123
5124 new_rthash = _MALLOC(sizeof (*sc->sc_rthash) * new_rthash_size,
5125 M_DEVBUF, M_WAITOK | M_ZERO);
5126
5127 BRIDGE_LOCK(sc);
5128 sc->sc_flags &= ~SCF_RESIZING;
5129
5130 if (new_rthash == NULL) {
5131 error = ENOMEM;
5132 goto out;
5133 }
5134 if ((sc->sc_flags & SCF_DETACHING)) {
5135 error = ENODEV;
5136 goto out;
5137 }
5138 /*
5139 * Fail safe from here on
5140 */
5141 old_rthash = sc->sc_rthash;
5142 sc->sc_rthash = new_rthash;
5143 sc->sc_rthash_size = new_rthash_size;
5144
5145 /*
5146 * Get a new key to force entries to be shuffled around to reduce
5147 * the likelihood they will land in the same buckets
5148 */
5149 sc->sc_rthash_key = RandomULong();
5150
5151 for (i = 0; i < sc->sc_rthash_size; i++)
5152 LIST_INIT(&sc->sc_rthash[i]);
5153
5154 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
5155 LIST_REMOVE(brt, brt_hash);
5156 (void) bridge_rtnode_hash(sc, brt);
5157 }
5158out:
5159 if (error == 0) {
5160#if BRIDGE_DEBUG
5161 if (if_bridge_debug & BR_DBGF_RT_TABLE)
5162 printf("%s: %s new size %u\n", __func__,
5163 sc->sc_ifp->if_xname, sc->sc_rthash_size);
5164#endif /* BRIDGE_DEBUG */
5165 if (old_rthash)
5166 _FREE(old_rthash, M_DEVBUF);
5167 } else {
5168#if BRIDGE_DEBUG
5169 printf("%s: %s failed %d\n", __func__,
5170 sc->sc_ifp->if_xname, error);
5171#endif /* BRIDGE_DEBUG */
5172 if (new_rthash != NULL)
5173 _FREE(new_rthash, M_DEVBUF);
5174 }
5175}
5176
5177/*
5178 * Resize the number of hash buckets based on the load factor
5179 * Currently only grow
5180 * Failing to resize the hash table is not fatal
5181 */
5182static void
5183bridge_rthash_resize(struct bridge_softc *sc)
5184{
5185 BRIDGE_LOCK_ASSERT_HELD(sc);
5186
5187 if ((sc->sc_flags & SCF_DETACHING) || (sc->sc_flags & SCF_RESIZING))
5188 return;
5189
5190 /*
5191 * Four entries per hash bucket is our ideal load factor
5192 */
5193 if (sc->sc_brtcnt < sc->sc_rthash_size * 4)
5194 return;
5195 /*
5196 * Hard limit on the size of the routing hash table
5197 */
5198 if (sc->sc_rthash_size >= bridge_rtable_hash_size_max)
5199 return;
5200
5201 sc->sc_resize_call.bdc_sc = sc;
5202 sc->sc_resize_call.bdc_func = bridge_rthash_delayed_resize;
5203 bridge_schedule_delayed_call(&sc->sc_resize_call);
5204}
5205
6d2010ae
A
5206/*
5207 * bridge_rtable_fini:
5208 *
5209 * Deconstruct the route table for this bridge.
5210 */
5211static void
5212bridge_rtable_fini(struct bridge_softc *sc)
5213{
6d2010ae
A
5214 KASSERT(sc->sc_brtcnt == 0,
5215 ("%s: %d bridge routes referenced", __func__, sc->sc_brtcnt));
39236c6e
A
5216 if (sc->sc_rthash) {
5217 _FREE(sc->sc_rthash, M_DEVBUF);
5218 sc->sc_rthash = NULL;
5219 }
6d2010ae
A
5220}
5221
5222/*
5223 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
5224 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
5225 */
5226#define mix(a, b, c) \
5227do { \
5228 a -= b; a -= c; a ^= (c >> 13); \
5229 b -= c; b -= a; b ^= (a << 8); \
5230 c -= a; c -= b; c ^= (b >> 13); \
5231 a -= b; a -= c; a ^= (c >> 12); \
5232 b -= c; b -= a; b ^= (a << 16); \
5233 c -= a; c -= b; c ^= (b >> 5); \
5234 a -= b; a -= c; a ^= (c >> 3); \
5235 b -= c; b -= a; b ^= (a << 10); \
5236 c -= a; c -= b; c ^= (b >> 15); \
5237} while (/*CONSTCOND*/0)
5238
5239static __inline uint32_t
5240bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
5241{
5242 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key;
5243
5244 b += addr[5] << 8;
5245 b += addr[4];
5246 a += addr[3] << 24;
5247 a += addr[2] << 16;
5248 a += addr[1] << 8;
5249 a += addr[0];
5250
5251 mix(a, b, c);
5252
39236c6e 5253 return (c & BRIDGE_RTHASH_MASK(sc));
6d2010ae
A
5254}
5255
5256#undef mix
5257
5258static int
5259bridge_rtnode_addr_cmp(const uint8_t *a, const uint8_t *b)
5260{
5261 int i, d;
5262
5263 for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
5264 d = ((int)a[i]) - ((int)b[i]);
5265 }
5266
5267 return (d);
5268}
5269
5270/*
5271 * bridge_rtnode_lookup:
5272 *
5273 * Look up a bridge route node for the specified destination. Compare the
5274 * vlan id or if zero then just return the first match.
5275 */
5276static struct bridge_rtnode *
316670eb 5277bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr,
39236c6e 5278 uint16_t vlan)
6d2010ae
A
5279{
5280 struct bridge_rtnode *brt;
5281 uint32_t hash;
5282 int dir;
5283
39236c6e 5284 BRIDGE_LOCK_ASSERT_HELD(sc);
5ba3f43e 5285 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae
A
5286
5287 hash = bridge_rthash(sc, addr);
5288 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
5289 dir = bridge_rtnode_addr_cmp(addr, brt->brt_addr);
5290 if (dir == 0 && (brt->brt_vlan == vlan || vlan == 0))
5291 return (brt);
5292 if (dir > 0)
5293 return (NULL);
5294 }
5295
5296 return (NULL);
5297}
5298
5299/*
39236c6e 5300 * bridge_rtnode_hash:
6d2010ae 5301 *
39236c6e
A
5302 * Insert the specified bridge node into the route hash table.
5303 * This is used when adding a new node or to rehash when resizing
5304 * the hash table
6d2010ae
A
5305 */
5306static int
39236c6e 5307bridge_rtnode_hash(struct bridge_softc *sc, struct bridge_rtnode *brt)
6d2010ae
A
5308{
5309 struct bridge_rtnode *lbrt;
5310 uint32_t hash;
5311 int dir;
5312
39236c6e 5313 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
5314
5315 hash = bridge_rthash(sc, brt->brt_addr);
5316
5317 lbrt = LIST_FIRST(&sc->sc_rthash[hash]);
5318 if (lbrt == NULL) {
5319 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash);
5320 goto out;
5321 }
5322
5323 do {
5324 dir = bridge_rtnode_addr_cmp(brt->brt_addr, lbrt->brt_addr);
39236c6e
A
5325 if (dir == 0 && brt->brt_vlan == lbrt->brt_vlan) {
5326#if BRIDGE_DEBUG
5327 if (if_bridge_debug & BR_DBGF_RT_TABLE)
5328 printf("%s: %s EEXIST "
5329 "%02x:%02x:%02x:%02x:%02x:%02x\n",
5330 __func__, sc->sc_ifp->if_xname,
5331 brt->brt_addr[0], brt->brt_addr[1],
5332 brt->brt_addr[2], brt->brt_addr[3],
5333 brt->brt_addr[4], brt->brt_addr[5]);
5334#endif
6d2010ae 5335 return (EEXIST);
39236c6e 5336 }
6d2010ae
A
5337 if (dir > 0) {
5338 LIST_INSERT_BEFORE(lbrt, brt, brt_hash);
5339 goto out;
5340 }
5341 if (LIST_NEXT(lbrt, brt_hash) == NULL) {
5342 LIST_INSERT_AFTER(lbrt, brt, brt_hash);
5343 goto out;
5344 }
5345 lbrt = LIST_NEXT(lbrt, brt_hash);
5346 } while (lbrt != NULL);
5347
39236c6e
A
5348#if BRIDGE_DEBUG
5349 if (if_bridge_debug & BR_DBGF_RT_TABLE)
5350 printf("%s: %s impossible %02x:%02x:%02x:%02x:%02x:%02x\n",
5351 __func__, sc->sc_ifp->if_xname,
5352 brt->brt_addr[0], brt->brt_addr[1], brt->brt_addr[2],
5353 brt->brt_addr[3], brt->brt_addr[4], brt->brt_addr[5]);
6d2010ae
A
5354#endif
5355
5356out:
39236c6e
A
5357 return (0);
5358}
5359
5360/*
5361 * bridge_rtnode_insert:
5362 *
5363 * Insert the specified bridge node into the route table. We
5364 * assume the entry is not already in the table.
5365 */
5366static int
5367bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
5368{
5369 int error;
5370
5371 error = bridge_rtnode_hash(sc, brt);
5372 if (error != 0)
5373 return (error);
5374
6d2010ae
A
5375 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list);
5376 sc->sc_brtcnt++;
5377
39236c6e
A
5378 bridge_rthash_resize(sc);
5379
6d2010ae
A
5380 return (0);
5381}
5382
5383/*
5384 * bridge_rtnode_destroy:
5385 *
5386 * Destroy a bridge rtnode.
5387 */
5388static void
5389bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
5390{
39236c6e 5391 BRIDGE_LOCK_ASSERT_HELD(sc);
6d2010ae
A
5392
5393 LIST_REMOVE(brt, brt_hash);
5394
5395 LIST_REMOVE(brt, brt_list);
5396 sc->sc_brtcnt--;
5397 brt->brt_dst->bif_addrcnt--;
5398 zfree(bridge_rtnode_pool, brt);
5399}
5400
316670eb 5401#if BRIDGESTP
6d2010ae
A
5402/*
5403 * bridge_rtable_expire:
5404 *
5405 * Set the expiry time for all routes on an interface.
5406 */
5407static void
5408bridge_rtable_expire(struct ifnet *ifp, int age)
5409{
5410 struct bridge_softc *sc = ifp->if_bridge;
5411 struct bridge_rtnode *brt;
5412
5413 BRIDGE_LOCK(sc);
5414
5415 /*
5416 * If the age is zero then flush, otherwise set all the expiry times to
5417 * age for the interface
5418 */
316670eb 5419 if (age == 0) {
6d2010ae 5420 bridge_rtdelete(sc, ifp, IFBF_FLUSHDYN);
316670eb 5421 } else {
39236c6e 5422 unsigned long now;
316670eb 5423
39236c6e
A
5424 now = (unsigned long) net_uptime();
5425
5426 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) {
6d2010ae
A
5427 /* Cap the expiry time to 'age' */
5428 if (brt->brt_ifp == ifp &&
39236c6e 5429 brt->brt_expire > now + age &&
6d2010ae 5430 (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
39236c6e 5431 brt->brt_expire = now + age;
6d2010ae
A
5432 }
5433 }
5434 BRIDGE_UNLOCK(sc);
5435}
5436
5437/*
5438 * bridge_state_change:
5439 *
5440 * Callback from the bridgestp code when a port changes states.
5441 */
5442static void
5443bridge_state_change(struct ifnet *ifp, int state)
5444{
5445 struct bridge_softc *sc = ifp->if_bridge;
5446 static const char *stpstates[] = {
5447 "disabled",
5448 "listening",
5449 "learning",
5450 "forwarding",
5451 "blocking",
5452 "discarding"
5453 };
5454
5455 if (log_stp)
39236c6e
A
5456 log(LOG_NOTICE, "%s: state changed to %s on %s\n",
5457 sc->sc_ifp->if_xname,
5458 stpstates[state], ifp->if_xname);
6d2010ae 5459}
316670eb 5460#endif /* BRIDGESTP */
6d2010ae
A
5461
5462#ifdef PFIL_HOOKS
5463/*
5464 * Send bridge packets through pfil if they are one of the types pfil can deal
5465 * with, or if they are ARP or REVARP. (pfil will pass ARP and REVARP without
5466 * question.) If *bifp or *ifp are NULL then packet filtering is skipped for
5467 * that interface.
5468 */
5469static int
5470bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
5471{
5472 int snap, error, i, hlen;
5473 struct ether_header *eh1, eh2;
5474 struct ip_fw_args args;
5475 struct ip *ip;
5476 struct llc llc1;
5477 u_int16_t ether_type;
5478
5479 snap = 0;
5480 error = -1; /* Default error if not error == 0 */
5481
5482#if 0
5483 /* we may return with the IP fields swapped, ensure its not shared */
5484 KASSERT(M_WRITABLE(*mp), ("%s: modifying a shared mbuf", __func__));
5485#endif
5486
5487 if (pfil_bridge == 0 && pfil_member == 0 && pfil_ipfw == 0)
5488 return (0); /* filtering is disabled */
5489
5490 i = min((*mp)->m_pkthdr.len, max_protohdr);
5491 if ((*mp)->m_len < i) {
316670eb
A
5492 *mp = m_pullup(*mp, i);
5493 if (*mp == NULL) {
5494 printf("%s: m_pullup failed\n", __func__);
5495 return (-1);
5496 }
6d2010ae
A
5497 }
5498
5499 eh1 = mtod(*mp, struct ether_header *);
5500 ether_type = ntohs(eh1->ether_type);
5501
5502 /*
5503 * Check for SNAP/LLC.
5504 */
5505 if (ether_type < ETHERMTU) {
5506 struct llc *llc2 = (struct llc *)(eh1 + 1);
5507
5508 if ((*mp)->m_len >= ETHER_HDR_LEN + 8 &&
5509 llc2->llc_dsap == LLC_SNAP_LSAP &&
5510 llc2->llc_ssap == LLC_SNAP_LSAP &&
5511 llc2->llc_control == LLC_UI) {
5512 ether_type = htons(llc2->llc_un.type_snap.ether_type);
5513 snap = 1;
5514 }
5515 }
5516
5517 /*
5518 * If we're trying to filter bridge traffic, don't look at anything
5519 * other than IP and ARP traffic. If the filter doesn't understand
5520 * IPv6, don't allow IPv6 through the bridge either. This is lame
5521 * since if we really wanted, say, an AppleTalk filter, we are hosed,
5522 * but of course we don't have an AppleTalk filter to begin with.
5523 * (Note that since pfil doesn't understand ARP it will pass *ALL*
5524 * ARP traffic.)
5525 */
5526 switch (ether_type) {
5527 case ETHERTYPE_ARP:
5528 case ETHERTYPE_REVARP:
5529 if (pfil_ipfw_arp == 0)
5530 return (0); /* Automatically pass */
5531 break;
5532
5533 case ETHERTYPE_IP:
39236c6e 5534#if INET6
6d2010ae
A
5535 case ETHERTYPE_IPV6:
5536#endif /* INET6 */
5537 break;
5538 default:
5539 /*
5540 * Check to see if the user wants to pass non-ip
5541 * packets, these will not be checked by pfil(9) and
5542 * passed unconditionally so the default is to drop.
5543 */
5544 if (pfil_onlyip)
5545 goto bad;
5546 }
5547
5548 /* Strip off the Ethernet header and keep a copy. */
316670eb 5549 m_copydata(*mp, 0, ETHER_HDR_LEN, (caddr_t)&eh2);
6d2010ae
A
5550 m_adj(*mp, ETHER_HDR_LEN);
5551
5552 /* Strip off snap header, if present */
5553 if (snap) {
316670eb
A
5554 m_copydata(*mp, 0, sizeof (struct llc), (caddr_t)&llc1);
5555 m_adj(*mp, sizeof (struct llc));
6d2010ae
A
5556 }
5557
5558 /*
5559 * Check the IP header for alignment and errors
5560 */
5561 if (dir == PFIL_IN) {
5562 switch (ether_type) {
5563 case ETHERTYPE_IP:
5564 error = bridge_ip_checkbasic(mp);
5565 break;
39236c6e 5566#if INET6
6d2010ae
A
5567 case ETHERTYPE_IPV6:
5568 error = bridge_ip6_checkbasic(mp);
5569 break;
5570#endif /* INET6 */
5571 default:
5572 error = 0;
5573 }
5574 if (error)
5575 goto bad;
5576 }
5577
5578 if (IPFW_LOADED && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
5579 error = -1;
5580 args.rule = ip_dn_claim_rule(*mp);
5581 if (args.rule != NULL && fw_one_pass)
5582 goto ipfwpass; /* packet already partially processed */
5583
5584 args.m = *mp;
5585 args.oif = ifp;
5586 args.next_hop = NULL;
5587 args.eh = &eh2;
5588 args.inp = NULL; /* used by ipfw uid/gid/jail rules */
5589 i = ip_fw_chk_ptr(&args);
5590 *mp = args.m;
5591
5592 if (*mp == NULL)
5593 return (error);
5594
5595 if (DUMMYNET_LOADED && (i == IP_FW_DUMMYNET)) {
5596
5597 /* put the Ethernet header back on */
3e170ce0 5598 M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT, 0);
6d2010ae
A
5599 if (*mp == NULL)
5600 return (error);
5601 bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
5602
5603 /*
5604 * Pass the pkt to dummynet, which consumes it. The
5605 * packet will return to us via bridge_dummynet().
5606 */
5607 args.oif = ifp;
316670eb 5608 ip_dn_io_ptr(mp, DN_TO_IFB_FWD, &args, DN_CLIENT_IPFW);
6d2010ae
A
5609 return (error);
5610 }
5611
5612 if (i != IP_FW_PASS) /* drop */
5613 goto bad;
5614 }
5615
5616ipfwpass:
5617 error = 0;
5618
5619 /*
5620 * Run the packet through pfil
5621 */
5622 switch (ether_type) {
5623 case ETHERTYPE_IP:
5624 /*
5625 * before calling the firewall, swap fields the same as
5626 * IP does. here we assume the header is contiguous
5627 */
5628 ip = mtod(*mp, struct ip *);
5629
5630 ip->ip_len = ntohs(ip->ip_len);
5631 ip->ip_off = ntohs(ip->ip_off);
5632
5633 /*
5634 * Run pfil on the member interface and the bridge, both can
5635 * be skipped by clearing pfil_member or pfil_bridge.
5636 *
5637 * Keep the order:
5638 * in_if -> bridge_if -> out_if
5639 */
5640 if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
5641 error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
316670eb 5642 dir, NULL);
6d2010ae
A
5643
5644 if (*mp == NULL || error != 0) /* filter may consume */
5645 break;
5646
5647 if (pfil_member && ifp != NULL)
5648 error = pfil_run_hooks(&inet_pfil_hook, mp, ifp,
316670eb 5649 dir, NULL);
6d2010ae
A
5650
5651 if (*mp == NULL || error != 0) /* filter may consume */
5652 break;
5653
5654 if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
5655 error = pfil_run_hooks(&inet_pfil_hook, mp, bifp,
316670eb 5656 dir, NULL);
6d2010ae
A
5657
5658 if (*mp == NULL || error != 0) /* filter may consume */
5659 break;
5660
5661 /* check if we need to fragment the packet */
5662 if (pfil_member && ifp != NULL && dir == PFIL_OUT) {
5663 i = (*mp)->m_pkthdr.len;
5664 if (i > ifp->if_mtu) {
5665 error = bridge_fragment(ifp, *mp, &eh2, snap,
316670eb 5666 &llc1);
6d2010ae
A
5667 return (error);
5668 }
5669 }
5670
5671 /* Recalculate the ip checksum and restore byte ordering */
5672 ip = mtod(*mp, struct ip *);
5673 hlen = ip->ip_hl << 2;
316670eb 5674 if (hlen < sizeof (struct ip))
6d2010ae
A
5675 goto bad;
5676 if (hlen > (*mp)->m_len) {
5677 if ((*mp = m_pullup(*mp, hlen)) == 0)
5678 goto bad;
5679 ip = mtod(*mp, struct ip *);
5680 if (ip == NULL)
5681 goto bad;
5682 }
5683 ip->ip_len = htons(ip->ip_len);
5684 ip->ip_off = htons(ip->ip_off);
5685 ip->ip_sum = 0;
316670eb 5686 if (hlen == sizeof (struct ip))
6d2010ae
A
5687 ip->ip_sum = in_cksum_hdr(ip);
5688 else
5689 ip->ip_sum = in_cksum(*mp, hlen);
5690
5691 break;
39236c6e 5692#if INET6
6d2010ae
A
5693 case ETHERTYPE_IPV6:
5694 if (pfil_bridge && dir == PFIL_OUT && bifp != NULL)
5695 error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
316670eb 5696 dir, NULL);
6d2010ae
A
5697
5698 if (*mp == NULL || error != 0) /* filter may consume */
5699 break;
5700
5701 if (pfil_member && ifp != NULL)
5702 error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp,
316670eb 5703 dir, NULL);
6d2010ae
A
5704
5705 if (*mp == NULL || error != 0) /* filter may consume */
5706 break;
5707
5708 if (pfil_bridge && dir == PFIL_IN && bifp != NULL)
5709 error = pfil_run_hooks(&inet6_pfil_hook, mp, bifp,
316670eb 5710 dir, NULL);
6d2010ae
A
5711 break;
5712#endif
5713 default:
5714 error = 0;
5715 break;
5716 }
5717
5718 if (*mp == NULL)
5719 return (error);
5720 if (error != 0)
5721 goto bad;
5722
5723 error = -1;
5724
5725 /*
5726 * Finally, put everything back the way it was and return
5727 */
5728 if (snap) {
3e170ce0 5729 M_PREPEND(*mp, sizeof (struct llc), M_DONTWAIT, 0);
6d2010ae
A
5730 if (*mp == NULL)
5731 return (error);
316670eb 5732 bcopy(&llc1, mtod(*mp, caddr_t), sizeof (struct llc));
6d2010ae
A
5733 }
5734
3e170ce0 5735 M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT, 0);
6d2010ae
A
5736 if (*mp == NULL)
5737 return (error);
5738 bcopy(&eh2, mtod(*mp, caddr_t), ETHER_HDR_LEN);
5739
5740 return (0);
5741
5742bad:
5743 m_freem(*mp);
5744 *mp = NULL;
5745 return (error);
5746}
5747
6d2010ae
A
5748/*
5749 * Perform basic checks on header size since
5750 * pfil assumes ip_input has already processed
5751 * it for it. Cut-and-pasted from ip_input.c.
5752 * Given how simple the IPv6 version is,
5753 * does the IPv4 version really need to be
5754 * this complicated?
5755 *
5756 * XXX Should we update ipstat here, or not?
5757 * XXX Right now we update ipstat but not
5758 * XXX csum_counter.
5759 */
5760static int
5761bridge_ip_checkbasic(struct mbuf **mp)
5762{
5763 struct mbuf *m = *mp;
5764 struct ip *ip;
5765 int len, hlen;
5766 u_short sum;
5767
5768 if (*mp == NULL)
5769 return (-1);
5770
5771 if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
316670eb
A
5772 /* max_linkhdr is already rounded up to nearest 4-byte */
5773 if ((m = m_copyup(m, sizeof (struct ip),
5774 max_linkhdr)) == NULL) {
6d2010ae
A
5775 /* XXXJRT new stat, please */
5776 ipstat.ips_toosmall++;
5777 goto bad;
5778 }
5779 } else if (__predict_false(m->m_len < sizeof (struct ip))) {
5780 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
5781 ipstat.ips_toosmall++;
5782 goto bad;
5783 }
5784 }
5785 ip = mtod(m, struct ip *);
5786 if (ip == NULL) goto bad;
5787
5788 if (ip->ip_v != IPVERSION) {
5789 ipstat.ips_badvers++;
5790 goto bad;
5791 }
5792 hlen = ip->ip_hl << 2;
316670eb 5793 if (hlen < sizeof (struct ip)) { /* minimum header length */
6d2010ae
A
5794 ipstat.ips_badhlen++;
5795 goto bad;
5796 }
5797 if (hlen > m->m_len) {
5798 if ((m = m_pullup(m, hlen)) == 0) {
5799 ipstat.ips_badhlen++;
5800 goto bad;
5801 }
5802 ip = mtod(m, struct ip *);
5803 if (ip == NULL) goto bad;
5804 }
5805
5806 if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
5807 sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
5808 } else {
316670eb 5809 if (hlen == sizeof (struct ip)) {
6d2010ae
A
5810 sum = in_cksum_hdr(ip);
5811 } else {
5812 sum = in_cksum(m, hlen);
5813 }
5814 }
5815 if (sum) {
5816 ipstat.ips_badsum++;
5817 goto bad;
5818 }
5819
5820 /* Retrieve the packet length. */
5821 len = ntohs(ip->ip_len);
5822
5823 /*
5824 * Check for additional length bogosity
5825 */
5826 if (len < hlen) {
5827 ipstat.ips_badlen++;
5828 goto bad;
5829 }
5830
5831 /*
5832 * Check that the amount of data in the buffers
5833 * is as at least much as the IP header would have us expect.
5834 * Drop packet if shorter than we expect.
5835 */
5836 if (m->m_pkthdr.len < len) {
5837 ipstat.ips_tooshort++;
5838 goto bad;
5839 }
5840
5841 /* Checks out, proceed */
5842 *mp = m;
5843 return (0);
5844
5845bad:
5846 *mp = m;
5847 return (-1);
5848}
5849
39236c6e 5850#if INET6
6d2010ae
A
5851/*
5852 * Same as above, but for IPv6.
5853 * Cut-and-pasted from ip6_input.c.
5854 * XXX Should we update ip6stat, or not?
5855 */
5856static int
5857bridge_ip6_checkbasic(struct mbuf **mp)
5858{
5859 struct mbuf *m = *mp;
5860 struct ip6_hdr *ip6;
5861
5862 /*
5863 * If the IPv6 header is not aligned, slurp it up into a new
5864 * mbuf with space for link headers, in the event we forward
5865 * it. Otherwise, if it is aligned, make sure the entire base
5866 * IPv6 header is in the first mbuf of the chain.
5867 */
5868 if (IP6_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
5869 struct ifnet *inifp = m->m_pkthdr.rcvif;
316670eb
A
5870 /* max_linkhdr is already rounded up to nearest 4-byte */
5871 if ((m = m_copyup(m, sizeof (struct ip6_hdr),
5872 max_linkhdr)) == NULL) {
6d2010ae
A
5873 /* XXXJRT new stat, please */
5874 ip6stat.ip6s_toosmall++;
5875 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
5876 goto bad;
5877 }
316670eb 5878 } else if (__predict_false(m->m_len < sizeof (struct ip6_hdr))) {
6d2010ae 5879 struct ifnet *inifp = m->m_pkthdr.rcvif;
316670eb 5880 if ((m = m_pullup(m, sizeof (struct ip6_hdr))) == NULL) {
6d2010ae
A
5881 ip6stat.ip6s_toosmall++;
5882 in6_ifstat_inc(inifp, ifs6_in_hdrerr);
5883 goto bad;
5884 }
5885 }
5886
5887 ip6 = mtod(m, struct ip6_hdr *);
5888
5889 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
5890 ip6stat.ip6s_badvers++;
5891 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
5892 goto bad;
5893 }
5894
5895 /* Checks out, proceed */
5896 *mp = m;
5897 return (0);
5898
5899bad:
5900 *mp = m;
5901 return (-1);
5902}
5903#endif /* INET6 */
5904
5905/*
5906 * bridge_fragment:
5907 *
5908 * Return a fragmented mbuf chain.
5909 */
5910static int
5911bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
39236c6e 5912 int snap, struct llc *llc)
6d2010ae
A
5913{
5914 struct mbuf *m0;
5915 struct ip *ip;
5916 int error = -1;
5917
316670eb
A
5918 if (m->m_len < sizeof (struct ip) &&
5919 (m = m_pullup(m, sizeof (struct ip))) == NULL)
6d2010ae
A
5920 goto out;
5921 ip = mtod(m, struct ip *);
5922
5923 error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist,
316670eb 5924 CSUM_DELAY_IP);
6d2010ae
A
5925 if (error)
5926 goto out;
5927
5928 /* walk the chain and re-add the Ethernet header */
5929 for (m0 = m; m0; m0 = m0->m_nextpkt) {
5930 if (error == 0) {
5931 if (snap) {
3e170ce0 5932 M_PREPEND(m0, sizeof (struct llc), M_DONTWAIT, 0);
6d2010ae
A
5933 if (m0 == NULL) {
5934 error = ENOBUFS;
5935 continue;
5936 }
5937 bcopy(llc, mtod(m0, caddr_t),
316670eb 5938 sizeof (struct llc));
6d2010ae 5939 }
3e170ce0 5940 M_PREPEND(m0, ETHER_HDR_LEN, M_DONTWAIT, 0);
6d2010ae
A
5941 if (m0 == NULL) {
5942 error = ENOBUFS;
5943 continue;
5944 }
5945 bcopy(eh, mtod(m0, caddr_t), ETHER_HDR_LEN);
316670eb 5946 } else {
6d2010ae 5947 m_freem(m);
316670eb 5948 }
6d2010ae
A
5949 }
5950
5951 if (error == 0)
5952 ipstat.ips_fragmented++;
5953
5954 return (error);
5955
5956out:
5957 if (m != NULL)
5958 m_freem(m);
5959 return (error);
5960}
5961#endif /* PFIL_HOOKS */
5962
39236c6e
A
5963/*
5964 * bridge_set_bpf_tap:
5965 *
5966 * Sets ups the BPF callbacks.
5967 */
6d2010ae
A
5968static errno_t
5969bridge_set_bpf_tap(ifnet_t ifp, bpf_tap_mode mode, bpf_packet_func bpf_callback)
5970{
5971 struct bridge_softc *sc = (struct bridge_softc *)ifnet_softc(ifp);
316670eb 5972
6d2010ae
A
5973 /* TBD locking */
5974 if (sc == NULL || (sc->sc_flags & SCF_DETACHING)) {
316670eb 5975 return (ENODEV);
6d2010ae 5976 }
5ba3f43e 5977 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae
A
5978 switch (mode) {
5979 case BPF_TAP_DISABLE:
5980 sc->sc_bpf_input = sc->sc_bpf_output = NULL;
5981 break;
316670eb 5982
6d2010ae
A
5983 case BPF_TAP_INPUT:
5984 sc->sc_bpf_input = bpf_callback;
5985 break;
316670eb 5986
6d2010ae
A
5987 case BPF_TAP_OUTPUT:
5988 sc->sc_bpf_output = bpf_callback;
5989 break;
316670eb 5990
6d2010ae
A
5991 case BPF_TAP_INPUT_OUTPUT:
5992 sc->sc_bpf_input = sc->sc_bpf_output = bpf_callback;
5993 break;
316670eb 5994
6d2010ae
A
5995 default:
5996 break;
5997 }
316670eb
A
5998
5999 return (0);
6d2010ae
A
6000}
6001
39236c6e
A
6002/*
6003 * bridge_detach:
6004 *
6005 * Callback when interface has been detached.
6006 */
6d2010ae
A
6007static void
6008bridge_detach(ifnet_t ifp)
6009{
6010 struct bridge_softc *sc = (struct bridge_softc *)ifnet_softc(ifp);
316670eb
A
6011
6012#if BRIDGESTP
6d2010ae 6013 bstp_detach(&sc->sc_stp);
316670eb 6014#endif /* BRIDGESTP */
6d2010ae 6015
5ba3f43e
A
6016 if (bridge_in_bsd_mode(sc)) {
6017 /* Tear down the routing table. */
6018 bridge_rtable_fini(sc);
6019 }
316670eb 6020
39236c6e 6021 lck_mtx_lock(&bridge_list_mtx);
6d2010ae 6022 LIST_REMOVE(sc, sc_list);
39236c6e 6023 lck_mtx_unlock(&bridge_list_mtx);
316670eb 6024
6d2010ae 6025 ifnet_release(ifp);
316670eb 6026
39236c6e 6027 lck_mtx_destroy(&sc->sc_mtx, bridge_lock_grp);
316670eb 6028
6d2010ae 6029 _FREE(sc, M_DEVBUF);
6d2010ae
A
6030}
6031
39236c6e
A
6032/*
6033 * bridge_bpf_input:
6034 *
6035 * Invoke the input BPF callback if enabled
6036 */
316670eb
A
6037__private_extern__ errno_t
6038bridge_bpf_input(ifnet_t ifp, struct mbuf *m)
6d2010ae
A
6039{
6040 struct bridge_softc *sc = (struct bridge_softc *)ifnet_softc(ifp);
316670eb 6041
5ba3f43e 6042 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae 6043 if (sc->sc_bpf_input) {
316670eb 6044 if (mbuf_pkthdr_rcvif(m) != ifp) {
39236c6e
A
6045 printf("%s: rcvif: 0x%llx != ifp 0x%llx\n", __func__,
6046 (uint64_t)VM_KERNEL_ADDRPERM(mbuf_pkthdr_rcvif(m)),
6047 (uint64_t)VM_KERNEL_ADDRPERM(ifp));
316670eb 6048 }
6d2010ae
A
6049 (*sc->sc_bpf_input)(ifp, m);
6050 }
316670eb 6051 return (0);
6d2010ae
A
6052}
6053
39236c6e
A
6054/*
6055 * bridge_bpf_output:
6056 *
6057 * Invoke the output BPF callback if enabled
6058 */
316670eb
A
6059__private_extern__ errno_t
6060bridge_bpf_output(ifnet_t ifp, struct mbuf *m)
6d2010ae
A
6061{
6062 struct bridge_softc *sc = (struct bridge_softc *)ifnet_softc(ifp);
316670eb 6063
5ba3f43e 6064 ASSERT(bridge_in_bsd_mode(sc));
6d2010ae
A
6065 if (sc->sc_bpf_output) {
6066 (*sc->sc_bpf_output)(ifp, m);
6067 }
316670eb 6068 return (0);
6d2010ae 6069}
39236c6e
A
6070
6071/*
6072 * bridge_link_event:
6073 *
6074 * Report a data link event on an interface
6075 */
6076static void
6077bridge_link_event(struct ifnet *ifp, u_int32_t event_code)
6078{
6079 struct {
6080 struct kern_event_msg header;
6081 u_int32_t unit;
6082 char if_name[IFNAMSIZ];
6083 } event;
6084
6085#if BRIDGE_DEBUG
6086 if (if_bridge_debug & BR_DBGF_LIFECYCLE)
6087 printf("%s: %s event_code %u - %s\n", __func__, ifp->if_xname,
6088 event_code, dlil_kev_dl_code_str(event_code));
6089#endif /* BRIDGE_DEBUG */
6090
6091 bzero(&event, sizeof (event));
6092 event.header.total_size = sizeof (event);
6093 event.header.vendor_code = KEV_VENDOR_APPLE;
6094 event.header.kev_class = KEV_NETWORK_CLASS;
6095 event.header.kev_subclass = KEV_DL_SUBCLASS;
6096 event.header.event_code = event_code;
6097 event.header.event_data[0] = ifnet_family(ifp);
6098 event.unit = (u_int32_t)ifnet_unit(ifp);
fe8ab488 6099 strlcpy(event.if_name, ifnet_name(ifp), IFNAMSIZ);
39236c6e
A
6100 ifnet_event(ifp, &event.header);
6101}
fe8ab488
A
6102
6103#define BRIDGE_HF_DROP(reason, func, line) { \
6104 bridge_hostfilter_stats.reason++; \
6105 if (if_bridge_debug & BR_DBGF_HOSTFILTER) \
6106 printf("%s.%d" #reason, func, line); \
6107 error = EINVAL; \
6108}
6109
6110/*
6111 * Make sure this is a DHCP or Bootp request that match the host filter
6112 */
6113static int
6114bridge_dhcp_filter(struct bridge_iflist *bif, struct mbuf *m, size_t offset)
6115{
6116 int error = EINVAL;
6117 struct dhcp dhcp;
6118
6119 /*
6120 * Note: We use the dhcp structure because bootp structure definition
6121 * is larger and some vendors do not pad the request
6122 */
6123 error = mbuf_copydata(m, offset, sizeof(struct dhcp), &dhcp);
6124 if (error != 0) {
6125 BRIDGE_HF_DROP(brhf_dhcp_too_small, __func__, __LINE__);
6126 goto done;
6127 }
6128 if (dhcp.dp_op != BOOTREQUEST) {
6129 BRIDGE_HF_DROP(brhf_dhcp_bad_op, __func__, __LINE__);
6130 goto done;
6131 }
6132 /*
6133 * The hardware address must be an exact match
6134 */
6135 if (dhcp.dp_htype != ARPHRD_ETHER) {
6136 BRIDGE_HF_DROP(brhf_dhcp_bad_htype, __func__, __LINE__);
6137 goto done;
6138 }
6139 if (dhcp.dp_hlen != ETHER_ADDR_LEN) {
6140 BRIDGE_HF_DROP(brhf_dhcp_bad_hlen, __func__, __LINE__);
6141 goto done;
6142 }
6143 if (bcmp(dhcp.dp_chaddr, bif->bif_hf_hwsrc,
6144 ETHER_ADDR_LEN) != 0) {
6145 BRIDGE_HF_DROP(brhf_dhcp_bad_chaddr, __func__, __LINE__);
6146 goto done;
6147 }
6148 /*
6149 * Client address must match the host address or be not specified
6150 */
6151 if (dhcp.dp_ciaddr.s_addr != bif->bif_hf_ipsrc.s_addr &&
6152 dhcp.dp_ciaddr.s_addr != INADDR_ANY) {
6153 BRIDGE_HF_DROP(brhf_dhcp_bad_ciaddr, __func__, __LINE__);
6154 goto done;
6155 }
6156 error = 0;
6157done:
6158 return (error);
6159}
6160
6161static int
6162bridge_host_filter(struct bridge_iflist *bif, struct mbuf *m)
6163{
6164 int error = EINVAL;
6165 struct ether_header *eh;
6166 static struct in_addr inaddr_any = { .s_addr = INADDR_ANY };
6167
6168 /*
6169 * Check the Ethernet header is large enough
6170 */
6171 if (mbuf_pkthdr_len(m) < sizeof(struct ether_header)) {
6172 BRIDGE_HF_DROP(brhf_ether_too_small, __func__, __LINE__);
6173 goto done;
6174 }
6175 if (mbuf_len(m) < sizeof(struct ether_header) &&
6176 mbuf_pullup(&m, sizeof(struct ether_header)) != 0) {
6177 BRIDGE_HF_DROP(brhf_ether_pullup_failed, __func__, __LINE__);
6178 goto done;
6179 }
6180 eh = mtod(m, struct ether_header *);
6181
6182 /*
6183 * Restrict the source hardware address
6184 */
6185 if ((bif->bif_flags & BIFF_HF_HWSRC) == 0 ||
6186 bcmp(eh->ether_shost, bif->bif_hf_hwsrc,
6187 ETHER_ADDR_LEN) != 0) {
6188 BRIDGE_HF_DROP(brhf_bad_ether_srchw_addr, __func__, __LINE__);
6189 goto done;
6190 }
6191
6192 /*
6193 * Restrict Ethernet protocols to ARP and IP
6194 */
6195 if (eh->ether_type == htons(ETHERTYPE_ARP)) {
6196 struct ether_arp *ea;
6197 size_t minlen = sizeof(struct ether_header) +
6198 sizeof(struct ether_arp);
6199
6200 /*
6201 * Make the Ethernet and ARP headers contiguous
6202 */
6203 if (mbuf_pkthdr_len(m) < minlen) {
6204 BRIDGE_HF_DROP(brhf_arp_too_small, __func__, __LINE__);
6205 goto done;
6206 }
6207 if (mbuf_len(m) < minlen && mbuf_pullup(&m, minlen) != 0) {
6208 BRIDGE_HF_DROP(brhf_arp_pullup_failed,
6209 __func__, __LINE__);
6210 goto done;
6211 }
6212 /*
6213 * Verify this is an ethernet/ip arp
6214 */
6215 eh = mtod(m, struct ether_header *);
6216 ea = (struct ether_arp *)(eh + 1);
6217 if (ea->arp_hrd != htons(ARPHRD_ETHER)) {
6218 BRIDGE_HF_DROP(brhf_arp_bad_hw_type,
6219 __func__, __LINE__);
6220 goto done;
6221 }
6222 if (ea->arp_pro != htons(ETHERTYPE_IP)) {
6223 BRIDGE_HF_DROP(brhf_arp_bad_pro_type,
6224 __func__, __LINE__);
6225 goto done;
6226 }
6227 /*
6228 * Verify the address lengths are correct
6229 */
6230 if (ea->arp_hln != ETHER_ADDR_LEN) {
6231 BRIDGE_HF_DROP(brhf_arp_bad_hw_len, __func__, __LINE__);
6232 goto done;
6233 }
6234 if (ea->arp_pln != sizeof(struct in_addr)) {
6235 BRIDGE_HF_DROP(brhf_arp_bad_pro_len,
6236 __func__, __LINE__);
6237 goto done;
6238 }
6239
6240 /*
6241 * Allow only ARP request or ARP reply
6242 */
6243 if (ea->arp_op != htons(ARPOP_REQUEST) &&
6244 ea->arp_op != htons(ARPOP_REPLY)) {
6245 BRIDGE_HF_DROP(brhf_arp_bad_op, __func__, __LINE__);
6246 goto done;
6247 }
6248 /*
6249 * Verify source hardware address matches
6250 */
6251 if (bcmp(ea->arp_sha, bif->bif_hf_hwsrc,
6252 ETHER_ADDR_LEN) != 0) {
6253 BRIDGE_HF_DROP(brhf_arp_bad_sha, __func__, __LINE__);
6254 goto done;
6255 }
6256 /*
6257 * Verify source protocol address:
6258 * May be null for an ARP probe
6259 */
6260 if (bcmp(ea->arp_spa, &bif->bif_hf_ipsrc.s_addr,
6261 sizeof(struct in_addr)) != 0 &&
6262 bcmp(ea->arp_spa, &inaddr_any,
6263 sizeof(struct in_addr)) != 0) {
6264 BRIDGE_HF_DROP(brhf_arp_bad_spa, __func__, __LINE__);
6265 goto done;
6266 }
6267 /*
6268 *
6269 */
6270 bridge_hostfilter_stats.brhf_arp_ok += 1;
6271 error = 0;
6272 } else if (eh->ether_type == htons(ETHERTYPE_IP)) {
6273 size_t minlen = sizeof(struct ether_header) + sizeof(struct ip);
6274 struct ip iphdr;
6275 size_t offset;
6276
6277 /*
6278 * Make the Ethernet and IP headers contiguous
6279 */
6280 if (mbuf_pkthdr_len(m) < minlen) {
6281 BRIDGE_HF_DROP(brhf_ip_too_small, __func__, __LINE__);
6282 goto done;
6283 }
6284 offset = sizeof(struct ether_header);
6285 error = mbuf_copydata(m, offset, sizeof(struct ip), &iphdr);
6286 if (error != 0) {
6287 BRIDGE_HF_DROP(brhf_ip_too_small, __func__, __LINE__);
6288 goto done;
6289 }
6290 /*
6291 * Verify the source IP address
6292 */
6293 if (iphdr.ip_p == IPPROTO_UDP) {
6294 struct udphdr udp;
6295
6296 minlen += sizeof(struct udphdr);
6297 if (mbuf_pkthdr_len(m) < minlen) {
6298 BRIDGE_HF_DROP(brhf_ip_too_small,
6299 __func__, __LINE__);
6300 goto done;
6301 }
6302
6303 /*
6304 * Allow all zero addresses for DHCP requests
6305 */
6306 if (iphdr.ip_src.s_addr != bif->bif_hf_ipsrc.s_addr &&
6307 iphdr.ip_src.s_addr != INADDR_ANY) {
6308 BRIDGE_HF_DROP(brhf_ip_bad_srcaddr,
6309 __func__, __LINE__);
6310 goto done;
6311 }
6312 offset = sizeof(struct ether_header) +
6313 (IP_VHL_HL(iphdr.ip_vhl) << 2);
6314 error = mbuf_copydata(m, offset,
6315 sizeof(struct udphdr), &udp);
6316 if (error != 0) {
6317 BRIDGE_HF_DROP(brhf_ip_too_small,
6318 __func__, __LINE__);
6319 goto done;
6320 }
6321 /*
6322 * Either it's a Bootp/DHCP packet that we like or
6323 * it's a UDP packet from the host IP as source address
6324 */
6325 if (udp.uh_sport == htons(IPPORT_BOOTPC) &&
6326 udp.uh_dport == htons(IPPORT_BOOTPS)) {
6327 minlen += sizeof(struct dhcp);
6328 if (mbuf_pkthdr_len(m) < minlen) {
6329 BRIDGE_HF_DROP(brhf_ip_too_small,
6330 __func__, __LINE__);
6331 goto done;
6332 }
6333 offset += sizeof(struct udphdr);
6334 error = bridge_dhcp_filter(bif, m, offset);
6335 if (error != 0)
6336 goto done;
6337 } else if (iphdr.ip_src.s_addr == INADDR_ANY) {
6338 BRIDGE_HF_DROP(brhf_ip_bad_srcaddr,
6339 __func__, __LINE__);
6340 goto done;
6341 }
6342 } else if (iphdr.ip_src.s_addr != bif->bif_hf_ipsrc.s_addr ||
6343 bif->bif_hf_ipsrc.s_addr == INADDR_ANY) {
6344
6345 BRIDGE_HF_DROP(brhf_ip_bad_srcaddr, __func__, __LINE__);
6346 goto done;
6347 }
6348 /*
6349 * Allow only boring IP protocols
6350 */
6351 if (iphdr.ip_p != IPPROTO_TCP &&
6352 iphdr.ip_p != IPPROTO_UDP &&
6353 iphdr.ip_p != IPPROTO_ICMP &&
6354 iphdr.ip_p != IPPROTO_ESP &&
6355 iphdr.ip_p != IPPROTO_AH &&
6356 iphdr.ip_p != IPPROTO_GRE) {
6357 BRIDGE_HF_DROP(brhf_ip_bad_proto, __func__, __LINE__);
6358 goto done;
6359 }
6360 bridge_hostfilter_stats.brhf_ip_ok += 1;
6361 error = 0;
6362 } else {
6363 BRIDGE_HF_DROP(brhf_bad_ether_type, __func__, __LINE__);
6364 goto done;
6365 }
6366done:
6367 if (error != 0) {
6368 if (if_bridge_debug & BR_DBGF_HOSTFILTER) {
6369 if (m) {
6370 printf_mbuf_data(m, 0,
6371 sizeof(struct ether_header) +
6372 sizeof(struct ip));
6373 }
6374 printf("\n");
6375 }
6376
6377 if (m != NULL)
6378 m_freem(m);
6379 }
6380 return (error);
6381}
5ba3f43e
A
6382
6383