1 /* $NetBSD: if_bridge.c,v 1.31 2005/06/01 19:45:34 jdc Exp $ */
3 * Copyright (c) 2004-2010 Apple Inc. All rights reserved.
5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
25 * limitations under the License.
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 * Copyright 2001 Wasabi Systems, Inc.
32 * All rights reserved.
34 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
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
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.
66 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
67 * All rights reserved.
69 * Redistribution and use in source and binary forms, with or without
70 * modification, are permitted provided that the following conditions
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.
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.
90 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
94 * Network interface bridge support.
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).
104 #include <sys/cdefs.h>
105 //__FBSDID("$FreeBSD$");
107 //#include "opt_inet.h"
108 //#include "opt_inet6.h"
109 //#include "opt_carp.h"
111 #define BRIDGE_DEBUG 1
113 #define BRIDGE_DEBUG 0
114 #endif /* BRIDGE_DEBUG */
116 #include <sys/param.h>
117 #include <sys/mbuf.h>
118 #include <sys/malloc.h>
119 #include <sys/protosw.h>
120 #include <sys/systm.h>
121 #include <sys/time.h>
122 #include <sys/socket.h> /* for net/if.h */
123 #include <sys/sockio.h>
124 //#include <sys/ctype.h> /* string functions */
125 #include <sys/kernel.h>
126 #include <sys/random.h>
127 #include <sys/syslog.h>
128 #include <sys/sysctl.h>
129 //#include <vm/uma.h>
130 //#include <sys/module.h>
131 //#include <sys/priv.h>
132 #include <sys/proc.h>
133 #include <sys/lock.h>
134 //#include <sys/mutex.h>
135 #include <sys/mcache.h>
137 #include <sys/kauth.h>
139 #include <libkern/libkern.h>
141 #include <kern/zalloc.h>
147 //#include <net/if_clone.h>
148 #include <net/if_dl.h>
149 #include <net/if_types.h>
150 #include <net/if_var.h>
151 //#include <net/pfil.h>
153 #include <netinet/in.h> /* for struct arpcom */
154 #include <netinet/in_systm.h>
155 #include <netinet/in_var.h>
156 #include <netinet/ip.h>
157 #include <netinet/ip_var.h>
159 #include <netinet/ip6.h>
160 #include <netinet6/ip6_var.h>
163 #include <netinet/ip_carp.h>
165 //#include <machine/in_cksum.h>
166 #include <netinet/if_ether.h> /* for struct arpcom */
167 #include <net/bridgestp.h>
168 #include <net/if_bridgevar.h>
169 #include <net/if_llc.h>
170 #include <net/if_vlan_var.h>
172 #include <net/if_ether.h>
173 #include <net/dlil.h>
174 #include <net/kpi_interfacefilter.h>
176 #include <net/route.h>
178 #include <netinet/ip_fw2.h>
179 #include <netinet/ip_dummynet.h>
180 #endif /* PFIL_HOOKS */
184 #define BR_LCKDBG_MAX 4
186 #define BRIDGE_LOCK(_sc) bridge_lock(_sc)
187 #define BRIDGE_UNLOCK(_sc) bridge_unlock(_sc)
188 #define BRIDGE_LOCK_ASSERT(_sc) lck_mtx_assert((_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED)
189 #define BRIDGE_LOCK2REF(_sc, _err) _err = bridge_lock2ref(_sc)
190 #define BRIDGE_UNREF(_sc) bridge_unref(_sc)
191 #define BRIDGE_XLOCK(_sc) bridge_xlock(_sc)
192 #define BRIDGE_XDROP(_sc) bridge_xdrop(_sc)
194 #else /* BRIDGE_DEBUG */
196 #define BRIDGE_LOCK(_sc) lck_mtx_lock((_sc)->sc_mtx)
197 #define BRIDGE_UNLOCK(_sc) lck_mtx_unlock((_sc)->sc_mtx)
198 #define BRIDGE_LOCK_ASSERT(_sc) lck_mtx_assert((_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED)
199 #define BRIDGE_LOCK2REF(_sc, _err) do { \
200 lck_mtx_assert((_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED); \
201 if ((_sc)->sc_iflist_xcnt > 0) \
204 (_sc)->sc_iflist_ref++; \
205 lck_mtx_unlock((_sc)->sc_mtx); \
207 #define BRIDGE_UNREF(_sc) do { \
208 lck_mtx_lock((_sc)->sc_mtx); \
209 (_sc)->sc_iflist_ref--; \
210 if (((_sc)->sc_iflist_xcnt > 0) && ((_sc)->sc_iflist_ref == 0)) { \
211 lck_mtx_unlock((_sc)->sc_mtx); \
212 wakeup(&(_sc)->sc_cv); \
214 lck_mtx_unlock((_sc)->sc_mtx); \
216 #define BRIDGE_XLOCK(_sc) do { \
217 lck_mtx_assert((_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED); \
218 (_sc)->sc_iflist_xcnt++; \
219 while ((_sc)->sc_iflist_ref > 0) \
220 msleep(&(_sc)->sc_cv, (_sc)->sc_mtx, PZERO, "BRIDGE_XLOCK", NULL); \
222 #define BRIDGE_XDROP(_sc) do { \
223 lck_mtx_assert((_sc)->sc_mtx, LCK_MTX_ASSERT_OWNED); \
224 (_sc)->sc_iflist_xcnt--; \
227 #endif /* BRIDGE_DEBUG */
230 #define BRIDGE_BPF_MTAP_INPUT(sc, m) \
231 if (sc->sc_bpf_input) \
232 bridge_bpf_input(sc->sc_ifp, m)
233 #else /* NBPFILTER */
234 #define BRIDGE_BPF_MTAP_INPUT(ifp, m)
235 #endif /* NBPFILTER */
238 * Size of the route hash table. Must be a power of two.
240 /* APPLE MODIFICATION - per Wasabi performance improvement, change the hash table size */
242 #ifndef BRIDGE_RTHASH_SIZE
243 #define BRIDGE_RTHASH_SIZE 1024
246 #ifndef BRIDGE_RTHASH_SIZE
247 #define BRIDGE_RTHASH_SIZE 256
251 /* APPLE MODIFICATION - support for HW checksums */
252 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
253 #include <netinet/udp.h>
254 #include <netinet/tcp.h>
257 #define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
260 * Maximum number of addresses to cache.
262 #ifndef BRIDGE_RTABLE_MAX
263 #define BRIDGE_RTABLE_MAX 100
268 * Timeout (in seconds) for entries learned dynamically.
270 #ifndef BRIDGE_RTABLE_TIMEOUT
271 #define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
275 * Number of seconds between walks of the route list.
277 #ifndef BRIDGE_RTABLE_PRUNE_PERIOD
278 #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
282 * List of capabilities to possibly mask on the member interface.
284 #define BRIDGE_IFCAPS_MASK (IFCAP_TOE|IFCAP_TSO|IFCAP_TXCSUM)
286 * List of capabilities to disable on the member interface.
288 #define BRIDGE_IFCAPS_STRIP IFCAP_LRO
291 * Bridge interface list entry.
293 struct bridge_iflist
{
294 TAILQ_ENTRY(bridge_iflist
) bif_next
;
295 struct ifnet
*bif_ifp
; /* member if */
296 struct bstp_port bif_stp
; /* STP state */
297 uint32_t bif_flags
; /* member if flags */
298 int bif_savedcaps
; /* saved capabilities */
299 uint32_t bif_addrmax
; /* max # of addresses */
300 uint32_t bif_addrcnt
; /* cur. # of addresses */
301 uint32_t bif_addrexceeded
;/* # of address violations */
303 interface_filter_t bif_iff_ref
;
304 struct bridge_softc
*bif_sc
;
305 char bif_promisc
; /* promiscuous mode set */
306 char bif_proto_attached
; /* protocol attached */
307 char bif_filter_attached
; /* interface filter attached */
313 struct bridge_rtnode
{
314 LIST_ENTRY(bridge_rtnode
) brt_hash
; /* hash table linkage */
315 LIST_ENTRY(bridge_rtnode
) brt_list
; /* list linkage */
316 struct bridge_iflist
*brt_dst
; /* destination if */
317 unsigned long brt_expire
; /* expiration time */
318 uint8_t brt_flags
; /* address flags */
319 uint8_t brt_addr
[ETHER_ADDR_LEN
];
320 uint16_t brt_vlan
; /* vlan id */
323 #define brt_ifp brt_dst->bif_ifp
326 * Software state for each bridge.
328 struct bridge_softc
{
329 struct ifnet
*sc_ifp
; /* make this an interface */
330 LIST_ENTRY(bridge_softc
) sc_list
;
333 uint32_t sc_brtmax
; /* max # of addresses */
334 uint32_t sc_brtcnt
; /* cur. # of addresses */
335 uint32_t sc_brttimeout
; /* rt timeout in seconds */
336 uint32_t sc_iflist_ref
; /* refcount for sc_iflist */
337 uint32_t sc_iflist_xcnt
; /* refcount for sc_iflist */
338 TAILQ_HEAD(, bridge_iflist
) sc_iflist
; /* member interface list */
339 LIST_HEAD(, bridge_rtnode
) *sc_rthash
; /* our forwarding table */
340 LIST_HEAD(, bridge_rtnode
) sc_rtlist
; /* list version of above */
341 uint32_t sc_rthash_key
; /* key for hash */
342 TAILQ_HEAD(, bridge_iflist
) sc_spanlist
; /* span ports list */
343 struct bstp_state sc_stp
; /* STP state */
344 uint32_t sc_brtexceeded
; /* # of cache drops */
345 uint32_t sc_filter_flags
; /* ipf and flags */
347 char sc_if_xname
[IFNAMSIZ
];
348 bpf_packet_func sc_bpf_input
;
349 bpf_packet_func sc_bpf_output
;
353 void *lock_lr
[BR_LCKDBG_MAX
]; /* locking calling history */
355 void *unlock_lr
[BR_LCKDBG_MAX
]; /* unlocking caller history */
357 #endif /* BRIDGE_DEBUG */
360 #define SCF_DETACHING 0x1
362 static lck_mtx_t
*bridge_list_mtx
;
363 //eventhandler_tag bridge_detach_cookie = NULL;
365 int bridge_rtable_prune_period
= BRIDGE_RTABLE_PRUNE_PERIOD
;
367 static zone_t bridge_rtnode_pool
= NULL
;
369 static int bridge_clone_create(struct if_clone
*, uint32_t, void *);
370 static int bridge_clone_destroy(struct ifnet
*);
372 static errno_t
bridge_ioctl(struct ifnet
*, u_long
, void *);
374 static void bridge_mutecaps(struct bridge_softc
*);
375 static void bridge_set_ifcap(struct bridge_softc
*, struct bridge_iflist
*,
378 __private_extern__
void bridge_ifdetach(struct bridge_iflist
*, struct ifnet
*);
379 static int bridge_init(struct ifnet
*);
380 #if HAS_BRIDGE_DUMMYNET
381 static void bridge_dummynet(struct mbuf
*, struct ifnet
*);
383 static void bridge_stop(struct ifnet
*, int);
384 static errno_t
bridge_start(struct ifnet
*, struct mbuf
*);
385 __private_extern__ errno_t
bridge_input(struct ifnet
*, struct mbuf
*, void *);
386 #if BRIDGE_MEMBER_OUT_FILTER
387 static errno_t
bridge_iff_output(void *, ifnet_t
, protocol_family_t
, mbuf_t
*);
388 static int bridge_output(struct ifnet
*, struct mbuf
*, struct sockaddr
*,
391 static void bridge_enqueue(struct bridge_softc
*, struct ifnet
*,
393 static void bridge_rtdelete(struct bridge_softc
*, struct ifnet
*ifp
, int);
395 static void bridge_forward(struct bridge_softc
*, struct bridge_iflist
*,
398 static void bridge_timer(void *);
400 static void bridge_broadcast(struct bridge_softc
*, struct ifnet
*,
402 static void bridge_span(struct bridge_softc
*, struct mbuf
*);
404 static int bridge_rtupdate(struct bridge_softc
*, const uint8_t *,
405 uint16_t, struct bridge_iflist
*, int, uint8_t);
406 static struct ifnet
*bridge_rtlookup(struct bridge_softc
*, const uint8_t *,
408 static void bridge_rttrim(struct bridge_softc
*);
409 static void bridge_rtage(struct bridge_softc
*);
410 static void bridge_rtflush(struct bridge_softc
*, int);
411 static int bridge_rtdaddr(struct bridge_softc
*, const uint8_t *,
414 static int bridge_rtable_init(struct bridge_softc
*);
415 static void bridge_rtable_fini(struct bridge_softc
*);
417 static int bridge_rtnode_addr_cmp(const uint8_t *, const uint8_t *);
418 static struct bridge_rtnode
*bridge_rtnode_lookup(struct bridge_softc
*,
419 const uint8_t *, uint16_t);
420 static int bridge_rtnode_insert(struct bridge_softc
*,
421 struct bridge_rtnode
*);
422 static void bridge_rtnode_destroy(struct bridge_softc
*,
423 struct bridge_rtnode
*);
424 static void bridge_rtable_expire(struct ifnet
*, int);
425 static void bridge_state_change(struct ifnet
*, int);
427 static struct bridge_iflist
*bridge_lookup_member(struct bridge_softc
*,
429 static struct bridge_iflist
*bridge_lookup_member_if(struct bridge_softc
*,
431 static void bridge_delete_member(struct bridge_softc
*,
432 struct bridge_iflist
*, int);
433 static void bridge_delete_span(struct bridge_softc
*,
434 struct bridge_iflist
*);
436 static int bridge_ioctl_add(struct bridge_softc
*, void *);
437 static int bridge_ioctl_del(struct bridge_softc
*, void *);
438 static int bridge_ioctl_gifflags(struct bridge_softc
*, void *);
439 static int bridge_ioctl_sifflags(struct bridge_softc
*, void *);
440 static int bridge_ioctl_scache(struct bridge_softc
*, void *);
441 static int bridge_ioctl_gcache(struct bridge_softc
*, void *);
442 static int bridge_ioctl_gifs32(struct bridge_softc
*, void *);
443 static int bridge_ioctl_gifs64(struct bridge_softc
*, void *);
444 static int bridge_ioctl_rts32(struct bridge_softc
*, void *);
445 static int bridge_ioctl_rts64(struct bridge_softc
*, void *);
446 static int bridge_ioctl_saddr32(struct bridge_softc
*, void *);
447 static int bridge_ioctl_saddr64(struct bridge_softc
*, void *);
448 static int bridge_ioctl_sto(struct bridge_softc
*, void *);
449 static int bridge_ioctl_gto(struct bridge_softc
*, void *);
450 static int bridge_ioctl_daddr32(struct bridge_softc
*, void *);
451 static int bridge_ioctl_daddr64(struct bridge_softc
*, void *);
452 static int bridge_ioctl_flush(struct bridge_softc
*, void *);
453 static int bridge_ioctl_gpri(struct bridge_softc
*, void *);
454 static int bridge_ioctl_spri(struct bridge_softc
*, void *);
455 static int bridge_ioctl_ght(struct bridge_softc
*, void *);
456 static int bridge_ioctl_sht(struct bridge_softc
*, void *);
457 static int bridge_ioctl_gfd(struct bridge_softc
*, void *);
458 static int bridge_ioctl_sfd(struct bridge_softc
*, void *);
459 static int bridge_ioctl_gma(struct bridge_softc
*, void *);
460 static int bridge_ioctl_sma(struct bridge_softc
*, void *);
461 static int bridge_ioctl_sifprio(struct bridge_softc
*, void *);
462 static int bridge_ioctl_sifcost(struct bridge_softc
*, void *);
463 static int bridge_ioctl_sifmaxaddr(struct bridge_softc
*, void *);
464 static int bridge_ioctl_addspan(struct bridge_softc
*, void *);
465 static int bridge_ioctl_delspan(struct bridge_softc
*, void *);
466 static int bridge_ioctl_gbparam32(struct bridge_softc
*, void *);
467 static int bridge_ioctl_gbparam64(struct bridge_softc
*, void *);
468 static int bridge_ioctl_grte(struct bridge_softc
*, void *);
469 static int bridge_ioctl_gifsstp32(struct bridge_softc
*, void *);
470 static int bridge_ioctl_gifsstp64(struct bridge_softc
*, void *);
471 static int bridge_ioctl_sproto(struct bridge_softc
*, void *);
472 static int bridge_ioctl_stxhc(struct bridge_softc
*, void *);
473 static int bridge_ioctl_purge(struct bridge_softc
*sc
, void *arg
);
474 static int bridge_ioctl_gfilt(struct bridge_softc
*, void *);
475 static int bridge_ioctl_sfilt(struct bridge_softc
*, void *);
477 static int bridge_pfil(struct mbuf
**, struct ifnet
*, struct ifnet
*,
479 static int bridge_ip_checkbasic(struct mbuf
**mp
);
481 static int bridge_ip6_checkbasic(struct mbuf
**mp
);
483 static int bridge_fragment(struct ifnet
*, struct mbuf
*,
484 struct ether_header
*, int, struct llc
*);
485 #endif /* PFIL_HOOKS */
487 static errno_t
bridge_set_bpf_tap(ifnet_t ifn
, bpf_tap_mode mode
, bpf_packet_func bpf_callback
);
488 __private_extern__ errno_t
bridge_bpf_input(ifnet_t ifp
, struct mbuf
*m
);
489 __private_extern__ errno_t
bridge_bpf_output(ifnet_t ifp
, struct mbuf
*m
);
491 static void bridge_detach(ifnet_t ifp
);
493 #define m_copypacket(m, how) m_copym(m, 0, M_COPYALL, how)
495 /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */
496 #define VLANTAGOF(_m) 0
498 static struct bstp_cb_ops bridge_ops
= {
499 .bcb_state
= bridge_state_change
,
500 .bcb_rtage
= bridge_rtable_expire
503 SYSCTL_DECL(_net_link
);
504 SYSCTL_NODE(_net_link
, IFT_BRIDGE
, bridge
, CTLFLAG_RW
, 0, "Bridge");
506 #if defined(PFIL_HOOKS)
507 static int pfil_onlyip
= 1; /* only pass IP[46] packets when pfil is enabled */
508 static int pfil_bridge
= 1; /* run pfil hooks on the bridge interface */
509 static int pfil_member
= 1; /* run pfil hooks on the member interface */
510 static int pfil_ipfw
= 0; /* layer2 filter with ipfw */
511 static int pfil_ipfw_arp
= 0; /* layer2 filter with ipfw */
512 static int pfil_local_phys
= 0; /* run pfil hooks on the physical interface for
513 locally destined packets */
514 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, pfil_onlyip
, CTLFLAG_RW
,
515 &pfil_onlyip
, 0, "Only pass IP packets when pfil is enabled");
516 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, ipfw_arp
, CTLFLAG_RW
,
517 &pfil_ipfw_arp
, 0, "Filter ARP packets through IPFW layer2");
518 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, pfil_bridge
, CTLFLAG_RW
,
519 &pfil_bridge
, 0, "Packet filter on the bridge interface");
520 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, pfil_member
, CTLFLAG_RW
,
521 &pfil_member
, 0, "Packet filter on the member interface");
522 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, pfil_local_phys
, CTLFLAG_RW
,
524 "Packet filter on the physical interface for locally destined packets");
525 #endif /* PFIL_HOOKS */
527 static int log_stp
= 0; /* log STP state changes */
528 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, log_stp
, CTLFLAG_RW
,
529 &log_stp
, 0, "Log STP state changes");
531 struct bridge_control
{
532 int (*bc_func
)(struct bridge_softc
*, void *);
533 unsigned int bc_argsize
;
534 unsigned int bc_flags
;
537 #define BC_F_COPYIN 0x01 /* copy arguments in */
538 #define BC_F_COPYOUT 0x02 /* copy arguments out */
539 #define BC_F_SUSER 0x04 /* do super-user check */
541 static const struct bridge_control bridge_control_table32
[] = {
542 { bridge_ioctl_add
, sizeof(struct ifbreq
),
543 BC_F_COPYIN
|BC_F_SUSER
},
544 { bridge_ioctl_del
, sizeof(struct ifbreq
),
545 BC_F_COPYIN
|BC_F_SUSER
},
547 { bridge_ioctl_gifflags
, sizeof(struct ifbreq
),
548 BC_F_COPYIN
|BC_F_COPYOUT
},
549 { bridge_ioctl_sifflags
, sizeof(struct ifbreq
),
550 BC_F_COPYIN
|BC_F_SUSER
},
552 { bridge_ioctl_scache
, sizeof(struct ifbrparam
),
553 BC_F_COPYIN
|BC_F_SUSER
},
554 { bridge_ioctl_gcache
, sizeof(struct ifbrparam
),
557 { bridge_ioctl_gifs32
, sizeof(struct ifbifconf32
),
558 BC_F_COPYIN
|BC_F_COPYOUT
},
559 { bridge_ioctl_rts32
, sizeof(struct ifbaconf32
),
560 BC_F_COPYIN
|BC_F_COPYOUT
},
562 { bridge_ioctl_saddr32
, sizeof(struct ifbareq32
),
563 BC_F_COPYIN
|BC_F_SUSER
},
565 { bridge_ioctl_sto
, sizeof(struct ifbrparam
),
566 BC_F_COPYIN
|BC_F_SUSER
},
567 { bridge_ioctl_gto
, sizeof(struct ifbrparam
),
570 { bridge_ioctl_daddr32
, sizeof(struct ifbareq32
),
571 BC_F_COPYIN
|BC_F_SUSER
},
573 { bridge_ioctl_flush
, sizeof(struct ifbreq
),
574 BC_F_COPYIN
|BC_F_SUSER
},
576 { bridge_ioctl_gpri
, sizeof(struct ifbrparam
),
578 { bridge_ioctl_spri
, sizeof(struct ifbrparam
),
579 BC_F_COPYIN
|BC_F_SUSER
},
581 { bridge_ioctl_ght
, sizeof(struct ifbrparam
),
583 { bridge_ioctl_sht
, sizeof(struct ifbrparam
),
584 BC_F_COPYIN
|BC_F_SUSER
},
586 { bridge_ioctl_gfd
, sizeof(struct ifbrparam
),
588 { bridge_ioctl_sfd
, sizeof(struct ifbrparam
),
589 BC_F_COPYIN
|BC_F_SUSER
},
591 { bridge_ioctl_gma
, sizeof(struct ifbrparam
),
593 { bridge_ioctl_sma
, sizeof(struct ifbrparam
),
594 BC_F_COPYIN
|BC_F_SUSER
},
596 { bridge_ioctl_sifprio
, sizeof(struct ifbreq
),
597 BC_F_COPYIN
|BC_F_SUSER
},
599 { bridge_ioctl_sifcost
, sizeof(struct ifbreq
),
600 BC_F_COPYIN
|BC_F_SUSER
},
602 { bridge_ioctl_gfilt
, sizeof(struct ifbrparam
),
604 { bridge_ioctl_sfilt
, sizeof(struct ifbrparam
),
605 BC_F_COPYIN
|BC_F_SUSER
},
607 { bridge_ioctl_purge
, sizeof(struct ifbreq
),
608 BC_F_COPYIN
|BC_F_SUSER
},
610 { bridge_ioctl_addspan
, sizeof(struct ifbreq
),
611 BC_F_COPYIN
|BC_F_SUSER
},
612 { bridge_ioctl_delspan
, sizeof(struct ifbreq
),
613 BC_F_COPYIN
|BC_F_SUSER
},
615 { bridge_ioctl_gbparam32
, sizeof(struct ifbropreq32
),
618 { bridge_ioctl_grte
, sizeof(struct ifbrparam
),
621 { bridge_ioctl_gifsstp32
, sizeof(struct ifbpstpconf32
),
622 BC_F_COPYIN
|BC_F_COPYOUT
},
624 { bridge_ioctl_sproto
, sizeof(struct ifbrparam
),
625 BC_F_COPYIN
|BC_F_SUSER
},
627 { bridge_ioctl_stxhc
, sizeof(struct ifbrparam
),
628 BC_F_COPYIN
|BC_F_SUSER
},
630 { bridge_ioctl_sifmaxaddr
, sizeof(struct ifbreq
),
631 BC_F_COPYIN
|BC_F_SUSER
},
634 static const struct bridge_control bridge_control_table64
[] = {
635 { bridge_ioctl_add
, sizeof(struct ifbreq
),
636 BC_F_COPYIN
|BC_F_SUSER
},
637 { bridge_ioctl_del
, sizeof(struct ifbreq
),
638 BC_F_COPYIN
|BC_F_SUSER
},
640 { bridge_ioctl_gifflags
, sizeof(struct ifbreq
),
641 BC_F_COPYIN
|BC_F_COPYOUT
},
642 { bridge_ioctl_sifflags
, sizeof(struct ifbreq
),
643 BC_F_COPYIN
|BC_F_SUSER
},
645 { bridge_ioctl_scache
, sizeof(struct ifbrparam
),
646 BC_F_COPYIN
|BC_F_SUSER
},
647 { bridge_ioctl_gcache
, sizeof(struct ifbrparam
),
650 { bridge_ioctl_gifs64
, sizeof(struct ifbifconf64
),
651 BC_F_COPYIN
|BC_F_COPYOUT
},
652 { bridge_ioctl_rts64
, sizeof(struct ifbaconf64
),
653 BC_F_COPYIN
|BC_F_COPYOUT
},
655 { bridge_ioctl_saddr64
, sizeof(struct ifbareq64
),
656 BC_F_COPYIN
|BC_F_SUSER
},
658 { bridge_ioctl_sto
, sizeof(struct ifbrparam
),
659 BC_F_COPYIN
|BC_F_SUSER
},
660 { bridge_ioctl_gto
, sizeof(struct ifbrparam
),
663 { bridge_ioctl_daddr64
, sizeof(struct ifbareq64
),
664 BC_F_COPYIN
|BC_F_SUSER
},
666 { bridge_ioctl_flush
, sizeof(struct ifbreq
),
667 BC_F_COPYIN
|BC_F_SUSER
},
669 { bridge_ioctl_gpri
, sizeof(struct ifbrparam
),
671 { bridge_ioctl_spri
, sizeof(struct ifbrparam
),
672 BC_F_COPYIN
|BC_F_SUSER
},
674 { bridge_ioctl_ght
, sizeof(struct ifbrparam
),
676 { bridge_ioctl_sht
, sizeof(struct ifbrparam
),
677 BC_F_COPYIN
|BC_F_SUSER
},
679 { bridge_ioctl_gfd
, sizeof(struct ifbrparam
),
681 { bridge_ioctl_sfd
, sizeof(struct ifbrparam
),
682 BC_F_COPYIN
|BC_F_SUSER
},
684 { bridge_ioctl_gma
, sizeof(struct ifbrparam
),
686 { bridge_ioctl_sma
, sizeof(struct ifbrparam
),
687 BC_F_COPYIN
|BC_F_SUSER
},
689 { bridge_ioctl_sifprio
, sizeof(struct ifbreq
),
690 BC_F_COPYIN
|BC_F_SUSER
},
692 { bridge_ioctl_sifcost
, sizeof(struct ifbreq
),
693 BC_F_COPYIN
|BC_F_SUSER
},
695 { bridge_ioctl_gfilt
, sizeof(struct ifbrparam
),
697 { bridge_ioctl_sfilt
, sizeof(struct ifbrparam
),
698 BC_F_COPYIN
|BC_F_SUSER
},
700 { bridge_ioctl_purge
, sizeof(struct ifbreq
),
701 BC_F_COPYIN
|BC_F_SUSER
},
703 { bridge_ioctl_addspan
, sizeof(struct ifbreq
),
704 BC_F_COPYIN
|BC_F_SUSER
},
705 { bridge_ioctl_delspan
, sizeof(struct ifbreq
),
706 BC_F_COPYIN
|BC_F_SUSER
},
708 { bridge_ioctl_gbparam64
, sizeof(struct ifbropreq64
),
711 { bridge_ioctl_grte
, sizeof(struct ifbrparam
),
714 { bridge_ioctl_gifsstp64
, sizeof(struct ifbpstpconf64
),
715 BC_F_COPYIN
|BC_F_COPYOUT
},
717 { bridge_ioctl_sproto
, sizeof(struct ifbrparam
),
718 BC_F_COPYIN
|BC_F_SUSER
},
720 { bridge_ioctl_stxhc
, sizeof(struct ifbrparam
),
721 BC_F_COPYIN
|BC_F_SUSER
},
723 { bridge_ioctl_sifmaxaddr
, sizeof(struct ifbreq
),
724 BC_F_COPYIN
|BC_F_SUSER
},
727 static const unsigned int bridge_control_table_size
=
728 sizeof(bridge_control_table32
) / sizeof(bridge_control_table32
[0]);
730 static LIST_HEAD(, bridge_softc
) bridge_list
= LIST_HEAD_INITIALIZER(bridge_list
);
732 static lck_grp_t
*bridge_lock_grp
= NULL
;
733 static lck_attr_t
*bridge_lock_attr
= NULL
;
735 static if_clone_t bridge_cloner
= NULL
;
737 __private_extern__
int _if_brige_debug
= 0;
739 SYSCTL_INT(_net_link_bridge
, OID_AUTO
, debug
, CTLFLAG_RW
,
740 &_if_brige_debug
, 0, "Bridge debug");
744 static void printf_ether_header(struct ether_header
*eh
);
745 static void printf_mbuf_data(mbuf_t m
, size_t offset
, size_t len
);
746 static void printf_mbuf_pkthdr(mbuf_t m
, const char *prefix
, const char *suffix
);
747 static void printf_mbuf(mbuf_t m
, const char *prefix
, const char *suffix
);
748 static void link_print(struct sockaddr_dl
* dl_p
);
750 static void bridge_lock(struct bridge_softc
*);
751 static void bridge_unlock(struct bridge_softc
*);
752 static int bridge_lock2ref(struct bridge_softc
*);
753 static void bridge_unref(struct bridge_softc
*);
754 static void bridge_xlock(struct bridge_softc
*);
755 static void bridge_xdrop(struct bridge_softc
*);
757 static void bridge_lock(struct bridge_softc
*sc
)
759 void *lr_saved
= __builtin_return_address(0);
761 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
763 lck_mtx_lock(sc
->sc_mtx
);
765 sc
->lock_lr
[sc
->next_lock_lr
] = lr_saved
;
766 sc
->next_lock_lr
= (sc
->next_lock_lr
+1) % SO_LCKDBG_MAX
;
769 static void bridge_unlock(struct bridge_softc
*sc
)
771 void *lr_saved
= __builtin_return_address(0);
773 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_OWNED
);
775 sc
->unlock_lr
[sc
->next_unlock_lr
] = lr_saved
;
776 sc
->next_unlock_lr
= (sc
->next_unlock_lr
+1) % SO_LCKDBG_MAX
;
778 lck_mtx_unlock(sc
->sc_mtx
);
781 static int bridge_lock2ref(struct bridge_softc
*sc
)
784 void *lr_saved
= __builtin_return_address(0);
786 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_OWNED
);
788 if (sc
->sc_iflist_xcnt
> 0)
793 sc
->unlock_lr
[sc
->next_unlock_lr
] = lr_saved
;
794 sc
->next_unlock_lr
= (sc
->next_unlock_lr
+1) % SO_LCKDBG_MAX
;
795 lck_mtx_unlock(sc
->sc_mtx
);
800 static void bridge_unref(struct bridge_softc
*sc
)
802 void *lr_saved
= __builtin_return_address(0);
804 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
806 lck_mtx_lock(sc
->sc_mtx
);
807 sc
->lock_lr
[sc
->next_lock_lr
] = lr_saved
;
808 sc
->next_lock_lr
= (sc
->next_lock_lr
+1) % SO_LCKDBG_MAX
;
812 sc
->unlock_lr
[sc
->next_unlock_lr
] = lr_saved
;
813 sc
->next_unlock_lr
= (sc
->next_unlock_lr
+1) % SO_LCKDBG_MAX
;
814 if ((sc
->sc_iflist_xcnt
> 0) && (sc
->sc_iflist_ref
== 0)) {
815 lck_mtx_unlock(sc
->sc_mtx
);
818 lck_mtx_unlock(sc
->sc_mtx
);
821 static void bridge_xlock(struct bridge_softc
*sc
)
823 void *lr_saved
= __builtin_return_address(0);
825 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_OWNED
);
827 sc
->sc_iflist_xcnt
++;
828 while (sc
->sc_iflist_ref
> 0) {
829 sc
->unlock_lr
[sc
->next_unlock_lr
] = lr_saved
;
830 sc
->next_unlock_lr
= (sc
->next_unlock_lr
+1) % SO_LCKDBG_MAX
;
832 msleep(&sc
->sc_cv
, sc
->sc_mtx
, PZERO
, "BRIDGE_XLOCK", NULL
);
834 sc
->lock_lr
[sc
->next_lock_lr
] = lr_saved
;
835 sc
->next_lock_lr
= (sc
->next_lock_lr
+1) % SO_LCKDBG_MAX
;
839 static void bridge_xdrop(struct bridge_softc
*sc
)
841 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_OWNED
);
843 sc
->sc_iflist_xcnt
--;
847 printf_mbuf_pkthdr(mbuf_t m
, const char *prefix
, const char *suffix
)
850 printf("%spktlen: %u rcvif: %p header: %p nextpkt: %p%s",
851 prefix
? prefix
: "",
852 (unsigned int)mbuf_pkthdr_len(m
), mbuf_pkthdr_rcvif(m
), mbuf_pkthdr_header(m
), mbuf_nextpkt(m
),
853 suffix
? suffix
: "");
855 printf("%s<NULL>%s\n", prefix
, suffix
);
859 printf_mbuf(mbuf_t m
, const char *prefix
, const char *suffix
)
862 printf("%s%p type: %u flags: 0x%x len: %u data: %p maxlen: %u datastart: %p next: %p%s",
863 prefix
? prefix
: "",
864 m
, mbuf_type(m
), mbuf_flags(m
), (unsigned int)mbuf_len(m
), mbuf_data(m
),
865 (unsigned int)mbuf_maxlen(m
), mbuf_datastart(m
), mbuf_next(m
),
866 !suffix
|| (mbuf_flags(m
) & MBUF_PKTHDR
) ? "" : suffix
);
867 if ((mbuf_flags(m
) & MBUF_PKTHDR
))
868 printf_mbuf_pkthdr(m
, " ", suffix
);
870 printf("%s<NULL>%s\n", prefix
, suffix
);
874 printf_mbuf_data(mbuf_t m
, size_t offset
, size_t len
)
878 size_t pktlen
, mlen
, maxlen
;
881 pktlen
= mbuf_pkthdr_len(m
);
886 maxlen
= (pktlen
- offset
> len
) ? len
: pktlen
;
890 for (i
= 0, j
= 0; i
< maxlen
; i
++, j
++) {
900 printf("%02x%s", ptr
[j
], i
% 2 ? " " : "");
907 printf_ether_header(struct ether_header
*eh
)
909 printf("%02x:%02x:%02x:%02x:%02x:%02x > %02x:%02x:%02x:%02x:%02x:%02x 0x%04x ",
910 eh
->ether_shost
[0], eh
->ether_shost
[1], eh
->ether_shost
[2],
911 eh
->ether_shost
[3], eh
->ether_shost
[4], eh
->ether_shost
[5],
912 eh
->ether_dhost
[0], eh
->ether_dhost
[1], eh
->ether_dhost
[2],
913 eh
->ether_dhost
[3], eh
->ether_dhost
[4], eh
->ether_dhost
[5],
918 link_print(struct sockaddr_dl
* dl_p
)
923 printf("sdl len %d index %d family %d type 0x%x nlen %d alen %d"
924 " slen %d addr ", dl_p
->sdl_len
,
925 dl_p
->sdl_index
, dl_p
->sdl_family
, dl_p
->sdl_type
,
926 dl_p
->sdl_nlen
, dl_p
->sdl_alen
, dl_p
->sdl_slen
);
928 for (i
= 0; i
< dl_p
->sdl_alen
; i
++)
929 printf("%s%x", i
? ":" : "",
930 (CONST_LLADDR(dl_p
))[i
]);
935 #endif /* BRIDGE_DEBUG */
940 * Pseudo-device attach routine.
942 __private_extern__
int
943 bridgeattach(__unused
int n
)
946 lck_grp_attr_t
*lck_grp_attr
= NULL
;
947 struct ifnet_clone_params ifnet_clone_params
;
949 bridge_rtnode_pool
= zinit(sizeof(struct bridge_rtnode
), 1024 * sizeof(struct bridge_rtnode
),
951 zone_change(bridge_rtnode_pool
, Z_CALLERACCT
, FALSE
);
953 lck_grp_attr
= lck_grp_attr_alloc_init();
955 bridge_lock_grp
= lck_grp_alloc_init("if_bridge", lck_grp_attr
);
957 bridge_lock_attr
= lck_attr_alloc_init();
960 lck_attr_setdebug(bridge_lock_attr
);
963 bridge_list_mtx
= lck_mtx_alloc_init(bridge_lock_grp
, bridge_lock_attr
);
965 // can free the attributes once we've allocated the group lock
966 lck_grp_attr_free(lck_grp_attr
);
968 LIST_INIT(&bridge_list
);
972 ifnet_clone_params
.ifc_name
= "bridge";
973 ifnet_clone_params
.ifc_create
= bridge_clone_create
;
974 ifnet_clone_params
.ifc_destroy
= bridge_clone_destroy
;
976 error
= ifnet_clone_attach(&ifnet_clone_params
, &bridge_cloner
);
978 printf("bridgeattach: ifnet_clone_attach failed %d\n", error
);
983 #if defined(PFIL_HOOKS)
985 * handler for net.link.bridge.pfil_ipfw
988 sysctl_pfil_ipfw SYSCTL_HANDLER_ARGS
990 #pragma unused(arg1,arg2)
991 int enable
= pfil_ipfw
;
994 error
= sysctl_handle_int(oidp
, &enable
, 0, req
);
995 enable
= (enable
) ? 1 : 0;
997 if (enable
!= pfil_ipfw
) {
1001 * Disable pfil so that ipfw doesnt run twice, if the user
1002 * really wants both then they can re-enable pfil_bridge and/or
1003 * pfil_member. Also allow non-ip packets as ipfw can filter by
1015 SYSCTL_PROC(_net_link_bridge
, OID_AUTO
, ipfw
, CTLTYPE_INT
|CTLFLAG_RW
,
1016 &pfil_ipfw
, 0, &sysctl_pfil_ipfw
, "I", "Layer2 filter with IPFW");
1017 #endif /* PFIL_HOOKS */
1020 * bridge_clone_create:
1022 * Create a new bridge instance.
1025 bridge_clone_create(struct if_clone
*ifc
, uint32_t unit
, __unused
void *params
)
1027 struct ifnet
*ifp
= NULL
;
1028 struct bridge_softc
*sc
;
1030 struct ifnet_init_params init_params
;
1032 uint32_t sdl_buffer
[offsetof(struct sockaddr_dl
, sdl_data
) + IFNAMSIZ
+ ETHER_ADDR_LEN
];
1033 struct sockaddr_dl
*sdl
= (struct sockaddr_dl
*)sdl_buffer
;
1035 sc
= _MALLOC(sizeof(*sc
), M_DEVBUF
, M_WAITOK
);
1036 memset(sc
, 0, sizeof(*sc
));
1038 sc
->sc_mtx
= lck_mtx_alloc_init(bridge_lock_grp
, bridge_lock_attr
);
1039 sc
->sc_brtmax
= BRIDGE_RTABLE_MAX
;
1040 sc
->sc_brttimeout
= BRIDGE_RTABLE_TIMEOUT
;
1041 sc
->sc_filter_flags
= IFBF_FILT_DEFAULT
;
1044 * For backwards compatibility with previous behaviour...
1045 * Switch off filtering on the bridge itself if BRIDGE_IPF is
1048 sc
->sc_filter_flags
&= ~IFBF_FILT_USEIPF
;
1051 /* Initialize our routing table. */
1052 error
= bridge_rtable_init(sc
);
1054 printf("bridge_clone_create: bridge_rtable_init failed %d\n", error
);
1058 TAILQ_INIT(&sc
->sc_iflist
);
1059 TAILQ_INIT(&sc
->sc_spanlist
);
1061 /* use the interface name as the unique id for ifp recycle */
1062 snprintf(sc
->sc_if_xname
, sizeof(sc
->sc_if_xname
), "%s%d",
1063 ifc
->ifc_name
, unit
);
1064 memset(&init_params
, 0, sizeof(struct ifnet_init_params
));
1065 init_params
.uniqueid
= sc
->sc_if_xname
;
1066 init_params
.uniqueid_len
= strlen(sc
->sc_if_xname
);
1067 init_params
.name
= ifc
->ifc_name
;
1068 init_params
.unit
= unit
;
1069 init_params
.family
= IFNET_FAMILY_ETHERNET
;
1070 init_params
.type
= IFT_BRIDGE
;
1071 init_params
.output
= bridge_start
;
1072 init_params
.demux
= ether_demux
;
1073 init_params
.add_proto
= ether_add_proto
;
1074 init_params
.del_proto
= ether_del_proto
;
1075 init_params
.check_multi
= ether_check_multi
;
1076 init_params
.framer
= ether_frameout
;
1077 init_params
.softc
= sc
;
1078 init_params
.ioctl
= bridge_ioctl
;
1079 init_params
.set_bpf_tap
= bridge_set_bpf_tap
;
1080 init_params
.detach
= bridge_detach
;
1081 init_params
.broadcast_addr
= etherbroadcastaddr
;
1082 init_params
.broadcast_len
= ETHER_ADDR_LEN
;
1083 error
= ifnet_allocate(&init_params
, &ifp
);
1085 printf("bridge_clone_create: ifnet_allocate failed %d\n", error
);
1090 error
= ifnet_set_mtu(ifp
, ETHERMTU
);
1092 printf("bridge_clone_create: ifnet_set_mtu failed %d\n", error
);
1095 error
= ifnet_set_addrlen(ifp
, ETHER_ADDR_LEN
);
1097 printf("bridge_clone_create: ifnet_set_addrlen failed %d\n", error
);
1100 error
= ifnet_set_baudrate(ifp
, 10000000) ; // XXX: this is what IONetworking does
1102 printf("bridge_clone_create: ifnet_set_baudrate failed %d\n", error
);
1105 error
= ifnet_set_hdrlen(ifp
, ETHER_HDR_LEN
);
1107 printf("bridge_clone_create: ifnet_set_hdrlen failed %d\n", error
);
1110 error
= ifnet_set_flags(ifp
, IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
| IFF_MULTICAST
,
1113 printf("bridge_clone_create: ifnet_set_flags failed %d\n", error
);
1119 * Generate a random ethernet address with a locally administered
1122 * Since we are using random ethernet addresses for the bridge, it is
1123 * possible that we might have address collisions, so make sure that
1124 * this hardware address isn't already in use on another bridge.
1129 for (retry
= 1; retry
!= 0;) {
1131 struct bridge_softc
*sc2
;
1133 read_random(eaddr
, ETHER_ADDR_LEN
);
1134 eaddr
[0] &= ~1; /* clear multicast bit */
1135 eaddr
[0] |= 2; /* set the LAA bit */
1137 lck_mtx_lock(bridge_list_mtx
);
1138 LIST_FOREACH(sc2
, &bridge_list
, sc_list
) {
1140 if (memcmp(eaddr
, ifnet_lladdr(bifp
), ETHER_ADDR_LEN
) == 0)
1143 lck_mtx_unlock(bridge_list_mtx
);
1148 * Generate a random ethernet address and use the private AC:DE:48
1154 read_random(&r
, sizeof(r
));
1158 eaddr
[3] = (r
>> 0) & 0xffu
;
1159 eaddr
[4] = (r
>> 8) & 0xffu
;
1160 eaddr
[5] = (r
>> 16) & 0xffu
;
1164 memset(sdl
, 0, sizeof(sdl_buffer
));
1165 sdl
->sdl_family
= AF_LINK
;
1166 sdl
->sdl_nlen
= strlen(sc
->sc_if_xname
);
1167 sdl
->sdl_alen
= ETHER_ADDR_LEN
;
1168 sdl
->sdl_len
= offsetof(struct sockaddr_dl
, sdl_data
);
1169 memcpy(sdl
->sdl_data
, sc
->sc_if_xname
, sdl
->sdl_nlen
);
1170 memcpy(LLADDR(sdl
), eaddr
, ETHER_ADDR_LEN
);
1176 error
= ifnet_attach(ifp
, NULL
);
1178 printf("bridge_clone_create: ifnet_attach failed %d\n", error
);
1182 error
= ifnet_set_lladdr_and_type(ifp
, eaddr
, ETHER_ADDR_LEN
, IFT_ETHER
);
1184 printf("bridge_clone_create: ifnet_set_lladdr_and_type failed %d\n", error
);
1188 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
1190 * APPLE MODIFICATION - our bridge can support HW checksums
1191 * (useful if underlying interfaces support them) on TX,
1192 * RX is not that interesting, since the stack just looks to
1193 * see if the packet has been checksummed already (I think)
1194 * but we might as well indicate we support it
1196 ifp
->if_capabilities
=
1197 IFCAP_CSUM_IPv4_Tx
| IFCAP_CSUM_TCPv4_Tx
| IFCAP_CSUM_UDPv4_Tx
|
1198 IFCAP_CSUM_IPv4_Rx
| IFCAP_CSUM_TCPv4_Rx
| IFCAP_CSUM_UDPv4_Rx
;
1201 bstp_attach(&sc
->sc_stp
, &bridge_ops
);
1203 lck_mtx_lock(bridge_list_mtx
);
1204 LIST_INSERT_HEAD(&bridge_list
, sc
, sc_list
);
1205 lck_mtx_unlock(bridge_list_mtx
);
1207 /* attach as ethernet */
1208 error
= bpf_attach(ifp
, DLT_EN10MB
, sizeof(struct ether_header
), NULL
, NULL
);
1212 printf("bridge_clone_create failed error %d\n", error
);
1220 * bridge_clone_destroy:
1222 * Destroy a bridge instance.
1225 bridge_clone_destroy(struct ifnet
*ifp
)
1227 struct bridge_softc
*sc
= ifp
->if_softc
;
1228 struct bridge_iflist
*bif
;
1232 if ((sc
->sc_flags
& SCF_DETACHING
)) {
1236 sc
->sc_flags
|= SCF_DETACHING
;
1238 bridge_stop(ifp
, 1);
1240 error
= ifnet_set_flags(ifp
, 0, IFF_UP
);
1242 printf("bridge_clone_destroy: ifnet_set_flags failed %d\n", error
);
1245 while ((bif
= TAILQ_FIRST(&sc
->sc_iflist
)) != NULL
)
1246 bridge_delete_member(sc
, bif
, 0);
1248 while ((bif
= TAILQ_FIRST(&sc
->sc_spanlist
)) != NULL
) {
1249 bridge_delete_span(sc
, bif
);
1254 error
= ifnet_detach(ifp
);
1256 panic("bridge_clone_destroy: ifnet_detach(%p) failed %d\n", ifp
, error
);
1257 if ((sc
= (struct bridge_softc
*)ifnet_softc(ifp
)) != NULL
) {
1259 sc
->sc_flags
&= ~SCF_DETACHING
;
1268 #define DRVSPEC do { \
1269 if (ifd->ifd_cmd >= bridge_control_table_size) { \
1273 bc = &bridge_control_table[ifd->ifd_cmd]; \
1275 if (cmd == SIOCGDRVSPEC && \
1276 (bc->bc_flags & BC_F_COPYOUT) == 0) { \
1280 else if (cmd == SIOCSDRVSPEC && \
1281 (bc->bc_flags & BC_F_COPYOUT) != 0) { \
1286 if (bc->bc_flags & BC_F_SUSER) { \
1287 error = kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER); \
1292 if (ifd->ifd_len != bc->bc_argsize || \
1293 ifd->ifd_len > sizeof(args)) { \
1298 bzero(&args, sizeof(args)); \
1299 if (bc->bc_flags & BC_F_COPYIN) { \
1300 error = copyin(ifd->ifd_data, &args, ifd->ifd_len); \
1306 error = (*bc->bc_func)(sc, &args); \
1307 BRIDGE_UNLOCK(sc); \
1311 if (bc->bc_flags & BC_F_COPYOUT) \
1312 error = copyout(&args, ifd->ifd_data, ifd->ifd_len); \
1319 * Handle a control request from the operator.
1322 bridge_ioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
1324 struct bridge_softc
*sc
= ifp
->if_softc
;
1325 struct ifreq
*ifr
= (struct ifreq
*) data
;
1328 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1331 if (_if_brige_debug
)
1332 printf("bridge_ioctl: ifp %p cmd 0x%08lx (%c%c [%lu] %c %lu)\n",
1335 (cmd
& IOC_IN
) ? 'I' : ' ',
1336 (cmd
& IOC_OUT
) ? 'O' : ' ',
1338 (char)IOCGROUP(cmd
),
1346 ifnet_set_flags(ifp
, IFF_UP
, IFF_UP
);
1349 case SIOCGIFMEDIA32
:
1350 case SIOCGIFMEDIA64
:
1358 case SIOCSDRVSPEC32
:
1359 case SIOCGDRVSPEC32
: {
1361 struct ifbreq ifbreq
;
1362 struct ifbifconf32 ifbifconf
;
1363 struct ifbareq32 ifbareq
;
1364 struct ifbaconf32 ifbaconf
;
1365 struct ifbrparam ifbrparam
;
1366 struct ifbropreq32 ifbropreq
;
1368 struct ifdrv32
*ifd
= (struct ifdrv32
*) data
;
1369 const struct bridge_control
*bridge_control_table
= bridge_control_table32
, *bc
;
1375 case SIOCSDRVSPEC64
:
1376 case SIOCGDRVSPEC64
: {
1378 struct ifbreq ifbreq
;
1379 struct ifbifconf64 ifbifconf
;
1380 struct ifbareq64 ifbareq
;
1381 struct ifbaconf64 ifbaconf
;
1382 struct ifbrparam ifbrparam
;
1383 struct ifbropreq64 ifbropreq
;
1385 struct ifdrv64
*ifd
= (struct ifdrv64
*) data
;
1386 const struct bridge_control
*bridge_control_table
= bridge_control_table64
, *bc
;
1394 if (!(ifp
->if_flags
& IFF_UP
) &&
1395 (ifp
->if_flags
& IFF_RUNNING
)) {
1397 * If interface is marked down and it is running,
1398 * then stop and disable it.
1401 bridge_stop(ifp
, 1);
1403 } else if ((ifp
->if_flags
& IFF_UP
) &&
1404 !(ifp
->if_flags
& IFF_RUNNING
)) {
1406 * If interface is marked up and it is stopped, then
1410 error
= bridge_init(ifp
);
1416 error
= ifnet_set_lladdr(ifp
, ifr
->ifr_addr
.sa_data
, ifr
->ifr_addr
.sa_len
);
1418 printf("bridge_ioctl: ifnet_set_lladdr failed %d\n", error
);
1422 /* Do not allow the MTU to be changed on the bridge */
1428 * drop the lock as ether_ioctl() will call bridge_start() and
1429 * cause the lock to be recursed.
1431 error
= ether_ioctl(ifp
, cmd
, data
);
1434 printf("bridge_ioctl: ether_ioctl ifp %p cmd 0x%08lx (%c%c [%lu] %c %lu) failed error: %d\n",
1437 (cmd
& IOC_IN
) ? 'I' : ' ',
1438 (cmd
& IOC_OUT
) ? 'O' : ' ',
1440 (char) IOCGROUP(cmd
),
1443 #endif /* BRIDGE_DEBUG */
1446 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1455 * Clear or restore unwanted capabilities on the member interface
1458 bridge_mutecaps(struct bridge_softc
*sc
)
1460 struct bridge_iflist
*bif
;
1463 /* Initial bitmask of capabilities to test */
1464 mask
= BRIDGE_IFCAPS_MASK
;
1466 TAILQ_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1467 /* Every member must support it or its disabled */
1468 mask
&= bif
->bif_savedcaps
;
1471 TAILQ_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1472 enabled
= bif
->bif_ifp
->if_capenable
;
1473 enabled
&= ~BRIDGE_IFCAPS_STRIP
;
1474 /* strip off mask bits and enable them again if allowed */
1475 enabled
&= ~BRIDGE_IFCAPS_MASK
;
1478 bridge_set_ifcap(sc
, bif
, enabled
);
1484 bridge_set_ifcap(struct bridge_softc
*sc
, struct bridge_iflist
*bif
, int set
)
1486 struct ifnet
*ifp
= bif
->bif_ifp
;
1490 bzero(&ifr
, sizeof(ifr
));
1491 ifr
.ifr_reqcap
= set
;
1493 if (ifp
->if_capenable
!= set
) {
1495 error
= (*ifp
->if_ioctl
)(ifp
, SIOCSIFCAP
, (caddr_t
)&ifr
);
1496 IFF_UNLOCKGIANT(ifp
);
1498 printf("error setting interface capabilities on %s\n",
1499 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
1503 #endif /* HAS_IF_CAP */
1506 * bridge_lookup_member:
1508 * Lookup a bridge member interface.
1510 static struct bridge_iflist
*
1511 bridge_lookup_member(struct bridge_softc
*sc
, const char *name
)
1513 struct bridge_iflist
*bif
;
1515 char if_xname
[IFNAMSIZ
];
1517 BRIDGE_LOCK_ASSERT(sc
);
1519 TAILQ_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1521 snprintf(if_xname
, sizeof(if_xname
), "%s%d",
1522 ifnet_name(ifp
), ifnet_unit(ifp
));
1523 if (strncmp(if_xname
, name
, sizeof(if_xname
)) == 0)
1531 * bridge_lookup_member_if:
1533 * Lookup a bridge member interface by ifnet*.
1535 static struct bridge_iflist
*
1536 bridge_lookup_member_if(struct bridge_softc
*sc
, struct ifnet
*member_ifp
)
1538 struct bridge_iflist
*bif
;
1540 BRIDGE_LOCK_ASSERT(sc
);
1542 TAILQ_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
1543 if (bif
->bif_ifp
== member_ifp
)
1551 bridge_iff_input(void* cookie
, ifnet_t ifp
, __unused protocol_family_t protocol
,
1552 mbuf_t
*data
, char **frame_ptr
)
1555 struct bridge_iflist
*bif
= (struct bridge_iflist
*)cookie
;
1556 struct bridge_softc
*sc
= bif
->bif_sc
;
1561 if ((m
->m_flags
& M_PROTO1
))
1564 if (*frame_ptr
>= (char *)mbuf_datastart(m
) && *frame_ptr
<= (char *)mbuf_data(m
)) {
1566 frmlen
= (char *)mbuf_data(m
) - *frame_ptr
;
1569 if (_if_brige_debug
) {
1570 printf("bridge_iff_input %s%d from %s%d m %p data %p frame %p %s frmlen %lu\n",
1571 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
1572 ifnet_name(ifp
), ifnet_unit(ifp
),
1573 m
, mbuf_data(m
), *frame_ptr
, included
? "inside" : "outside", frmlen
);
1575 if (_if_brige_debug
> 1) {
1576 printf_mbuf(m
, "bridge_iff_input[", "\n");
1577 printf_ether_header((struct ether_header
*)*frame_ptr
);
1578 printf_mbuf_data(m
, 0, 20);
1582 #endif /* BRIDGE_DEBUG */
1584 /* Move data pointer to start of frame to the link layer header */
1586 (void) mbuf_setdata(m
, (char *)mbuf_data(m
) - frmlen
, mbuf_len(m
) + frmlen
);
1587 (void) mbuf_pkthdr_adjustlen(m
, frmlen
);
1589 printf("bridge_iff_input: frame_ptr outside mbuf\n");
1593 error
= bridge_input(ifp
, m
, *frame_ptr
);
1595 /* Adjust packet back to original */
1597 (void) mbuf_setdata(m
, (char *)mbuf_data(m
) + frmlen
, mbuf_len(m
) - frmlen
);
1598 (void) mbuf_pkthdr_adjustlen(m
, -frmlen
);
1601 if (_if_brige_debug
> 1) {
1603 printf_mbuf(m
, "bridge_iff_input]", "\n");
1605 #endif /* BRIDGE_DEBUG */
1608 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1614 #if BRIDGE_MEMBER_OUT_FILTER
1616 bridge_iff_output(void *cookie
, ifnet_t ifp
, __unused protocol_family_t protocol
, mbuf_t
*data
)
1619 struct bridge_iflist
*bif
= (struct bridge_iflist
*)cookie
;
1620 struct bridge_softc
*sc
= bif
->bif_sc
;
1623 if ((m
->m_flags
& M_PROTO1
))
1627 if (_if_brige_debug
) {
1628 printf("bridge_iff_output %s%d from %s%d m %p data %p\n",
1629 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
1630 ifnet_name(ifp
), ifnet_unit(ifp
),
1633 #endif /* BRIDGE_DEBUG */
1635 error
= bridge_output(sc
, ifp
, m
);
1637 printf("bridge_iff_output: bridge_output failed error %d\n", error
);
1641 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
1645 #endif /* BRIDGE_MEMBER_OUT_FILTER */
1649 bridge_iff_event(void* cookie
, ifnet_t ifp
, __unused protocol_family_t protocol
,
1650 const struct kev_msg
*event_msg
)
1652 struct bridge_iflist
*bif
= (struct bridge_iflist
*)cookie
;
1654 if (event_msg
->vendor_code
== KEV_VENDOR_APPLE
&&
1655 event_msg
->kev_class
== KEV_NETWORK_CLASS
&&
1656 event_msg
->kev_subclass
== KEV_DL_SUBCLASS
) {
1657 switch (event_msg
->event_code
) {
1658 case KEV_DL_IF_DETACHING
:
1659 case KEV_DL_IF_DETACHED
:
1660 bridge_ifdetach(bif
, ifp
);
1663 case KEV_DL_LINK_OFF
:
1664 case KEV_DL_LINK_ON
: {
1665 bstp_linkstate(ifp
, event_msg
->event_code
);
1669 case KEV_DL_SIFFLAGS
: {
1670 if (bif
->bif_promisc
== 0 && (ifp
->if_flags
& IFF_UP
)) {
1671 errno_t error
= ifnet_set_promiscuous(ifp
, 1);
1673 printf("bridge_iff_event: ifnet_set_promiscuous(%s%d) failed %d\n",
1674 ifnet_name(ifp
), ifnet_unit(ifp
), error
);
1676 bif
->bif_promisc
= 1;
1689 * bridge_iff_detached:
1691 * Detach an interface from a bridge. Called when a member
1692 * interface is detaching.
1695 bridge_iff_detached(void* cookie
, __unused ifnet_t ifp
)
1697 struct bridge_iflist
*bif
= (struct bridge_iflist
*)cookie
;
1700 printf("bridge_iff_detached: %s%d\n",
1701 ifnet_name(ifp
), ifnet_unit(ifp
));
1704 bridge_ifdetach(bif
, ifp
);
1706 _FREE(bif
, M_DEVBUF
);
1712 bridge_proto_input(ifnet_t ifp
, __unused protocol_family_t protocol
,
1713 __unused mbuf_t packet
, __unused
char *header
)
1715 printf("bridge_proto_input: unexpected packet from %s%d\n",
1716 ifnet_name(ifp
), ifnet_unit(ifp
));
1721 bridge_attach_protocol(struct ifnet
*ifp
)
1724 struct ifnet_attach_proto_param reg
;
1726 printf("bridge_attach_protocol: %s%d\n",
1727 ifnet_name(ifp
), ifnet_unit(ifp
));
1729 bzero(®
, sizeof(reg
));
1730 reg
.input
= bridge_proto_input
;
1732 error
= ifnet_attach_protocol(ifp
, PF_BRIDGE
, ®
);
1734 printf("bridge_attach_protocol: ifnet_attach_protocol(%s%d) failed, %d\n",
1735 ifnet_name(ifp
), ifnet_unit(ifp
), error
);
1741 bridge_detach_protocol(struct ifnet
*ifp
)
1745 printf("bridge_detach_protocol: %s%d\n",
1746 ifnet_name(ifp
), ifnet_unit(ifp
));
1748 error
= ifnet_detach_protocol(ifp
, PF_BRIDGE
);
1750 printf("bridge_attach_protocol: ifnet_detach_protocol(%s%d) failed, %d\n",
1751 ifnet_name(ifp
), ifnet_unit(ifp
), error
);
1757 * bridge_delete_member:
1759 * Delete the specified member interface.
1762 bridge_delete_member(struct bridge_softc
*sc
, struct bridge_iflist
*bif
,
1765 struct ifnet
*ifs
= bif
->bif_ifp
;
1767 BRIDGE_LOCK_ASSERT(sc
);
1770 switch (ifs
->if_type
) {
1774 * Take the interface out of promiscuous mode.
1776 if (bif
->bif_promisc
)
1777 (void) ifnet_set_promiscuous(ifs
, 0);
1785 panic("bridge_delete_member: impossible");
1791 /* reneable any interface capabilities */
1792 bridge_set_ifcap(sc
, bif
, bif
->bif_savedcaps
);
1796 if (bif
->bif_proto_attached
) {
1797 /* Respect lock ordering with DLIL lock */
1799 (void) bridge_detach_protocol(ifs
);
1802 if (bif
->bif_flags
& IFBIF_STP
)
1803 bstp_disable(&bif
->bif_stp
);
1805 ifs
->if_bridge
= NULL
;
1807 TAILQ_REMOVE(&sc
->sc_iflist
, bif
, bif_next
);
1813 bridge_mutecaps(sc
); /* recalcuate now this interface is removed */
1814 #endif /* HAS_IF_CAP */
1815 bridge_rtdelete(sc
, ifs
, IFBF_FLUSHALL
);
1816 KASSERT(bif
->bif_addrcnt
== 0,
1817 ("%s: %d bridge routes referenced", __func__
, bif
->bif_addrcnt
));
1820 bstp_destroy(&bif
->bif_stp
); /* prepare to free */
1823 if (bif
->bif_filter_attached
) {
1824 /* Respect lock ordering with DLIL lock */
1826 iflt_detach(bif
->bif_iff_ref
);
1829 _FREE(bif
, M_DEVBUF
);
1834 * bridge_delete_span:
1836 * Delete the specified span interface.
1839 bridge_delete_span(struct bridge_softc
*sc
, struct bridge_iflist
*bif
)
1841 BRIDGE_LOCK_ASSERT(sc
);
1843 KASSERT(bif
->bif_ifp
->if_bridge
== NULL
,
1844 ("%s: not a span interface", __func__
));
1846 ifnet_release(bif
->bif_ifp
);
1848 TAILQ_REMOVE(&sc
->sc_spanlist
, bif
, bif_next
);
1849 _FREE(bif
, M_DEVBUF
);
1853 bridge_ioctl_add(struct bridge_softc
*sc
, void *arg
)
1855 struct ifbreq
*req
= arg
;
1856 struct bridge_iflist
*bif
= NULL
;
1859 struct iff_filter iff
;
1861 ifs
= ifunit(req
->ifbr_ifsname
);
1864 if (ifs
->if_ioctl
== NULL
) /* must be supported */
1867 /* If it's in the span list, it can't be a member. */
1868 TAILQ_FOREACH(bif
, &sc
->sc_spanlist
, bif_next
)
1869 if (ifs
== bif
->bif_ifp
)
1872 /* Allow the first Ethernet member to define the MTU */
1873 if (ifs
->if_type
!= IFT_GIF
) {
1874 if (TAILQ_EMPTY(&sc
->sc_iflist
))
1875 sc
->sc_ifp
->if_mtu
= ifs
->if_mtu
;
1876 else if (sc
->sc_ifp
->if_mtu
!= ifs
->if_mtu
) {
1877 printf("%s%d: invalid MTU for %s%d",
1878 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
1879 ifnet_name(ifs
), ifnet_unit(ifs
));
1884 if (ifs
->if_bridge
== sc
)
1887 if (ifs
->if_bridge
!= NULL
)
1890 bif
= _MALLOC(sizeof(*bif
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
1895 bif
->bif_flags
= IFBIF_LEARNING
| IFBIF_DISCOVER
;
1897 bif
->bif_savedcaps
= ifs
->if_capenable
;
1898 #endif /* HAS_IF_CAP */
1901 ifnet_reference(ifs
);
1903 ifs
->if_bridge
= sc
;
1904 bstp_create(&sc
->sc_stp
, &bif
->bif_stp
, bif
->bif_ifp
);
1906 * XXX: XLOCK HERE!?!
1908 TAILQ_INSERT_TAIL(&sc
->sc_iflist
, bif
, bif_next
);
1911 /* Set interface capabilities to the intersection set of all members */
1912 bridge_mutecaps(sc
);
1913 #endif /* HAS_IF_CAP */
1916 switch (ifs
->if_type
) {
1920 * Place the interface into promiscuous mode.
1922 error
= ifnet_set_promiscuous(ifs
, 1);
1924 /* Ignore error when device is not up */
1925 if (error
!= ENETDOWN
)
1929 bif
->bif_promisc
= 1;
1942 * Respect lock ordering with DLIL lock for the following operations
1947 * install an interface filter
1949 memset(&iff
, 0, sizeof(struct iff_filter
));
1950 iff
.iff_cookie
= bif
;
1951 iff
.iff_name
= "com.apple.kernel.bsd.net.if_bridge";
1952 iff
.iff_input
= bridge_iff_input
;
1953 #if BRIDGE_MEMBER_OUT_FILTER
1954 iff
.iff_output
= bridge_iff_output
;
1955 #endif /* BRIDGE_MEMBER_OUT_FILTER */
1956 iff
.iff_event
= bridge_iff_event
;
1957 iff
.iff_detached
= bridge_iff_detached
;
1958 error
= iflt_attach(ifs
, &iff
, &bif
->bif_iff_ref
);
1960 printf("bridge_ioctl_add: iflt_attach failed %d\n", error
);
1964 bif
->bif_filter_attached
= 1;
1967 * install an dummy "bridge" protocol
1969 if ((error
= bridge_attach_protocol(ifs
)) != 0) {
1971 printf("bridge_ioctl_add: bridge_attach_protocol failed %d\n", error
);
1976 bif
->bif_proto_attached
= 1;
1981 if (error
&& bif
!= NULL
)
1982 bridge_delete_member(sc
, bif
, 1);
1988 bridge_ioctl_del(struct bridge_softc
*sc
, void *arg
)
1990 struct ifbreq
*req
= arg
;
1991 struct bridge_iflist
*bif
;
1993 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
1997 bridge_delete_member(sc
, bif
, 0);
2003 bridge_ioctl_purge(__unused
struct bridge_softc
*sc
, __unused
void *arg
)
2009 bridge_ioctl_gifflags(struct bridge_softc
*sc
, void *arg
)
2011 struct ifbreq
*req
= arg
;
2012 struct bridge_iflist
*bif
;
2013 struct bstp_port
*bp
;
2015 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
2020 req
->ifbr_ifsflags
= bif
->bif_flags
;
2021 req
->ifbr_state
= bp
->bp_state
;
2022 req
->ifbr_priority
= bp
->bp_priority
;
2023 req
->ifbr_path_cost
= bp
->bp_path_cost
;
2024 req
->ifbr_portno
= bif
->bif_ifp
->if_index
& 0xfff;
2025 req
->ifbr_proto
= bp
->bp_protover
;
2026 req
->ifbr_role
= bp
->bp_role
;
2027 req
->ifbr_stpflags
= bp
->bp_flags
;
2028 req
->ifbr_addrcnt
= bif
->bif_addrcnt
;
2029 req
->ifbr_addrmax
= bif
->bif_addrmax
;
2030 req
->ifbr_addrexceeded
= bif
->bif_addrexceeded
;
2032 /* Copy STP state options as flags */
2033 if (bp
->bp_operedge
)
2034 req
->ifbr_ifsflags
|= IFBIF_BSTP_EDGE
;
2035 if (bp
->bp_flags
& BSTP_PORT_AUTOEDGE
)
2036 req
->ifbr_ifsflags
|= IFBIF_BSTP_AUTOEDGE
;
2037 if (bp
->bp_ptp_link
)
2038 req
->ifbr_ifsflags
|= IFBIF_BSTP_PTP
;
2039 if (bp
->bp_flags
& BSTP_PORT_AUTOPTP
)
2040 req
->ifbr_ifsflags
|= IFBIF_BSTP_AUTOPTP
;
2041 if (bp
->bp_flags
& BSTP_PORT_ADMEDGE
)
2042 req
->ifbr_ifsflags
|= IFBIF_BSTP_ADMEDGE
;
2043 if (bp
->bp_flags
& BSTP_PORT_ADMCOST
)
2044 req
->ifbr_ifsflags
|= IFBIF_BSTP_ADMCOST
;
2049 bridge_ioctl_sifflags(struct bridge_softc
*sc
, void *arg
)
2051 struct ifbreq
*req
= arg
;
2052 struct bridge_iflist
*bif
;
2053 struct bstp_port
*bp
;
2056 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
2061 if (req
->ifbr_ifsflags
& IFBIF_SPAN
)
2062 /* SPAN is readonly */
2066 if (req
->ifbr_ifsflags
& IFBIF_STP
) {
2067 if ((bif
->bif_flags
& IFBIF_STP
) == 0) {
2068 error
= bstp_enable(&bif
->bif_stp
);
2073 if ((bif
->bif_flags
& IFBIF_STP
) != 0)
2074 bstp_disable(&bif
->bif_stp
);
2077 /* Pass on STP flags */
2078 bstp_set_edge(bp
, req
->ifbr_ifsflags
& IFBIF_BSTP_EDGE
? 1 : 0);
2079 bstp_set_autoedge(bp
, req
->ifbr_ifsflags
& IFBIF_BSTP_AUTOEDGE
? 1 : 0);
2080 bstp_set_ptp(bp
, req
->ifbr_ifsflags
& IFBIF_BSTP_PTP
? 1 : 0);
2081 bstp_set_autoptp(bp
, req
->ifbr_ifsflags
& IFBIF_BSTP_AUTOPTP
? 1 : 0);
2083 /* Save the bits relating to the bridge */
2084 bif
->bif_flags
= req
->ifbr_ifsflags
& IFBIFMASK
;
2091 bridge_ioctl_scache(struct bridge_softc
*sc
, void *arg
)
2093 struct ifbrparam
*param
= arg
;
2095 sc
->sc_brtmax
= param
->ifbrp_csize
;
2102 bridge_ioctl_gcache(struct bridge_softc
*sc
, void *arg
)
2104 struct ifbrparam
*param
= arg
;
2106 param
->ifbrp_csize
= sc
->sc_brtmax
;
2112 #define BRIDGE_IOCTL_GIFS do { \
2113 struct bridge_iflist *bif; \
2114 struct ifbreq breq; \
2115 char *buf, *outbuf; \
2116 unsigned int count, buflen, len; \
2119 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) \
2121 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next) \
2124 buflen = sizeof(breq) * count; \
2125 if (bifc->ifbic_len == 0) { \
2126 bifc->ifbic_len = buflen; \
2129 BRIDGE_UNLOCK(sc); \
2130 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
2135 len = min(bifc->ifbic_len, buflen); \
2136 bzero(&breq, sizeof(breq)); \
2137 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
2138 if (len < sizeof(breq)) \
2141 snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), "%s%d", \
2142 ifnet_name(bif->bif_ifp), ifnet_unit(bif->bif_ifp)); \
2143 /* Fill in the ifbreq structure */ \
2144 error = bridge_ioctl_gifflags(sc, &breq); \
2147 memcpy(buf, &breq, sizeof(breq)); \
2149 buf += sizeof(breq); \
2150 len -= sizeof(breq); \
2152 TAILQ_FOREACH(bif, &sc->sc_spanlist, bif_next) { \
2153 if (len < sizeof(breq)) \
2156 snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), "%s%d", \
2157 ifnet_name(bif->bif_ifp), ifnet_unit(bif->bif_ifp)); \
2158 breq.ifbr_ifsflags = bif->bif_flags; \
2159 breq.ifbr_portno = bif->bif_ifp->if_index & 0xfff; \
2160 memcpy(buf, &breq, sizeof(breq)); \
2162 buf += sizeof(breq); \
2163 len -= sizeof(breq); \
2166 BRIDGE_UNLOCK(sc); \
2167 bifc->ifbic_len = sizeof(breq) * count; \
2168 error = copyout(outbuf, bifc->ifbic_req, bifc->ifbic_len); \
2170 _FREE(outbuf, M_TEMP); \
2174 bridge_ioctl_gifs64(struct bridge_softc
*sc
, void *arg
)
2176 struct ifbifconf64
*bifc
= arg
;
2185 bridge_ioctl_gifs32(struct bridge_softc
*sc
, void *arg
)
2187 struct ifbifconf32
*bifc
= arg
;
2196 #define BRIDGE_IOCTL_RTS do { \
2197 struct bridge_rtnode *brt; \
2198 char *buf, *outbuf; \
2199 unsigned int count, buflen, len; \
2200 struct timespec now; \
2202 if (bac->ifbac_len == 0) \
2206 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) \
2208 buflen = sizeof(bareq) * count; \
2210 BRIDGE_UNLOCK(sc); \
2211 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
2216 len = min(bac->ifbac_len, buflen); \
2217 bzero(&bareq, sizeof(bareq)); \
2218 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { \
2219 if (len < sizeof(bareq)) \
2221 snprintf(bareq.ifba_ifsname, sizeof(bareq.ifba_ifsname), "%s%d", \
2222 ifnet_name(brt->brt_ifp), ifnet_unit(brt->brt_ifp)); \
2223 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr)); \
2224 bareq.ifba_vlan = brt->brt_vlan; \
2225 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { \
2227 if ((unsigned long)now.tv_sec < brt->brt_expire) \
2228 bareq.ifba_expire = brt->brt_expire - now.tv_sec; \
2230 bareq.ifba_expire = 0; \
2231 bareq.ifba_flags = brt->brt_flags; \
2233 memcpy(buf, &bareq, sizeof(bareq)); \
2235 buf += sizeof(bareq); \
2236 len -= sizeof(bareq); \
2239 BRIDGE_UNLOCK(sc); \
2240 bac->ifbac_len = sizeof(bareq) * count; \
2241 error = copyout(outbuf, bac->ifbac_req, bac->ifbac_len); \
2243 _FREE(outbuf, M_TEMP); \
2248 bridge_ioctl_rts64(struct bridge_softc
*sc
, void *arg
)
2250 struct ifbaconf64
*bac
= arg
;
2251 struct ifbareq64 bareq
;
2260 bridge_ioctl_rts32(struct bridge_softc
*sc
, void *arg
)
2262 struct ifbaconf32
*bac
= arg
;
2263 struct ifbareq32 bareq
;
2272 bridge_ioctl_saddr32(struct bridge_softc
*sc
, void *arg
)
2274 struct ifbareq32
*req
= arg
;
2275 struct bridge_iflist
*bif
;
2278 bif
= bridge_lookup_member(sc
, req
->ifba_ifsname
);
2282 error
= bridge_rtupdate(sc
, req
->ifba_dst
, req
->ifba_vlan
, bif
, 1,
2289 bridge_ioctl_saddr64(struct bridge_softc
*sc
, void *arg
)
2291 struct ifbareq64
*req
= arg
;
2292 struct bridge_iflist
*bif
;
2295 bif
= bridge_lookup_member(sc
, req
->ifba_ifsname
);
2299 error
= bridge_rtupdate(sc
, req
->ifba_dst
, req
->ifba_vlan
, bif
, 1,
2306 bridge_ioctl_sto(struct bridge_softc
*sc
, void *arg
)
2308 struct ifbrparam
*param
= arg
;
2310 sc
->sc_brttimeout
= param
->ifbrp_ctime
;
2315 bridge_ioctl_gto(struct bridge_softc
*sc
, void *arg
)
2317 struct ifbrparam
*param
= arg
;
2319 param
->ifbrp_ctime
= sc
->sc_brttimeout
;
2324 bridge_ioctl_daddr32(struct bridge_softc
*sc
, void *arg
)
2326 struct ifbareq32
*req
= arg
;
2328 return (bridge_rtdaddr(sc
, req
->ifba_dst
, req
->ifba_vlan
));
2332 bridge_ioctl_daddr64(struct bridge_softc
*sc
, void *arg
)
2334 struct ifbareq64
*req
= arg
;
2336 return (bridge_rtdaddr(sc
, req
->ifba_dst
, req
->ifba_vlan
));
2340 bridge_ioctl_flush(struct bridge_softc
*sc
, void *arg
)
2342 struct ifbreq
*req
= arg
;
2344 bridge_rtflush(sc
, req
->ifbr_ifsflags
);
2349 bridge_ioctl_gpri(struct bridge_softc
*sc
, void *arg
)
2351 struct ifbrparam
*param
= arg
;
2352 struct bstp_state
*bs
= &sc
->sc_stp
;
2354 param
->ifbrp_prio
= bs
->bs_bridge_priority
;
2359 bridge_ioctl_spri(struct bridge_softc
*sc
, void *arg
)
2361 struct ifbrparam
*param
= arg
;
2363 return (bstp_set_priority(&sc
->sc_stp
, param
->ifbrp_prio
));
2367 bridge_ioctl_ght(struct bridge_softc
*sc
, void *arg
)
2369 struct ifbrparam
*param
= arg
;
2370 struct bstp_state
*bs
= &sc
->sc_stp
;
2372 param
->ifbrp_hellotime
= bs
->bs_bridge_htime
>> 8;
2377 bridge_ioctl_sht(struct bridge_softc
*sc
, void *arg
)
2379 struct ifbrparam
*param
= arg
;
2381 return (bstp_set_htime(&sc
->sc_stp
, param
->ifbrp_hellotime
));
2385 bridge_ioctl_gfd(struct bridge_softc
*sc
, void *arg
)
2387 struct ifbrparam
*param
= arg
;
2388 struct bstp_state
*bs
= &sc
->sc_stp
;
2390 param
->ifbrp_fwddelay
= bs
->bs_bridge_fdelay
>> 8;
2395 bridge_ioctl_sfd(struct bridge_softc
*sc
, void *arg
)
2397 struct ifbrparam
*param
= arg
;
2399 return (bstp_set_fdelay(&sc
->sc_stp
, param
->ifbrp_fwddelay
));
2403 bridge_ioctl_gma(struct bridge_softc
*sc
, void *arg
)
2405 struct ifbrparam
*param
= arg
;
2406 struct bstp_state
*bs
= &sc
->sc_stp
;
2408 param
->ifbrp_maxage
= bs
->bs_bridge_max_age
>> 8;
2413 bridge_ioctl_sma(struct bridge_softc
*sc
, void *arg
)
2415 struct ifbrparam
*param
= arg
;
2417 return (bstp_set_maxage(&sc
->sc_stp
, param
->ifbrp_maxage
));
2421 bridge_ioctl_sifprio(struct bridge_softc
*sc
, void *arg
)
2423 struct ifbreq
*req
= arg
;
2424 struct bridge_iflist
*bif
;
2426 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
2430 return (bstp_set_port_priority(&bif
->bif_stp
, req
->ifbr_priority
));
2434 bridge_ioctl_sifcost(struct bridge_softc
*sc
, void *arg
)
2436 struct ifbreq
*req
= arg
;
2437 struct bridge_iflist
*bif
;
2439 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
2443 return (bstp_set_path_cost(&bif
->bif_stp
, req
->ifbr_path_cost
));
2447 bridge_ioctl_gfilt(struct bridge_softc
*sc
, void *arg
)
2449 struct ifbrparam
*param
= arg
;
2451 param
->ifbrp_filter
= sc
->sc_filter_flags
;
2457 bridge_ioctl_sfilt(struct bridge_softc
*sc
, void *arg
)
2459 struct ifbrparam
*param
= arg
;
2461 if (param
->ifbrp_filter
& ~IFBF_FILT_MASK
)
2465 if (param
->ifbrp_filter
& IFBF_FILT_USEIPF
)
2469 sc
->sc_filter_flags
= param
->ifbrp_filter
;
2475 bridge_ioctl_sifmaxaddr(struct bridge_softc
*sc
, void *arg
)
2477 struct ifbreq
*req
= arg
;
2478 struct bridge_iflist
*bif
;
2480 bif
= bridge_lookup_member(sc
, req
->ifbr_ifsname
);
2484 bif
->bif_addrmax
= req
->ifbr_addrmax
;
2489 bridge_ioctl_addspan(struct bridge_softc
*sc
, void *arg
)
2491 struct ifbreq
*req
= arg
;
2492 struct bridge_iflist
*bif
= NULL
;
2495 ifs
= ifunit(req
->ifbr_ifsname
);
2499 TAILQ_FOREACH(bif
, &sc
->sc_spanlist
, bif_next
)
2500 if (ifs
== bif
->bif_ifp
)
2503 if (ifs
->if_bridge
!= NULL
)
2506 switch (ifs
->if_type
) {
2515 bif
= _MALLOC(sizeof(*bif
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
2520 bif
->bif_flags
= IFBIF_SPAN
;
2522 ifnet_reference(bif
->bif_ifp
);
2524 TAILQ_INSERT_HEAD(&sc
->sc_spanlist
, bif
, bif_next
);
2530 bridge_ioctl_delspan(struct bridge_softc
*sc
, void *arg
)
2532 struct ifbreq
*req
= arg
;
2533 struct bridge_iflist
*bif
;
2536 ifs
= ifunit(req
->ifbr_ifsname
);
2540 TAILQ_FOREACH(bif
, &sc
->sc_spanlist
, bif_next
)
2541 if (ifs
== bif
->bif_ifp
)
2547 bridge_delete_span(sc
, bif
);
2552 #define BRIDGE_IOCTL_GBPARAM do { \
2553 struct bstp_state *bs = &sc->sc_stp; \
2554 struct bstp_port *root_port; \
2556 req->ifbop_maxage = bs->bs_bridge_max_age >> 8; \
2557 req->ifbop_hellotime = bs->bs_bridge_htime >> 8; \
2558 req->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8; \
2560 root_port = bs->bs_root_port; \
2561 if (root_port == NULL) \
2562 req->ifbop_root_port = 0; \
2564 req->ifbop_root_port = root_port->bp_ifp->if_index; \
2566 req->ifbop_holdcount = bs->bs_txholdcount; \
2567 req->ifbop_priority = bs->bs_bridge_priority; \
2568 req->ifbop_protocol = bs->bs_protover; \
2569 req->ifbop_root_path_cost = bs->bs_root_pv.pv_cost; \
2570 req->ifbop_bridgeid = bs->bs_bridge_pv.pv_dbridge_id; \
2571 req->ifbop_designated_root = bs->bs_root_pv.pv_root_id; \
2572 req->ifbop_designated_bridge = bs->bs_root_pv.pv_dbridge_id; \
2573 req->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec; \
2574 req->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec; \
2578 bridge_ioctl_gbparam32(struct bridge_softc
*sc
, void *arg
)
2580 struct ifbropreq32
*req
= arg
;
2582 BRIDGE_IOCTL_GBPARAM
;
2588 bridge_ioctl_gbparam64(struct bridge_softc
*sc
, void *arg
)
2590 struct ifbropreq64
*req
= arg
;
2592 BRIDGE_IOCTL_GBPARAM
;
2599 bridge_ioctl_grte(struct bridge_softc
*sc
, void *arg
)
2601 struct ifbrparam
*param
= arg
;
2603 param
->ifbrp_cexceeded
= sc
->sc_brtexceeded
;
2607 #define BRIDGE_IOCTL_GIFSSTP do { \
2608 struct bridge_iflist *bif; \
2609 struct bstp_port *bp; \
2610 struct ifbpstpreq bpreq; \
2611 char *buf, *outbuf; \
2612 unsigned int count, buflen, len; \
2615 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
2616 if ((bif->bif_flags & IFBIF_STP) != 0) \
2620 buflen = sizeof(bpreq) * count; \
2621 if (bifstp->ifbpstp_len == 0) { \
2622 bifstp->ifbpstp_len = buflen; \
2626 BRIDGE_UNLOCK(sc); \
2627 outbuf = _MALLOC(buflen, M_TEMP, M_WAITOK | M_ZERO); \
2632 len = min(bifstp->ifbpstp_len, buflen); \
2633 bzero(&bpreq, sizeof(bpreq)); \
2634 TAILQ_FOREACH(bif, &sc->sc_iflist, bif_next) { \
2635 if (len < sizeof(bpreq)) \
2638 if ((bif->bif_flags & IFBIF_STP) == 0) \
2641 bp = &bif->bif_stp; \
2642 bpreq.ifbp_portno = bif->bif_ifp->if_index & 0xfff; \
2643 bpreq.ifbp_fwd_trans = bp->bp_forward_transitions; \
2644 bpreq.ifbp_design_cost = bp->bp_desg_pv.pv_cost; \
2645 bpreq.ifbp_design_port = bp->bp_desg_pv.pv_port_id; \
2646 bpreq.ifbp_design_bridge = bp->bp_desg_pv.pv_dbridge_id; \
2647 bpreq.ifbp_design_root = bp->bp_desg_pv.pv_root_id; \
2649 memcpy(buf, &bpreq, sizeof(bpreq)); \
2651 buf += sizeof(bpreq); \
2652 len -= sizeof(bpreq); \
2655 BRIDGE_UNLOCK(sc); \
2656 bifstp->ifbpstp_len = sizeof(bpreq) * count; \
2657 error = copyout(outbuf, bifstp->ifbpstp_req, bifstp->ifbpstp_len); \
2659 _FREE(outbuf, M_TEMP); \
2664 bridge_ioctl_gifsstp32(struct bridge_softc
*sc
, void *arg
)
2666 struct ifbpstpconf32
*bifstp
= arg
;
2669 BRIDGE_IOCTL_GIFSSTP
;
2675 bridge_ioctl_gifsstp64(struct bridge_softc
*sc
, void *arg
)
2677 struct ifbpstpconf64
*bifstp
= arg
;
2680 BRIDGE_IOCTL_GIFSSTP
;
2686 bridge_ioctl_sproto(struct bridge_softc
*sc
, void *arg
)
2688 struct ifbrparam
*param
= arg
;
2690 return (bstp_set_protocol(&sc
->sc_stp
, param
->ifbrp_proto
));
2694 bridge_ioctl_stxhc(struct bridge_softc
*sc
, void *arg
)
2696 struct ifbrparam
*param
= arg
;
2698 return (bstp_set_holdcount(&sc
->sc_stp
, param
->ifbrp_txhc
));
2704 * Detach an interface from a bridge. Called when a member
2705 * interface is detaching.
2707 __private_extern__
void
2708 bridge_ifdetach(struct bridge_iflist
*bif
, struct ifnet
*ifp
)
2710 struct bridge_softc
*sc
= ifp
->if_bridge
;
2713 printf("bridge_ifdetach %s%d\n", ifnet_name(ifp
), ifnet_unit(ifp
));
2716 /* Check if the interface is a bridge member */
2720 bif
= bridge_lookup_member_if(sc
, ifp
);
2722 bridge_delete_member(sc
, bif
, 1);
2728 /* Check if the interface is a span port */
2729 lck_mtx_lock(bridge_list_mtx
);
2730 LIST_FOREACH(sc
, &bridge_list
, sc_list
) {
2732 TAILQ_FOREACH(bif
, &sc
->sc_spanlist
, bif_next
)
2733 if (ifp
== bif
->bif_ifp
) {
2734 bridge_delete_span(sc
, bif
);
2740 lck_mtx_unlock(bridge_list_mtx
);
2746 * Initialize a bridge interface.
2749 bridge_init(struct ifnet
*ifp
)
2751 struct bridge_softc
*sc
= (struct bridge_softc
*)ifp
->if_softc
;
2755 BRIDGE_LOCK_ASSERT(sc
);
2757 if ((ifnet_flags(ifp
) & IFF_RUNNING
))
2760 ts
.tv_sec
= bridge_rtable_prune_period
;
2762 bsd_timeout(bridge_timer
, sc
, &ts
);
2764 error
= ifnet_set_flags(ifp
, IFF_RUNNING
, IFF_RUNNING
);
2766 bstp_init(&sc
->sc_stp
); /* Initialize Spanning Tree */
2774 * Stop the bridge interface.
2777 bridge_stop(struct ifnet
*ifp
, __unused
int disable
)
2779 struct bridge_softc
*sc
= ifp
->if_softc
;
2781 BRIDGE_LOCK_ASSERT(sc
);
2783 if ((ifnet_flags(ifp
) & IFF_RUNNING
) == 0)
2786 bsd_untimeout(bridge_timer
, sc
);
2787 bstp_stop(&sc
->sc_stp
);
2789 bridge_rtflush(sc
, IFBF_FLUSHDYN
);
2791 (void) ifnet_set_flags(ifp
, 0, IFF_RUNNING
);
2797 * Enqueue a packet on a bridge member interface.
2801 bridge_enqueue(struct bridge_softc
*sc
, struct ifnet
*dst_ifp
, struct mbuf
*m
)
2807 /* We may be sending a fragment so traverse the mbuf */
2810 m
->m_nextpkt
= NULL
;
2812 len
= m
->m_pkthdr
.len
;
2813 mflags
= m
->m_flags
;
2814 m
->m_flags
|= M_PROTO1
; //set to avoid loops
2818 * If underlying interface can not do VLAN tag insertion itself
2819 * then attach a packet tag that holds it.
2821 if ((m
->m_flags
& M_VLANTAG
) &&
2822 (dst_ifp
->if_capenable
& IFCAP_VLAN_HWTAGGING
) == 0) {
2823 m
= ether_vlanencap(m
, m
->m_pkthdr
.ether_vtag
);
2825 printf("%s%d: unable to prepend VLAN header\n",
2826 ifnet_name(dst_ifp
), ifnet_unit(dst_ifp
));
2827 (void) ifnet_stat_increment_out(dst_ifp
, 0, 0, 1);
2830 m
->m_flags
&= ~M_VLANTAG
;
2832 #endif /* HAS_IF_CAP */
2834 error
= ifnet_output_raw(dst_ifp
, 0, m
);
2836 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 1, len
, 0);
2838 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 0, 0, 1);
2845 #if HAS_BRIDGE_DUMMYNET
2849 * Receive a queued packet from dummynet and pass it on to the output
2852 * The mbuf has the Ethernet header already attached.
2855 bridge_dummynet(struct mbuf
*m
, struct ifnet
*ifp
)
2857 struct bridge_softc
*sc
;
2859 sc
= ifp
->if_bridge
;
2862 * The packet didnt originate from a member interface. This should only
2863 * ever happen if a member interface is removed while packets are
2871 if (PFIL_HOOKED(&inet_pfil_hook
)
2873 || PFIL_HOOKED(&inet6_pfil_hook
)
2876 if (bridge_pfil(&m
, sc
->sc_ifp
, ifp
, PFIL_OUT
) != 0)
2882 bridge_enqueue(sc
, ifp
, m
);
2884 #endif /* HAS_BRIDGE_DUMMYNET */
2886 #if BRIDGE_MEMBER_OUT_FILTER
2890 * Send output from a bridge member interface. This
2891 * performs the bridging function for locally originated
2894 * The mbuf has the Ethernet header already attached. We must
2895 * enqueue or free the mbuf before returning.
2898 bridge_output(struct ifnet
*ifp
, struct mbuf
*m
, __unused
struct sockaddr
*sa
,
2899 __unused
struct rtentry
*rt
)
2901 struct ether_header
*eh
;
2902 struct ifnet
*dst_if
;
2903 struct bridge_softc
*sc
;
2907 if (_if_brige_debug
)
2908 printf("bridge_output ifp %p %s%d\n", ifp
, ifnet_name(ifp
), ifnet_unit(ifp
));
2909 #endif /* BRIDGE_DEBUG */
2911 if (m
->m_len
< ETHER_HDR_LEN
) {
2912 m
= m_pullup(m
, ETHER_HDR_LEN
);
2917 eh
= mtod(m
, struct ether_header
*);
2918 sc
= ifp
->if_bridge
;
2919 vlan
= VLANTAGOF(m
);
2923 /* APPLE MODIFICATION
2924 * If the packet is an 802.1X ethertype, then only send on the
2925 * original output interface.
2927 if (eh
->ether_type
== htons(ETHERTYPE_PAE
)) {
2933 * If bridge is down, but the original output interface is up,
2934 * go ahead and send out that interface. Otherwise, the packet
2937 if ((sc
->sc_ifp
->if_flags
& IFF_RUNNING
) == 0) {
2943 * If the packet is a multicast, or we don't know a better way to
2944 * get there, send to all interfaces.
2946 if (ETHER_IS_MULTICAST(eh
->ether_dhost
))
2949 dst_if
= bridge_rtlookup(sc
, eh
->ether_dhost
, vlan
);
2950 if (dst_if
== NULL
) {
2951 struct bridge_iflist
*bif
;
2953 int error
= 0, used
= 0;
2957 BRIDGE_LOCK2REF(sc
, error
);
2963 TAILQ_FOREACH(bif
, &sc
->sc_iflist
, bif_next
) {
2964 dst_if
= bif
->bif_ifp
;
2966 if (dst_if
->if_type
== IFT_GIF
)
2968 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
2972 * If this is not the original output interface,
2973 * and the interface is participating in spanning
2974 * tree, make sure the port is in a state that
2975 * allows forwarding.
2977 if (dst_if
!= ifp
&& (bif
->bif_flags
& IFBIF_STP
) &&
2978 bif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
)
2981 if (LIST_NEXT(bif
, bif_next
) == NULL
) {
2985 mc
= m_copypacket(m
, M_DONTWAIT
);
2987 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 0, 0, 1);
2992 bridge_enqueue(sc
, dst_if
, mc
);
3002 * XXX Spanning tree consideration here?
3006 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0) {
3013 bridge_enqueue(sc
, dst_if
, m
);
3016 #endif /* BRIDGE_MEMBER_OUT_FILTER */
3018 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
3019 static struct mbuf
* bridge_fix_txcsum( struct mbuf
*m
)
3021 // basic tests indicate that the vast majority of packets being processed
3022 // here have an Ethernet header mbuf pre-pended to them (the first case below)
3023 // the second highest are those where the Ethernet and IP/TCP/UDP headers are
3024 // all in one mbuf (second case below)
3025 // the third case has, in fact, never hit for me -- although if I comment out
3026 // the first two cases, that code works for them, so I consider it a
3027 // decent general solution
3029 int amt
= ETHER_HDR_LEN
;
3030 int hlen
= M_CSUM_DATA_IPv4_IPHL( m
->m_pkthdr
.csum_data
);
3031 int off
= M_CSUM_DATA_IPv4_OFFSET( m
->m_pkthdr
.csum_data
);
3034 * NOTE we should never get vlan-attached packets here;
3035 * support for those COULD be added, but we don't use them
3036 * and it really kinda slows things down to worry about them
3040 if ( m_tag_find( m
, PACKET_TAG_VLAN
, NULL
) != NULL
)
3042 printf( "bridge: transmitting packet tagged with VLAN?\n" );
3049 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_IPv4
)
3053 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_TCPv4
)
3055 amt
+= off
+ sizeof( uint16_t );
3058 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_UDPv4
)
3060 amt
+= off
+ sizeof( uint16_t );
3063 if ( m
->m_len
== ETHER_HDR_LEN
)
3065 // this is the case where there's an Ethernet header in an mbuf
3067 // the first mbuf is the Ethernet header -- just strip it off and do the checksum
3068 struct mbuf
*m_ip
= m
->m_next
;
3070 // set up m_ip so the cksum operations work
3071 /* APPLE MODIFICATION 22 Apr 2008 <mvega@apple.com>
3072 * <rdar://5817385> Clear the m_tag list before setting
3075 * If this m_buf chain was extended via M_PREPEND(), then
3076 * m_ip->m_pkthdr is identical to m->m_pkthdr (see
3077 * M_MOVE_PKTHDR()). The only thing preventing access to this
3078 * invalid packet header data is the fact that the M_PKTHDR
3079 * flag is clear, i.e., m_ip->m_flag & M_PKTHDR == 0, but we're
3080 * about to set the M_PKTHDR flag, so to be safe we initialize,
3081 * more accurately, we clear, m_ip->m_pkthdr.tags via
3084 * Suppose that we do not do this; if m_pullup(), below, fails,
3085 * then m_ip will be freed along with m_ip->m_pkthdr.tags, but
3086 * we will also free m soon after, via m_freem(), and
3087 * consequently attempt to free m->m_pkthdr.tags in the
3088 * process. The problem is that m->m_pkthdr.tags will have
3089 * already been freed by virtue of being equal to
3090 * m_ip->m_pkthdr.tags. Attempts to dereference
3091 * m->m_pkthdr.tags in m_tag_delete_chain() will result in a
3095 /* END MODIFICATION */
3096 m_ip
->m_flags
|= M_PKTHDR
;
3097 m_ip
->m_pkthdr
.csum_flags
= m
->m_pkthdr
.csum_flags
;
3098 m_ip
->m_pkthdr
.csum_data
= m
->m_pkthdr
.csum_data
;
3099 m_ip
->m_pkthdr
.len
= m
->m_pkthdr
.len
- ETHER_HDR_LEN
;
3101 // set up the header mbuf so we can prepend it back on again later
3102 m
->m_pkthdr
.csum_flags
= 0;
3103 m
->m_pkthdr
.csum_data
= 0;
3104 m
->m_pkthdr
.len
= ETHER_HDR_LEN
;
3108 // now do the checksums we need -- first IP
3109 if ( m_ip
->m_pkthdr
.csum_flags
& M_CSUM_IPv4
)
3111 // make sure the IP header (or at least the part with the cksum) is there
3112 m_ip
= m_pullup( m_ip
, sizeof( struct ip
) );
3115 printf( "bridge: failed to flatten header\n ");
3120 // now do the checksum
3122 struct ip
*ip
= mtod( m_ip
, struct ip
* );
3123 ip
->ip_sum
= in_cksum( m_ip
, hlen
);
3125 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3126 printf( "bridge: performed IPv4 checksum\n" );
3131 // now do a TCP or UDP delayed checksum
3132 if ( m_ip
->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
) )
3134 in_delayed_cksum( m_ip
);
3136 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3137 printf( "bridge: performed TCPv4/UDPv4 checksum\n" );
3141 // now attach the ethernet header back onto the IP packet
3143 m
->m_pkthdr
.len
+= m_length( m_ip
);
3145 // clear the M_PKTHDR flags on the ip packet (again, we re-attach later)
3146 m_ip
->m_flags
&= ~M_PKTHDR
;
3148 // and clear any csum flags
3149 m
->m_pkthdr
.csum_flags
&= ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
|M_CSUM_IPv4
);
3151 else if ( m
->m_len
>= amt
)
3153 // everything fits in the first mbuf, so futz with m->m_data, m->m_len and m->m_pkthdr.len to
3155 m
->m_len
-= ETHER_HDR_LEN
;
3156 m
->m_data
+= ETHER_HDR_LEN
;
3157 m
->m_pkthdr
.len
-= ETHER_HDR_LEN
;
3159 // now do the checksums we need -- first IP
3160 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_IPv4
)
3162 struct ip
*ip
= mtod( m
, struct ip
* );
3163 ip
->ip_sum
= in_cksum( m
, hlen
);
3165 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3166 printf( "bridge: performed IPv4 checksum\n" );
3170 // now do a TCP or UDP delayed checksum
3171 if ( m
->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
) )
3173 in_delayed_cksum( m
);
3175 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3176 printf( "bridge: performed TCPv4/UDPv4 checksum\n" );
3180 // now stick the ethernet header back on
3181 m
->m_len
+= ETHER_HDR_LEN
;
3182 m
->m_data
-= ETHER_HDR_LEN
;
3183 m
->m_pkthdr
.len
+= ETHER_HDR_LEN
;
3185 // and clear any csum flags
3186 m
->m_pkthdr
.csum_flags
&= ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
|M_CSUM_IPv4
);
3192 // general case -- need to simply split it off and deal
3194 // first, calculate how much needs to be made writable (we may have a read-only mbuf here)
3195 hlen
= M_CSUM_DATA_IPv4_IPHL( m
->m_pkthdr
.csum_data
);
3197 off
= M_CSUM_DATA_IPv4_OFFSET( m
->m_pkthdr
.csum_data
);
3199 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_IPv4
)
3204 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_TCPv4
)
3206 amt
+= sizeof( struct tcphdr
* );
3210 if ( m
->m_pkthdr
.csum_flags
& M_CSUM_UDPv4
)
3212 amt
+= sizeof( struct udphdr
* );
3217 // now split the ethernet header off of the IP packet (we'll re-attach later)
3218 m_ip
= m_split( m
, ETHER_HDR_LEN
, M_NOWAIT
);
3221 printf( "bridge_fix_txcsum: could not split ether header\n" );
3228 // make sure that the IP packet is writable for the portion we need
3229 if ( m_makewritable( &m_ip
, 0, amt
, M_DONTWAIT
) != 0 )
3231 printf( "bridge_fix_txcsum: could not make %d bytes writable\n", amt
);
3239 m_ip
->m_pkthdr
.csum_flags
= m
->m_pkthdr
.csum_flags
;
3240 m_ip
->m_pkthdr
.csum_data
= m
->m_pkthdr
.csum_data
;
3242 m
->m_pkthdr
.csum_flags
= 0;
3243 m
->m_pkthdr
.csum_data
= 0;
3245 // now do the checksums we need -- first IP
3246 if ( m_ip
->m_pkthdr
.csum_flags
& M_CSUM_IPv4
)
3248 // make sure the IP header (or at least the part with the cksum) is there
3249 m_ip
= m_pullup( m_ip
, sizeof( struct ip
) );
3252 printf( "bridge: failed to flatten header\n ");
3257 // now do the checksum
3259 struct ip
*ip
= mtod( m_ip
, struct ip
* );
3260 ip
->ip_sum
= in_cksum( m_ip
, hlen
);
3262 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3263 printf( "bridge: performed IPv4 checksum\n" );
3268 // now do a TCP or UDP delayed checksum
3269 if ( m_ip
->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
) )
3271 in_delayed_cksum( m_ip
);
3273 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3274 printf( "bridge: performed TCPv4/UDPv4 checksum\n" );
3278 // now attach the ethernet header back onto the IP packet
3280 m
->m_pkthdr
.len
+= m_length( m_ip
);
3282 // clear the M_PKTHDR flags on the ip packet (again, we re-attach later)
3283 m_ip
->m_flags
&= ~M_PKTHDR
;
3285 // and clear any csum flags
3286 m
->m_pkthdr
.csum_flags
&= ~(M_CSUM_TCPv4
|M_CSUM_UDPv4
|M_CSUM_IPv4
);
3296 * Start output on a bridge.
3300 bridge_start(struct ifnet
*ifp
, struct mbuf
*m
)
3302 struct bridge_softc
*sc
= ifnet_softc(ifp
);
3303 struct ether_header
*eh
;
3304 struct ifnet
*dst_if
;
3306 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_NOTOWNED
);
3308 eh
= mtod(m
, struct ether_header
*);
3312 if ((m
->m_flags
& (M_BCAST
|M_MCAST
)) == 0 &&
3313 (dst_if
= bridge_rtlookup(sc
, eh
->ether_dhost
, 0)) != NULL
) {
3316 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
3318 * APPLE MODIFICATION - if the packet needs a checksum (i.e.,
3319 * checksum has been deferred for HW support) AND the destination
3320 * interface doesn't support HW checksums, then we
3321 * need to fix-up the checksum here
3324 ( (m
->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
|M_CSUM_IPv4
) ) != 0 ) &&
3325 ( (dst_if
->if_csum_flags_tx
& m
->m_pkthdr
.csum_flags
) != m
->m_pkthdr
.csum_flags
)
3328 m
= bridge_fix_txcsum( m
);
3336 if (eh
->ether_type
== htons(ETHERTYPE_IP
))
3337 mbuf_outbound_finalize(m
, PF_INET
, sizeof(struct ether_header
));
3339 m
->m_pkthdr
.csum_flags
= 0;
3342 if (sc
->sc_bpf_output
)
3343 bridge_bpf_output(ifp
, m
);
3346 bridge_enqueue(sc
, dst_if
, m
);
3350 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
3353 * APPLE MODIFICATION - if the MULTICAST packet needs a checksum (i.e.,
3354 * checksum has been deferred for HW support) AND at least one destination
3355 * interface doesn't support HW checksums, then we go ahead and fix it up
3356 * here, since it doesn't make sense to do it more than once
3360 (m
->m_pkthdr
.csum_flags
& (M_CSUM_TCPv4
|M_CSUM_UDPv4
|M_CSUM_IPv4
)) &&
3362 * XXX FIX ME: keep track of whether or not we have any interfaces that
3363 * do not support checksums (for now, assume we do)
3368 m
= bridge_fix_txcsum( m
);
3375 if (eh
->ether_type
== htons(ETHERTYPE_IP
))
3376 mbuf_outbound_finalize(m
, PF_INET
, sizeof(struct ether_header
));
3378 m
->m_pkthdr
.csum_flags
= 0;
3382 if (sc
->sc_bpf_output
)
3383 bridge_bpf_output(ifp
, m
);
3385 bridge_broadcast(sc
, ifp
, m
, 0);
3387 #if APPLE_BRIDGE_HWCKSUM_SUPPORT
3397 * The forwarding function of the bridge.
3399 * NOTE: Releases the lock on return.
3402 bridge_forward(struct bridge_softc
*sc
, struct bridge_iflist
*sbif
,
3405 struct bridge_iflist
*dbif
;
3406 struct ifnet
*src_if
, *dst_if
, *ifp
;
3407 struct ether_header
*eh
;
3412 lck_mtx_assert(sc
->sc_mtx
, LCK_MTX_ASSERT_OWNED
);
3415 if (_if_brige_debug
)
3416 printf("bridge_forward %s%d m%p\n", ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
), m
);
3417 #endif /* BRIDGE_DEBUG */
3419 src_if
= m
->m_pkthdr
.rcvif
;
3422 (void) ifnet_stat_increment_in(ifp
, 1, m
->m_pkthdr
.len
, 0);
3423 vlan
= VLANTAGOF(m
);
3426 if ((sbif
->bif_flags
& IFBIF_STP
) &&
3427 sbif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
)
3430 eh
= mtod(m
, struct ether_header
*);
3431 dst
= eh
->ether_dhost
;
3433 /* If the interface is learning, record the address. */
3434 if (sbif
->bif_flags
& IFBIF_LEARNING
) {
3435 error
= bridge_rtupdate(sc
, eh
->ether_shost
, vlan
,
3436 sbif
, 0, IFBAF_DYNAMIC
);
3438 * If the interface has addresses limits then deny any source
3439 * that is not in the cache.
3441 if (error
&& sbif
->bif_addrmax
)
3445 if ((sbif
->bif_flags
& IFBIF_STP
) != 0 &&
3446 sbif
->bif_stp
.bp_state
== BSTP_IFSTATE_LEARNING
)
3450 * At this point, the port either doesn't participate
3451 * in spanning tree or it is in the forwarding state.
3455 * If the packet is unicast, destined for someone on
3456 * "this" side of the bridge, drop it.
3458 if ((m
->m_flags
& (M_BCAST
|M_MCAST
)) == 0) {
3459 dst_if
= bridge_rtlookup(sc
, dst
, vlan
);
3460 if (src_if
== dst_if
)
3464 * Check if its a reserved multicast address, any address
3465 * listed in 802.1D section 7.12.6 may not be forwarded by the
3467 * This is currently 01-80-C2-00-00-00 to 01-80-C2-00-00-0F
3469 if (dst
[0] == 0x01 && dst
[1] == 0x80 &&
3470 dst
[2] == 0xc2 && dst
[3] == 0x00 &&
3471 dst
[4] == 0x00 && dst
[5] <= 0x0f)
3475 /* ...forward it to all interfaces. */
3476 atomic_add_64(&ifp
->if_imcasts
, 1);
3481 * If we have a destination interface which is a member of our bridge,
3482 * OR this is a unicast packet, push it through the bpf(4) machinery.
3483 * For broadcast or multicast packets, don't bother because it will
3484 * be reinjected into ether_input. We do this before we pass the packets
3485 * through the pfil(9) framework, as it is possible that pfil(9) will
3486 * drop the packet, or possibly modify it, making it difficult to debug
3487 * firewall issues on the bridge.
3490 if (eh
->ether_type
== htons(ETHERTYPE_RSN_PREAUTH
) ||
3491 dst_if
!= NULL
|| (m
->m_flags
& (M_BCAST
| M_MCAST
)) == 0) {
3492 m
->m_pkthdr
.rcvif
= ifp
;
3493 if (sc
->sc_bpf_input
)
3494 bridge_bpf_input(ifp
, m
);
3496 #endif /* NBPFILTER */
3498 #if defined(PFIL_HOOKS)
3499 /* run the packet filter */
3500 if (PFIL_HOOKED(&inet_pfil_hook
)
3502 || PFIL_HOOKED(&inet6_pfil_hook
)
3506 if (bridge_pfil(&m
, ifp
, src_if
, PFIL_IN
) != 0)
3512 #endif /* PFIL_HOOKS */
3514 if (dst_if
== NULL
) {
3516 * Clear any in-bound checksum flags for this packet.
3518 mbuf_inbound_modified(m
);
3520 bridge_broadcast(sc
, src_if
, m
, 1);
3526 * At this point, we're dealing with a unicast frame
3527 * going to a different interface.
3529 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
3532 dbif
= bridge_lookup_member_if(sc
, dst_if
);
3534 /* Not a member of the bridge (anymore?) */
3537 /* Private segments can not talk to each other */
3538 if (sbif
->bif_flags
& dbif
->bif_flags
& IFBIF_PRIVATE
)
3541 if ((dbif
->bif_flags
& IFBIF_STP
) &&
3542 dbif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
)
3546 /* APPLE MODIFICATION <rdar://6985737> */
3547 if ((dst_if
->if_extflags
& IFEXTF_DHCPRA_MASK
) != 0) {
3548 m
= ip_xdhcpra_output(dst_if
, m
);
3550 ++sc
->sc_sc
.sc_ifp
.if_xdhcpra
;
3554 #endif /* HAS_DHCPRA_MASK */
3558 #if defined(PFIL_HOOKS)
3559 if (PFIL_HOOKED(&inet_pfil_hook
)
3561 || PFIL_HOOKED(&inet6_pfil_hook
)
3564 if (bridge_pfil(&m
, ifp
, dst_if
, PFIL_OUT
) != 0)
3569 #endif /* PFIL_HOOKS */
3572 * Clear any in-bound checksum flags for this packet.
3574 mbuf_inbound_modified(m
);
3576 bridge_enqueue(sc
, dst_if
, m
);
3586 char * ether_ntop(char *, size_t , const u_char
*);
3588 __private_extern__
char *
3589 ether_ntop(char *buf
, size_t len
, const u_char
*ap
)
3591 snprintf(buf
, len
, "%02x:%02x:%02x:%02x:%02x:%02x",
3592 ap
[0], ap
[1], ap
[2], ap
[3], ap
[4], ap
[5]);
3597 #endif /* BRIDGE_DEBUG */
3602 * Filter input from a member interface. Queue the packet for
3603 * bridging if it is not for us.
3605 __private_extern__ errno_t
3606 bridge_input(struct ifnet
*ifp
, struct mbuf
*m
, __unused
void *frame_header
)
3608 struct bridge_softc
*sc
= ifp
->if_bridge
;
3609 struct bridge_iflist
*bif
, *bif2
;
3611 struct ether_header
*eh
;
3612 struct mbuf
*mc
, *mc2
;
3617 if (_if_brige_debug
)
3618 printf("bridge_input: %s%d from %s%d m %p data %p\n",
3619 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
3620 ifnet_name(ifp
), ifnet_unit(ifp
),
3622 #endif /* BRIDGE_DEBUG */
3624 if ((sc
->sc_ifp
->if_flags
& IFF_RUNNING
) == 0) {
3626 if (_if_brige_debug
)
3627 printf( "bridge_input: %s%d not running passing along\n",
3628 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
));
3629 #endif /* BRIDGE_DEBUG */
3634 vlan
= VLANTAGOF(m
);
3638 * Implement support for bridge monitoring. If this flag has been
3639 * set on this interface, discard the packet once we push it through
3640 * the bpf(4) machinery, but before we do, increment the byte and
3641 * packet counters associated with this interface.
3643 if ((bifp
->if_flags
& IFF_MONITOR
) != 0) {
3644 m
->m_pkthdr
.rcvif
= bifp
;
3645 BRIDGE_BPF_MTAP_INPUT(sc
, m
);
3646 (void) ifnet_stat_increment_in(bifp
, 1, m
->m_pkthdr
.len
, 0);
3650 #endif /* IFF_MONITOR */
3653 * Need to clear the promiscous flags otherwise it will be
3654 * dropped by DLIL after processing filters
3656 if ((mbuf_flags(m
) & MBUF_PROMISC
))
3657 mbuf_setflags_mask(m
, 0, MBUF_PROMISC
);
3660 bif
= bridge_lookup_member_if(sc
, ifp
);
3664 if (_if_brige_debug
)
3665 printf( "bridge_input: %s%d bridge_lookup_member_if failed\n",
3666 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
));
3667 #endif /* BRIDGE_DEBUG */
3671 eh
= mtod(m
, struct ether_header
*);
3675 if (m
->m_flags
& (M_BCAST
|M_MCAST
)) {
3678 if (_if_brige_debug
)
3679 if ((m
->m_flags
& M_MCAST
))
3680 printf("mulicast: %02x:%02x:%02x:%02x:%02x:%02x\n",
3681 eh
->ether_dhost
[0], eh
->ether_dhost
[1], eh
->ether_dhost
[2],
3682 eh
->ether_dhost
[3], eh
->ether_dhost
[4], eh
->ether_dhost
[5]);
3684 #endif /* BRIDGE_DEBUG */
3686 /* Tap off 802.1D packets; they do not get forwarded. */
3687 if (memcmp(eh
->ether_dhost
, bstp_etheraddr
,
3688 ETHER_ADDR_LEN
) == 0) {
3689 m
= bstp_input(&bif
->bif_stp
, ifp
, m
);
3696 if ((bif
->bif_flags
& IFBIF_STP
) &&
3697 bif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
) {
3703 * Make a deep copy of the packet and enqueue the copy
3704 * for bridge processing; return the original packet for
3707 mc
= m_dup(m
, M_DONTWAIT
);
3714 * Perform the bridge forwarding function with the copy.
3716 * Note that bridge_forward calls BRIDGE_UNLOCK
3718 bridge_forward(sc
, bif
, mc
);
3721 * Reinject the mbuf as arriving on the bridge so we have a
3722 * chance at claiming multicast packets. We can not loop back
3723 * here from ether_input as a bridge is never a member of a
3726 KASSERT(bifp
->if_bridge
== NULL
,
3727 ("loop created in bridge_input"));
3728 mc2
= m_dup(m
, M_DONTWAIT
);
3730 /* Keep the layer3 header aligned */
3731 int i
= min(mc2
->m_pkthdr
.len
, max_protohdr
);
3732 mc2
= m_copyup(mc2
, i
, ETHER_ALIGN
);
3735 // mark packet as arriving on the bridge
3736 mc2
->m_pkthdr
.rcvif
= bifp
;
3737 mc2
->m_pkthdr
.header
= mbuf_data(mc2
);
3740 if (sc
->sc_bpf_input
)
3741 bridge_bpf_input(bifp
, mc2
);
3742 #endif /* NBPFILTER */
3743 (void) mbuf_setdata(mc2
, (char *)mbuf_data(mc2
) + ETHER_HDR_LEN
, mbuf_len(mc2
) - ETHER_HDR_LEN
);
3744 (void) mbuf_pkthdr_adjustlen(mc2
, - ETHER_HDR_LEN
);
3746 (void) ifnet_stat_increment_in(bifp
, 1, mbuf_pkthdr_len(mc2
), 0);
3749 if (_if_brige_debug
)
3750 printf( "bridge_input: %s%d mcast for us\n",
3751 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
));
3752 #endif /* BRIDGE_DEBUG */
3754 dlil_input_packet_list(bifp
, mc2
);
3757 /* Return the original packet for local processing. */
3761 if ((bif
->bif_flags
& IFBIF_STP
) &&
3762 bif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
) {
3768 # define OR_CARP_CHECK_WE_ARE_DST(iface) \
3769 || ((iface)->if_carp \
3770 && carp_forus((iface)->if_carp, eh->ether_dhost))
3771 # define OR_CARP_CHECK_WE_ARE_SRC(iface) \
3772 || ((iface)->if_carp \
3773 && carp_forus((iface)->if_carp, eh->ether_shost))
3775 # define OR_CARP_CHECK_WE_ARE_DST(iface)
3776 # define OR_CARP_CHECK_WE_ARE_SRC(iface)
3780 # define OR_PFIL_HOOKED_INET6 \
3781 || PFIL_HOOKED(&inet6_pfil_hook)
3783 # define OR_PFIL_HOOKED_INET6
3786 #if defined(PFIL_HOOKS)
3787 #define PFIL_PHYS(sc, ifp, m) do { \
3788 if (pfil_local_phys && \
3789 (PFIL_HOOKED(&inet_pfil_hook) \
3790 OR_PFIL_HOOKED_INET6)) { \
3791 if (bridge_pfil(&m, NULL, ifp, \
3792 PFIL_IN) != 0 || m == NULL) { \
3793 BRIDGE_UNLOCK(sc); \
3798 #else /* PFIL_HOOKS */
3799 #define PFIL_PHYS(sc, ifp, m)
3800 #endif /* PFIL_HOOKS */
3802 #define GRAB_OUR_PACKETS(iface) \
3803 if ((iface)->if_type == IFT_GIF) \
3805 /* It is destined for us. */ \
3806 if (memcmp(ifnet_lladdr((iface)), eh->ether_dhost, ETHER_ADDR_LEN) == 0 \
3807 OR_CARP_CHECK_WE_ARE_DST((iface)) \
3809 if ((iface)->if_type == IFT_BRIDGE) { \
3810 BRIDGE_BPF_MTAP_INPUT(sc, m); \
3811 /* Filter on the physical interface. */ \
3812 PFIL_PHYS(sc, iface, m); \
3814 if (bif->bif_flags & IFBIF_LEARNING) { \
3815 error = bridge_rtupdate(sc, eh->ether_shost, \
3816 vlan, bif, 0, IFBAF_DYNAMIC); \
3817 if (error && bif->bif_addrmax) { \
3818 BRIDGE_UNLOCK(sc); \
3819 return EJUSTRETURN; \
3822 m->m_pkthdr.rcvif = iface; \
3823 BRIDGE_UNLOCK(sc); \
3827 /* We just received a packet that we sent out. */ \
3828 if (memcmp(ifnet_lladdr((iface)), eh->ether_shost, ETHER_ADDR_LEN) == 0 \
3829 OR_CARP_CHECK_WE_ARE_SRC((iface)) \
3831 BRIDGE_UNLOCK(sc); \
3832 return EJUSTRETURN; \
3839 * If the packet is for us, set the packets source as the
3840 * bridge, and return the packet back to ether_input for
3843 if (memcmp(eh
->ether_dhost
, ifnet_lladdr(bifp
),
3844 ETHER_ADDR_LEN
) == 0
3845 OR_CARP_CHECK_WE_ARE_DST(bifp
)) {
3847 /* Mark the packet as arriving on the bridge interface */
3848 (void) mbuf_pkthdr_setrcvif(m
, bifp
);
3849 mbuf_pkthdr_setheader(m
, frame_header
);
3852 * If the interface is learning, and the source
3853 * address is valid and not multicast, record
3856 if ((bif
->bif_flags
& IFBIF_LEARNING
) != 0 &&
3857 ETHER_IS_MULTICAST(eh
->ether_shost
) == 0 &&
3858 (eh
->ether_shost
[0] | eh
->ether_shost
[1] |
3859 eh
->ether_shost
[2] | eh
->ether_shost
[3] |
3860 eh
->ether_shost
[4] | eh
->ether_shost
[5]) != 0) {
3861 (void) bridge_rtupdate(sc
, eh
->ether_shost
,
3862 vlan
, bif
, 0, IFBAF_DYNAMIC
);
3865 BRIDGE_BPF_MTAP_INPUT(sc
, m
);
3867 (void) mbuf_setdata(m
, (char *)mbuf_data(m
) + ETHER_HDR_LEN
, mbuf_len(m
) - ETHER_HDR_LEN
);
3868 (void) mbuf_pkthdr_adjustlen(m
, - ETHER_HDR_LEN
);
3870 (void) ifnet_stat_increment_in(bifp
, 1, mbuf_pkthdr_len(m
), 0);
3875 if (_if_brige_debug
)
3876 printf( "bridge_input: %s%d packet for bridge\n",
3877 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
));
3878 #endif /* BRIDGE_DEBUG */
3880 dlil_input_packet_list(bifp
, m
);
3886 * if the destination of the packet is for the MAC address of
3887 * the member interface itself, then we don't need to forward
3888 * it -- just pass it back. Note that it'll likely just be
3889 * dropped by the stack, but if something else is bound to
3890 * the interface directly (for example, the wireless stats
3891 * protocol -- although that actually uses BPF right now),
3892 * then it will consume the packet
3894 * ALSO, note that we do this check AFTER checking for the
3895 * bridge's own MAC address, because the bridge may be
3896 * using the SAME MAC address as one of its interfaces
3898 if (memcmp(eh
->ether_dhost
, ifnet_lladdr(ifp
),
3899 ETHER_ADDR_LEN
) == 0) {
3901 #ifdef VERY_VERY_VERY_DIAGNOSTIC
3902 printf("bridge_input: not forwarding packet bound for member interface\n" );
3908 /* Now check the all bridge members. */
3909 TAILQ_FOREACH(bif2
, &sc
->sc_iflist
, bif_next
) {
3910 GRAB_OUR_PACKETS(bif2
->bif_ifp
)
3913 #undef OR_CARP_CHECK_WE_ARE_DST
3914 #undef OR_CARP_CHECK_WE_ARE_SRC
3915 #undef OR_PFIL_HOOKED_INET6
3916 #undef GRAB_OUR_PACKETS
3919 * Perform the bridge forwarding function.
3921 * Note that bridge_forward calls BRIDGE_UNLOCK
3923 bridge_forward(sc
, bif
, m
);
3931 * Send a frame to all interfaces that are members of
3932 * the bridge, except for the one on which the packet
3935 * NOTE: Releases the lock on return.
3938 bridge_broadcast(struct bridge_softc
*sc
, struct ifnet
*src_if
,
3939 struct mbuf
*m
, int runfilt
)
3942 #pragma unused(runfilt)
3944 struct bridge_iflist
*dbif
, *sbif
;
3946 struct ifnet
*dst_if
;
3947 int error
= 0, used
= 0;
3949 sbif
= bridge_lookup_member_if(sc
, src_if
);
3951 BRIDGE_LOCK2REF(sc
, error
);
3958 /* Filter on the bridge interface before broadcasting */
3959 if (runfilt
&& (PFIL_HOOKED(&inet_pfil_hook
)
3961 || PFIL_HOOKED(&inet6_pfil_hook
)
3964 if (bridge_pfil(&m
, sc
->sc_ifp
, NULL
, PFIL_OUT
) != 0)
3969 #endif /* PFIL_HOOKS */
3971 TAILQ_FOREACH(dbif
, &sc
->sc_iflist
, bif_next
) {
3972 dst_if
= dbif
->bif_ifp
;
3973 if (dst_if
== src_if
)
3976 /* Private segments can not talk to each other */
3977 if (sbif
&& (sbif
->bif_flags
& dbif
->bif_flags
& IFBIF_PRIVATE
))
3980 if ((dbif
->bif_flags
& IFBIF_STP
) &&
3981 dbif
->bif_stp
.bp_state
== BSTP_IFSTATE_DISCARDING
)
3984 if ((dbif
->bif_flags
& IFBIF_DISCOVER
) == 0 &&
3985 (m
->m_flags
& (M_BCAST
|M_MCAST
)) == 0)
3988 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
3991 if (TAILQ_NEXT(dbif
, bif_next
) == NULL
) {
3995 mc
= m_dup(m
, M_DONTWAIT
);
3997 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 0, 0, 1);
4004 * Filter on the output interface. Pass a NULL bridge interface
4005 * pointer so we do not redundantly filter on the bridge for
4006 * each interface we broadcast on.
4008 if (runfilt
&& (PFIL_HOOKED(&inet_pfil_hook
)
4010 || PFIL_HOOKED(&inet6_pfil_hook
)
4014 /* Keep the layer3 header aligned */
4015 int i
= min(mc
->m_pkthdr
.len
, max_protohdr
);
4016 mc
= m_copyup(mc
, i
, ETHER_ALIGN
);
4018 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 0, 0, 1);
4022 if (bridge_pfil(&mc
, NULL
, dst_if
, PFIL_OUT
) != 0)
4027 #endif /* PFIL_HOOKS */
4029 bridge_enqueue(sc
, dst_if
, mc
);
4036 #endif /* PFIL_HOOKS */
4044 * Duplicate a packet out one or more interfaces that are in span mode,
4045 * the original mbuf is unmodified.
4048 bridge_span(struct bridge_softc
*sc
, struct mbuf
*m
)
4050 struct bridge_iflist
*bif
;
4051 struct ifnet
*dst_if
;
4054 if (TAILQ_EMPTY(&sc
->sc_spanlist
))
4057 TAILQ_FOREACH(bif
, &sc
->sc_spanlist
, bif_next
) {
4058 dst_if
= bif
->bif_ifp
;
4060 if ((dst_if
->if_flags
& IFF_RUNNING
) == 0)
4063 mc
= m_copypacket(m
, M_DONTWAIT
);
4065 (void) ifnet_stat_increment_out(sc
->sc_ifp
, 0, 0, 1);
4069 bridge_enqueue(sc
, dst_if
, mc
);
4078 * Add a bridge routing entry.
4081 bridge_rtupdate(struct bridge_softc
*sc
, const uint8_t *dst
, uint16_t vlan
,
4082 struct bridge_iflist
*bif
, int setflags
, uint8_t flags
)
4084 struct bridge_rtnode
*brt
;
4087 BRIDGE_LOCK_ASSERT(sc
);
4089 /* Check the source address is valid and not multicast. */
4090 if (ETHER_IS_MULTICAST(dst
) ||
4091 (dst
[0] == 0 && dst
[1] == 0 && dst
[2] == 0 &&
4092 dst
[3] == 0 && dst
[4] == 0 && dst
[5] == 0) != 0)
4096 /* 802.1p frames map to vlan 1 */
4101 * A route for this destination might already exist. If so,
4102 * update it, otherwise create a new one.
4104 if ((brt
= bridge_rtnode_lookup(sc
, dst
, vlan
)) == NULL
) {
4105 if (sc
->sc_brtcnt
>= sc
->sc_brtmax
) {
4106 sc
->sc_brtexceeded
++;
4109 /* Check per interface address limits (if enabled) */
4110 if (bif
->bif_addrmax
&& bif
->bif_addrcnt
>= bif
->bif_addrmax
) {
4111 bif
->bif_addrexceeded
++;
4116 * Allocate a new bridge forwarding node, and
4117 * initialize the expiration time and Ethernet
4120 brt
= zalloc_noblock(bridge_rtnode_pool
);
4124 if (bif
->bif_flags
& IFBIF_STICKY
)
4125 brt
->brt_flags
= IFBAF_STICKY
;
4127 brt
->brt_flags
= IFBAF_DYNAMIC
;
4129 memcpy(brt
->brt_addr
, dst
, ETHER_ADDR_LEN
);
4130 brt
->brt_vlan
= vlan
;
4133 if ((error
= bridge_rtnode_insert(sc
, brt
)) != 0) {
4134 zfree(bridge_rtnode_pool
, brt
);
4141 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
&&
4142 brt
->brt_dst
!= bif
) {
4143 brt
->brt_dst
->bif_addrcnt
--;
4145 brt
->brt_dst
->bif_addrcnt
++;
4148 if ((flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
4149 struct timespec now
;
4152 brt
->brt_expire
= now
.tv_sec
+ sc
->sc_brttimeout
;
4155 brt
->brt_flags
= flags
;
4164 * Lookup the destination interface for an address.
4166 static struct ifnet
*
4167 bridge_rtlookup(struct bridge_softc
*sc
, const uint8_t *addr
, uint16_t vlan
)
4169 struct bridge_rtnode
*brt
;
4171 BRIDGE_LOCK_ASSERT(sc
);
4173 if ((brt
= bridge_rtnode_lookup(sc
, addr
, vlan
)) == NULL
)
4176 return (brt
->brt_ifp
);
4182 * Trim the routine table so that we have a number
4183 * of routing entries less than or equal to the
4187 bridge_rttrim(struct bridge_softc
*sc
)
4189 struct bridge_rtnode
*brt
, *nbrt
;
4191 BRIDGE_LOCK_ASSERT(sc
);
4193 /* Make sure we actually need to do this. */
4194 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
4197 /* Force an aging cycle; this might trim enough addresses. */
4199 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
4202 LIST_FOREACH_SAFE(brt
, &sc
->sc_rtlist
, brt_list
, nbrt
) {
4203 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
4204 bridge_rtnode_destroy(sc
, brt
);
4205 if (sc
->sc_brtcnt
<= sc
->sc_brtmax
)
4214 * Aging timer for the bridge.
4217 bridge_timer(void *arg
)
4219 struct bridge_softc
*sc
= arg
;
4227 if (sc
->sc_ifp
->if_flags
& IFF_RUNNING
) {
4230 ts
.tv_sec
= bridge_rtable_prune_period
;
4232 bsd_timeout(bridge_timer
, sc
, &ts
);
4239 * Perform an aging cycle.
4242 bridge_rtage(struct bridge_softc
*sc
)
4244 struct bridge_rtnode
*brt
, *nbrt
;
4246 BRIDGE_LOCK_ASSERT(sc
);
4248 LIST_FOREACH_SAFE(brt
, &sc
->sc_rtlist
, brt_list
, nbrt
) {
4249 if ((brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
) {
4250 struct timespec now
;
4253 if ((unsigned long)now
.tv_sec
>= brt
->brt_expire
)
4254 bridge_rtnode_destroy(sc
, brt
);
4262 * Remove all dynamic addresses from the bridge.
4265 bridge_rtflush(struct bridge_softc
*sc
, int full
)
4267 struct bridge_rtnode
*brt
, *nbrt
;
4269 BRIDGE_LOCK_ASSERT(sc
);
4271 LIST_FOREACH_SAFE(brt
, &sc
->sc_rtlist
, brt_list
, nbrt
) {
4272 if (full
|| (brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
)
4273 bridge_rtnode_destroy(sc
, brt
);
4280 * Remove an address from the table.
4283 bridge_rtdaddr(struct bridge_softc
*sc
, const uint8_t *addr
, uint16_t vlan
)
4285 struct bridge_rtnode
*brt
;
4288 BRIDGE_LOCK_ASSERT(sc
);
4291 * If vlan is zero then we want to delete for all vlans so the lookup
4292 * may return more than one.
4294 while ((brt
= bridge_rtnode_lookup(sc
, addr
, vlan
)) != NULL
) {
4295 bridge_rtnode_destroy(sc
, brt
);
4299 return (found
? 0 : ENOENT
);
4305 * Delete routes to a speicifc member interface.
4308 bridge_rtdelete(struct bridge_softc
*sc
, struct ifnet
*ifp
, int full
)
4310 struct bridge_rtnode
*brt
, *nbrt
;
4312 BRIDGE_LOCK_ASSERT(sc
);
4314 LIST_FOREACH_SAFE(brt
, &sc
->sc_rtlist
, brt_list
, nbrt
) {
4315 if (brt
->brt_ifp
== ifp
&& (full
||
4316 (brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
))
4317 bridge_rtnode_destroy(sc
, brt
);
4322 * bridge_rtable_init:
4324 * Initialize the route table for this bridge.
4327 bridge_rtable_init(struct bridge_softc
*sc
)
4331 sc
->sc_rthash
= _MALLOC(sizeof(*sc
->sc_rthash
) * BRIDGE_RTHASH_SIZE
,
4332 M_DEVBUF
, M_NOWAIT
);
4333 if (sc
->sc_rthash
== NULL
)
4336 for (i
= 0; i
< BRIDGE_RTHASH_SIZE
; i
++)
4337 LIST_INIT(&sc
->sc_rthash
[i
]);
4339 sc
->sc_rthash_key
= random();
4341 LIST_INIT(&sc
->sc_rtlist
);
4347 * bridge_rtable_fini:
4349 * Deconstruct the route table for this bridge.
4352 bridge_rtable_fini(struct bridge_softc
*sc
)
4355 KASSERT(sc
->sc_brtcnt
== 0,
4356 ("%s: %d bridge routes referenced", __func__
, sc
->sc_brtcnt
));
4357 _FREE(sc
->sc_rthash
, M_DEVBUF
);
4361 * The following hash function is adapted from "Hash Functions" by Bob Jenkins
4362 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
4364 #define mix(a, b, c) \
4366 a -= b; a -= c; a ^= (c >> 13); \
4367 b -= c; b -= a; b ^= (a << 8); \
4368 c -= a; c -= b; c ^= (b >> 13); \
4369 a -= b; a -= c; a ^= (c >> 12); \
4370 b -= c; b -= a; b ^= (a << 16); \
4371 c -= a; c -= b; c ^= (b >> 5); \
4372 a -= b; a -= c; a ^= (c >> 3); \
4373 b -= c; b -= a; b ^= (a << 10); \
4374 c -= a; c -= b; c ^= (b >> 15); \
4375 } while (/*CONSTCOND*/0)
4377 static __inline
uint32_t
4378 bridge_rthash(struct bridge_softc
*sc
, const uint8_t *addr
)
4380 uint32_t a
= 0x9e3779b9, b
= 0x9e3779b9, c
= sc
->sc_rthash_key
;
4391 return (c
& BRIDGE_RTHASH_MASK
);
4397 bridge_rtnode_addr_cmp(const uint8_t *a
, const uint8_t *b
)
4401 for (i
= 0, d
= 0; i
< ETHER_ADDR_LEN
&& d
== 0; i
++) {
4402 d
= ((int)a
[i
]) - ((int)b
[i
]);
4409 * bridge_rtnode_lookup:
4411 * Look up a bridge route node for the specified destination. Compare the
4412 * vlan id or if zero then just return the first match.
4414 static struct bridge_rtnode
*
4415 bridge_rtnode_lookup(struct bridge_softc
*sc
, const uint8_t *addr
, uint16_t vlan
)
4417 struct bridge_rtnode
*brt
;
4421 BRIDGE_LOCK_ASSERT(sc
);
4423 hash
= bridge_rthash(sc
, addr
);
4424 LIST_FOREACH(brt
, &sc
->sc_rthash
[hash
], brt_hash
) {
4425 dir
= bridge_rtnode_addr_cmp(addr
, brt
->brt_addr
);
4426 if (dir
== 0 && (brt
->brt_vlan
== vlan
|| vlan
== 0))
4436 * bridge_rtnode_insert:
4438 * Insert the specified bridge node into the route table. We
4439 * assume the entry is not already in the table.
4442 bridge_rtnode_insert(struct bridge_softc
*sc
, struct bridge_rtnode
*brt
)
4444 struct bridge_rtnode
*lbrt
;
4448 BRIDGE_LOCK_ASSERT(sc
);
4450 hash
= bridge_rthash(sc
, brt
->brt_addr
);
4452 lbrt
= LIST_FIRST(&sc
->sc_rthash
[hash
]);
4454 LIST_INSERT_HEAD(&sc
->sc_rthash
[hash
], brt
, brt_hash
);
4459 dir
= bridge_rtnode_addr_cmp(brt
->brt_addr
, lbrt
->brt_addr
);
4460 if (dir
== 0 && brt
->brt_vlan
== lbrt
->brt_vlan
)
4463 LIST_INSERT_BEFORE(lbrt
, brt
, brt_hash
);
4466 if (LIST_NEXT(lbrt
, brt_hash
) == NULL
) {
4467 LIST_INSERT_AFTER(lbrt
, brt
, brt_hash
);
4470 lbrt
= LIST_NEXT(lbrt
, brt_hash
);
4471 } while (lbrt
!= NULL
);
4474 panic("bridge_rtnode_insert: impossible");
4478 LIST_INSERT_HEAD(&sc
->sc_rtlist
, brt
, brt_list
);
4485 * bridge_rtnode_destroy:
4487 * Destroy a bridge rtnode.
4490 bridge_rtnode_destroy(struct bridge_softc
*sc
, struct bridge_rtnode
*brt
)
4492 BRIDGE_LOCK_ASSERT(sc
);
4494 LIST_REMOVE(brt
, brt_hash
);
4496 LIST_REMOVE(brt
, brt_list
);
4498 brt
->brt_dst
->bif_addrcnt
--;
4499 zfree(bridge_rtnode_pool
, brt
);
4503 * bridge_rtable_expire:
4505 * Set the expiry time for all routes on an interface.
4508 bridge_rtable_expire(struct ifnet
*ifp
, int age
)
4510 struct bridge_softc
*sc
= ifp
->if_bridge
;
4511 struct bridge_rtnode
*brt
;
4516 * If the age is zero then flush, otherwise set all the expiry times to
4517 * age for the interface
4520 bridge_rtdelete(sc
, ifp
, IFBF_FLUSHDYN
);
4522 LIST_FOREACH(brt
, &sc
->sc_rtlist
, brt_list
) {
4523 struct timespec now
;
4526 /* Cap the expiry time to 'age' */
4527 if (brt
->brt_ifp
== ifp
&&
4528 brt
->brt_expire
> (unsigned long)now
.tv_sec
+ age
&&
4529 (brt
->brt_flags
& IFBAF_TYPEMASK
) == IFBAF_DYNAMIC
)
4530 brt
->brt_expire
= (unsigned long)now
.tv_sec
+ age
;
4537 * bridge_state_change:
4539 * Callback from the bridgestp code when a port changes states.
4542 bridge_state_change(struct ifnet
*ifp
, int state
)
4544 struct bridge_softc
*sc
= ifp
->if_bridge
;
4545 static const char *stpstates
[] = {
4555 log(LOG_NOTICE
, "%s%d: state changed to %s on %s%d\n",
4556 ifnet_name(sc
->sc_ifp
), ifnet_unit(sc
->sc_ifp
),
4558 ifnet_name(ifp
), ifnet_unit(ifp
));
4563 * Send bridge packets through pfil if they are one of the types pfil can deal
4564 * with, or if they are ARP or REVARP. (pfil will pass ARP and REVARP without
4565 * question.) If *bifp or *ifp are NULL then packet filtering is skipped for
4569 bridge_pfil(struct mbuf
**mp
, struct ifnet
*bifp
, struct ifnet
*ifp
, int dir
)
4571 int snap
, error
, i
, hlen
;
4572 struct ether_header
*eh1
, eh2
;
4573 struct ip_fw_args args
;
4576 u_int16_t ether_type
;
4579 error
= -1; /* Default error if not error == 0 */
4582 /* we may return with the IP fields swapped, ensure its not shared */
4583 KASSERT(M_WRITABLE(*mp
), ("%s: modifying a shared mbuf", __func__
));
4586 if (pfil_bridge
== 0 && pfil_member
== 0 && pfil_ipfw
== 0)
4587 return (0); /* filtering is disabled */
4589 i
= min((*mp
)->m_pkthdr
.len
, max_protohdr
);
4590 if ((*mp
)->m_len
< i
) {
4591 *mp
= m_pullup(*mp
, i
);
4593 printf("%s: m_pullup failed\n", __func__
);
4598 eh1
= mtod(*mp
, struct ether_header
*);
4599 ether_type
= ntohs(eh1
->ether_type
);
4602 * Check for SNAP/LLC.
4604 if (ether_type
< ETHERMTU
) {
4605 struct llc
*llc2
= (struct llc
*)(eh1
+ 1);
4607 if ((*mp
)->m_len
>= ETHER_HDR_LEN
+ 8 &&
4608 llc2
->llc_dsap
== LLC_SNAP_LSAP
&&
4609 llc2
->llc_ssap
== LLC_SNAP_LSAP
&&
4610 llc2
->llc_control
== LLC_UI
) {
4611 ether_type
= htons(llc2
->llc_un
.type_snap
.ether_type
);
4617 * If we're trying to filter bridge traffic, don't look at anything
4618 * other than IP and ARP traffic. If the filter doesn't understand
4619 * IPv6, don't allow IPv6 through the bridge either. This is lame
4620 * since if we really wanted, say, an AppleTalk filter, we are hosed,
4621 * but of course we don't have an AppleTalk filter to begin with.
4622 * (Note that since pfil doesn't understand ARP it will pass *ALL*
4625 switch (ether_type
) {
4627 case ETHERTYPE_REVARP
:
4628 if (pfil_ipfw_arp
== 0)
4629 return (0); /* Automatically pass */
4634 case ETHERTYPE_IPV6
:
4639 * Check to see if the user wants to pass non-ip
4640 * packets, these will not be checked by pfil(9) and
4641 * passed unconditionally so the default is to drop.
4647 /* Strip off the Ethernet header and keep a copy. */
4648 m_copydata(*mp
, 0, ETHER_HDR_LEN
, (caddr_t
) &eh2
);
4649 m_adj(*mp
, ETHER_HDR_LEN
);
4651 /* Strip off snap header, if present */
4653 m_copydata(*mp
, 0, sizeof(struct llc
), (caddr_t
) &llc1
);
4654 m_adj(*mp
, sizeof(struct llc
));
4658 * Check the IP header for alignment and errors
4660 if (dir
== PFIL_IN
) {
4661 switch (ether_type
) {
4663 error
= bridge_ip_checkbasic(mp
);
4666 case ETHERTYPE_IPV6
:
4667 error
= bridge_ip6_checkbasic(mp
);
4677 if (IPFW_LOADED
&& pfil_ipfw
!= 0 && dir
== PFIL_OUT
&& ifp
!= NULL
) {
4679 args
.rule
= ip_dn_claim_rule(*mp
);
4680 if (args
.rule
!= NULL
&& fw_one_pass
)
4681 goto ipfwpass
; /* packet already partially processed */
4685 args
.next_hop
= NULL
;
4687 args
.inp
= NULL
; /* used by ipfw uid/gid/jail rules */
4688 i
= ip_fw_chk_ptr(&args
);
4694 if (DUMMYNET_LOADED
&& (i
== IP_FW_DUMMYNET
)) {
4696 /* put the Ethernet header back on */
4697 M_PREPEND(*mp
, ETHER_HDR_LEN
, M_DONTWAIT
);
4700 bcopy(&eh2
, mtod(*mp
, caddr_t
), ETHER_HDR_LEN
);
4703 * Pass the pkt to dummynet, which consumes it. The
4704 * packet will return to us via bridge_dummynet().
4707 ip_dn_io_ptr(mp
, DN_TO_IFB_FWD
, &args
);
4711 if (i
!= IP_FW_PASS
) /* drop */
4719 * Run the packet through pfil
4721 switch (ether_type
) {
4724 * before calling the firewall, swap fields the same as
4725 * IP does. here we assume the header is contiguous
4727 ip
= mtod(*mp
, struct ip
*);
4729 ip
->ip_len
= ntohs(ip
->ip_len
);
4730 ip
->ip_off
= ntohs(ip
->ip_off
);
4733 * Run pfil on the member interface and the bridge, both can
4734 * be skipped by clearing pfil_member or pfil_bridge.
4737 * in_if -> bridge_if -> out_if
4739 if (pfil_bridge
&& dir
== PFIL_OUT
&& bifp
!= NULL
)
4740 error
= pfil_run_hooks(&inet_pfil_hook
, mp
, bifp
,
4743 if (*mp
== NULL
|| error
!= 0) /* filter may consume */
4746 if (pfil_member
&& ifp
!= NULL
)
4747 error
= pfil_run_hooks(&inet_pfil_hook
, mp
, ifp
,
4750 if (*mp
== NULL
|| error
!= 0) /* filter may consume */
4753 if (pfil_bridge
&& dir
== PFIL_IN
&& bifp
!= NULL
)
4754 error
= pfil_run_hooks(&inet_pfil_hook
, mp
, bifp
,
4757 if (*mp
== NULL
|| error
!= 0) /* filter may consume */
4760 /* check if we need to fragment the packet */
4761 if (pfil_member
&& ifp
!= NULL
&& dir
== PFIL_OUT
) {
4762 i
= (*mp
)->m_pkthdr
.len
;
4763 if (i
> ifp
->if_mtu
) {
4764 error
= bridge_fragment(ifp
, *mp
, &eh2
, snap
,
4770 /* Recalculate the ip checksum and restore byte ordering */
4771 ip
= mtod(*mp
, struct ip
*);
4772 hlen
= ip
->ip_hl
<< 2;
4773 if (hlen
< sizeof(struct ip
))
4775 if (hlen
> (*mp
)->m_len
) {
4776 if ((*mp
= m_pullup(*mp
, hlen
)) == 0)
4778 ip
= mtod(*mp
, struct ip
*);
4782 ip
->ip_len
= htons(ip
->ip_len
);
4783 ip
->ip_off
= htons(ip
->ip_off
);
4785 if (hlen
== sizeof(struct ip
))
4786 ip
->ip_sum
= in_cksum_hdr(ip
);
4788 ip
->ip_sum
= in_cksum(*mp
, hlen
);
4792 case ETHERTYPE_IPV6
:
4793 if (pfil_bridge
&& dir
== PFIL_OUT
&& bifp
!= NULL
)
4794 error
= pfil_run_hooks(&inet6_pfil_hook
, mp
, bifp
,
4797 if (*mp
== NULL
|| error
!= 0) /* filter may consume */
4800 if (pfil_member
&& ifp
!= NULL
)
4801 error
= pfil_run_hooks(&inet6_pfil_hook
, mp
, ifp
,
4804 if (*mp
== NULL
|| error
!= 0) /* filter may consume */
4807 if (pfil_bridge
&& dir
== PFIL_IN
&& bifp
!= NULL
)
4808 error
= pfil_run_hooks(&inet6_pfil_hook
, mp
, bifp
,
4825 * Finally, put everything back the way it was and return
4828 M_PREPEND(*mp
, sizeof(struct llc
), M_DONTWAIT
);
4831 bcopy(&llc1
, mtod(*mp
, caddr_t
), sizeof(struct llc
));
4834 M_PREPEND(*mp
, ETHER_HDR_LEN
, M_DONTWAIT
);
4837 bcopy(&eh2
, mtod(*mp
, caddr_t
), ETHER_HDR_LEN
);
4849 * Perform basic checks on header size since
4850 * pfil assumes ip_input has already processed
4851 * it for it. Cut-and-pasted from ip_input.c.
4852 * Given how simple the IPv6 version is,
4853 * does the IPv4 version really need to be
4856 * XXX Should we update ipstat here, or not?
4857 * XXX Right now we update ipstat but not
4861 bridge_ip_checkbasic(struct mbuf
**mp
)
4863 struct mbuf
*m
= *mp
;
4871 if (IP_HDR_ALIGNED_P(mtod(m
, caddr_t
)) == 0) {
4872 if ((m
= m_copyup(m
, sizeof(struct ip
),
4873 (max_linkhdr
+ 3) & ~3)) == NULL
) {
4874 /* XXXJRT new stat, please */
4875 ipstat
.ips_toosmall
++;
4878 } else if (__predict_false(m
->m_len
< sizeof (struct ip
))) {
4879 if ((m
= m_pullup(m
, sizeof (struct ip
))) == NULL
) {
4880 ipstat
.ips_toosmall
++;
4884 ip
= mtod(m
, struct ip
*);
4885 if (ip
== NULL
) goto bad
;
4887 if (ip
->ip_v
!= IPVERSION
) {
4888 ipstat
.ips_badvers
++;
4891 hlen
= ip
->ip_hl
<< 2;
4892 if (hlen
< sizeof(struct ip
)) { /* minimum header length */
4893 ipstat
.ips_badhlen
++;
4896 if (hlen
> m
->m_len
) {
4897 if ((m
= m_pullup(m
, hlen
)) == 0) {
4898 ipstat
.ips_badhlen
++;
4901 ip
= mtod(m
, struct ip
*);
4902 if (ip
== NULL
) goto bad
;
4905 if (m
->m_pkthdr
.csum_flags
& CSUM_IP_CHECKED
) {
4906 sum
= !(m
->m_pkthdr
.csum_flags
& CSUM_IP_VALID
);
4908 if (hlen
== sizeof(struct ip
)) {
4909 sum
= in_cksum_hdr(ip
);
4911 sum
= in_cksum(m
, hlen
);
4915 ipstat
.ips_badsum
++;
4919 /* Retrieve the packet length. */
4920 len
= ntohs(ip
->ip_len
);
4923 * Check for additional length bogosity
4926 ipstat
.ips_badlen
++;
4931 * Check that the amount of data in the buffers
4932 * is as at least much as the IP header would have us expect.
4933 * Drop packet if shorter than we expect.
4935 if (m
->m_pkthdr
.len
< len
) {
4936 ipstat
.ips_tooshort
++;
4940 /* Checks out, proceed */
4951 * Same as above, but for IPv6.
4952 * Cut-and-pasted from ip6_input.c.
4953 * XXX Should we update ip6stat, or not?
4956 bridge_ip6_checkbasic(struct mbuf
**mp
)
4958 struct mbuf
*m
= *mp
;
4959 struct ip6_hdr
*ip6
;
4962 * If the IPv6 header is not aligned, slurp it up into a new
4963 * mbuf with space for link headers, in the event we forward
4964 * it. Otherwise, if it is aligned, make sure the entire base
4965 * IPv6 header is in the first mbuf of the chain.
4967 if (IP6_HDR_ALIGNED_P(mtod(m
, caddr_t
)) == 0) {
4968 struct ifnet
*inifp
= m
->m_pkthdr
.rcvif
;
4969 if ((m
= m_copyup(m
, sizeof(struct ip6_hdr
),
4970 (max_linkhdr
+ 3) & ~3)) == NULL
) {
4971 /* XXXJRT new stat, please */
4972 ip6stat
.ip6s_toosmall
++;
4973 in6_ifstat_inc(inifp
, ifs6_in_hdrerr
);
4976 } else if (__predict_false(m
->m_len
< sizeof(struct ip6_hdr
))) {
4977 struct ifnet
*inifp
= m
->m_pkthdr
.rcvif
;
4978 if ((m
= m_pullup(m
, sizeof(struct ip6_hdr
))) == NULL
) {
4979 ip6stat
.ip6s_toosmall
++;
4980 in6_ifstat_inc(inifp
, ifs6_in_hdrerr
);
4985 ip6
= mtod(m
, struct ip6_hdr
*);
4987 if ((ip6
->ip6_vfc
& IPV6_VERSION_MASK
) != IPV6_VERSION
) {
4988 ip6stat
.ip6s_badvers
++;
4989 in6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_hdrerr
);
4993 /* Checks out, proceed */
5006 * Return a fragmented mbuf chain.
5009 bridge_fragment(struct ifnet
*ifp
, struct mbuf
*m
, struct ether_header
*eh
,
5010 int snap
, struct llc
*llc
)
5016 if (m
->m_len
< sizeof(struct ip
) &&
5017 (m
= m_pullup(m
, sizeof(struct ip
))) == NULL
)
5019 ip
= mtod(m
, struct ip
*);
5021 error
= ip_fragment(ip
, &m
, ifp
->if_mtu
, ifp
->if_hwassist
,
5026 /* walk the chain and re-add the Ethernet header */
5027 for (m0
= m
; m0
; m0
= m0
->m_nextpkt
) {
5030 M_PREPEND(m0
, sizeof(struct llc
), M_DONTWAIT
);
5035 bcopy(llc
, mtod(m0
, caddr_t
),
5036 sizeof(struct llc
));
5038 M_PREPEND(m0
, ETHER_HDR_LEN
, M_DONTWAIT
);
5043 bcopy(eh
, mtod(m0
, caddr_t
), ETHER_HDR_LEN
);
5049 ipstat
.ips_fragmented
++;
5058 #endif /* PFIL_HOOKS */
5061 bridge_set_bpf_tap(ifnet_t ifp
, bpf_tap_mode mode
, bpf_packet_func bpf_callback
)
5063 struct bridge_softc
*sc
= (struct bridge_softc
*)ifnet_softc(ifp
);
5065 //printf("bridge_set_bpf_tap ifp %p mode %d\n", ifp, mode);
5068 if (sc
== NULL
|| (sc
->sc_flags
& SCF_DETACHING
)) {
5073 case BPF_TAP_DISABLE
:
5074 sc
->sc_bpf_input
= sc
->sc_bpf_output
= NULL
;
5078 sc
->sc_bpf_input
= bpf_callback
;
5081 case BPF_TAP_OUTPUT
:
5082 sc
->sc_bpf_output
= bpf_callback
;
5085 case BPF_TAP_INPUT_OUTPUT
:
5086 sc
->sc_bpf_input
= sc
->sc_bpf_output
= bpf_callback
;
5097 bridge_detach(ifnet_t ifp
)
5099 struct bridge_softc
*sc
= (struct bridge_softc
*)ifnet_softc(ifp
);
5101 bstp_detach(&sc
->sc_stp
);
5103 /* Tear down the routing table. */
5104 bridge_rtable_fini(sc
);
5106 lck_mtx_lock(bridge_list_mtx
);
5107 LIST_REMOVE(sc
, sc_list
);
5108 lck_mtx_unlock(bridge_list_mtx
);
5112 lck_mtx_free(sc
->sc_mtx
, bridge_lock_grp
);
5114 _FREE(sc
, M_DEVBUF
);
5118 __private_extern__ errno_t
bridge_bpf_input(ifnet_t ifp
, struct mbuf
*m
)
5120 struct bridge_softc
*sc
= (struct bridge_softc
*)ifnet_softc(ifp
);
5122 if (sc
->sc_bpf_input
) {
5123 if (mbuf_pkthdr_rcvif(m
) != ifp
)
5124 printf("bridge_bpf_input rcvif: %p != ifp %p\n", mbuf_pkthdr_rcvif(m
), ifp
);
5125 (*sc
->sc_bpf_input
)(ifp
, m
);
5130 __private_extern__ errno_t
bridge_bpf_output(ifnet_t ifp
, struct mbuf
*m
)
5132 struct bridge_softc
*sc
= (struct bridge_softc
*)ifnet_softc(ifp
);
5134 if (sc
->sc_bpf_output
) {
5135 (*sc
->sc_bpf_output
)(ifp
, m
);