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