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