Sat Dec 22 04:28:30 2018 UTC ()
Take the interface out of promiscuous mode in bridge_delete_member()
instead of bridge_ioctl_del(). Otherwise, the member interfaces are
left in promiscuous mode when the bridge is destroyed.


(rin)
diff -r1.163 -r1.164 src/sys/net/if_bridge.c

cvs diff -r1.163 -r1.164 src/sys/net/if_bridge.c (switch to unified diff)

--- src/sys/net/if_bridge.c 2018/12/15 07:38:58 1.163
+++ src/sys/net/if_bridge.c 2018/12/22 04:28:30 1.164
@@ -1,1917 +1,1917 @@ @@ -1,1917 +1,1917 @@
1/* $NetBSD: if_bridge.c,v 1.163 2018/12/15 07:38:58 rin Exp $ */ 1/* $NetBSD: if_bridge.c,v 1.164 2018/12/22 04:28:30 rin Exp $ */
2 2
3/* 3/*
4 * Copyright 2001 Wasabi Systems, Inc. 4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38/* 38/*
39 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) 39 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
40 * All rights reserved. 40 * All rights reserved.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by Jason L. Wright 52 * This product includes software developed by Jason L. Wright
53 * 4. The name of the author may not be used to endorse or promote products 53 * 4. The name of the author may not be used to endorse or promote products
54 * derived from this software without specific prior written permission. 54 * derived from this software without specific prior written permission.
55 * 55 *
56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
60 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 60 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
61 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 61 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
64 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 64 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
65 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 65 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 * POSSIBILITY OF SUCH DAMAGE. 66 * POSSIBILITY OF SUCH DAMAGE.
67 * 67 *
68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp 68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp
69 */ 69 */
70 70
71/* 71/*
72 * Network interface bridge support. 72 * Network interface bridge support.
73 * 73 *
74 * TODO: 74 * TODO:
75 * 75 *
76 * - Currently only supports Ethernet-like interfaces (Ethernet, 76 * - Currently only supports Ethernet-like interfaces (Ethernet,
77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way 77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way
78 * to bridge other types of interfaces (FDDI-FDDI, and maybe 78 * to bridge other types of interfaces (FDDI-FDDI, and maybe
79 * consider heterogenous bridges). 79 * consider heterogenous bridges).
80 */ 80 */
81 81
82#include <sys/cdefs.h> 82#include <sys/cdefs.h>
83__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.163 2018/12/15 07:38:58 rin Exp $"); 83__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.164 2018/12/22 04:28:30 rin Exp $");
84 84
85#ifdef _KERNEL_OPT 85#ifdef _KERNEL_OPT
86#include "opt_bridge_ipf.h" 86#include "opt_bridge_ipf.h"
87#include "opt_inet.h" 87#include "opt_inet.h"
88#include "opt_net_mpsafe.h" 88#include "opt_net_mpsafe.h"
89#endif /* _KERNEL_OPT */ 89#endif /* _KERNEL_OPT */
90 90
91#include <sys/param.h> 91#include <sys/param.h>
92#include <sys/kernel.h> 92#include <sys/kernel.h>
93#include <sys/mbuf.h> 93#include <sys/mbuf.h>
94#include <sys/queue.h> 94#include <sys/queue.h>
95#include <sys/socket.h> 95#include <sys/socket.h>
96#include <sys/socketvar.h> /* for softnet_lock */ 96#include <sys/socketvar.h> /* for softnet_lock */
97#include <sys/sockio.h> 97#include <sys/sockio.h>
98#include <sys/systm.h> 98#include <sys/systm.h>
99#include <sys/proc.h> 99#include <sys/proc.h>
100#include <sys/pool.h> 100#include <sys/pool.h>
101#include <sys/kauth.h> 101#include <sys/kauth.h>
102#include <sys/cpu.h> 102#include <sys/cpu.h>
103#include <sys/cprng.h> 103#include <sys/cprng.h>
104#include <sys/mutex.h> 104#include <sys/mutex.h>
105#include <sys/kmem.h> 105#include <sys/kmem.h>
106 106
107#include <net/bpf.h> 107#include <net/bpf.h>
108#include <net/if.h> 108#include <net/if.h>
109#include <net/if_dl.h> 109#include <net/if_dl.h>
110#include <net/if_types.h> 110#include <net/if_types.h>
111#include <net/if_llc.h> 111#include <net/if_llc.h>
112 112
113#include <net/if_ether.h> 113#include <net/if_ether.h>
114#include <net/if_bridgevar.h> 114#include <net/if_bridgevar.h>
115#include <net/ether_sw_offload.h> 115#include <net/ether_sw_offload.h>
116 116
117#if defined(BRIDGE_IPF) 117#if defined(BRIDGE_IPF)
118/* Used for bridge_ip[6]_checkbasic */ 118/* Used for bridge_ip[6]_checkbasic */
119#include <netinet/in.h> 119#include <netinet/in.h>
120#include <netinet/in_systm.h> 120#include <netinet/in_systm.h>
121#include <netinet/ip.h> 121#include <netinet/ip.h>
122#include <netinet/ip_var.h> 122#include <netinet/ip_var.h>
123#include <netinet/ip_private.h> /* XXX */ 123#include <netinet/ip_private.h> /* XXX */
124 124
125#include <netinet/ip6.h> 125#include <netinet/ip6.h>
126#include <netinet6/in6_var.h> 126#include <netinet6/in6_var.h>
127#include <netinet6/ip6_var.h> 127#include <netinet6/ip6_var.h>
128#include <netinet6/ip6_private.h> /* XXX */ 128#include <netinet6/ip6_private.h> /* XXX */
129#endif /* BRIDGE_IPF */ 129#endif /* BRIDGE_IPF */
130 130
131/* 131/*
132 * Size of the route hash table. Must be a power of two. 132 * Size of the route hash table. Must be a power of two.
133 */ 133 */
134#ifndef BRIDGE_RTHASH_SIZE 134#ifndef BRIDGE_RTHASH_SIZE
135#define BRIDGE_RTHASH_SIZE 1024 135#define BRIDGE_RTHASH_SIZE 1024
136#endif 136#endif
137 137
138#define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1) 138#define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1)
139 139
140#include "carp.h" 140#include "carp.h"
141#if NCARP > 0 141#if NCARP > 0
142#include <netinet/in.h> 142#include <netinet/in.h>
143#include <netinet/in_var.h> 143#include <netinet/in_var.h>
144#include <netinet/ip_carp.h> 144#include <netinet/ip_carp.h>
145#endif 145#endif
146 146
147#include "ioconf.h" 147#include "ioconf.h"
148 148
149__CTASSERT(sizeof(struct ifbifconf) == sizeof(struct ifbaconf)); 149__CTASSERT(sizeof(struct ifbifconf) == sizeof(struct ifbaconf));
150__CTASSERT(offsetof(struct ifbifconf, ifbic_len) == offsetof(struct ifbaconf, ifbac_len)); 150__CTASSERT(offsetof(struct ifbifconf, ifbic_len) == offsetof(struct ifbaconf, ifbac_len));
151__CTASSERT(offsetof(struct ifbifconf, ifbic_buf) == offsetof(struct ifbaconf, ifbac_buf)); 151__CTASSERT(offsetof(struct ifbifconf, ifbic_buf) == offsetof(struct ifbaconf, ifbac_buf));
152 152
153/* 153/*
154 * Maximum number of addresses to cache. 154 * Maximum number of addresses to cache.
155 */ 155 */
156#ifndef BRIDGE_RTABLE_MAX 156#ifndef BRIDGE_RTABLE_MAX
157#define BRIDGE_RTABLE_MAX 100 157#define BRIDGE_RTABLE_MAX 100
158#endif 158#endif
159 159
160/* 160/*
161 * Spanning tree defaults. 161 * Spanning tree defaults.
162 */ 162 */
163#define BSTP_DEFAULT_MAX_AGE (20 * 256) 163#define BSTP_DEFAULT_MAX_AGE (20 * 256)
164#define BSTP_DEFAULT_HELLO_TIME (2 * 256) 164#define BSTP_DEFAULT_HELLO_TIME (2 * 256)
165#define BSTP_DEFAULT_FORWARD_DELAY (15 * 256) 165#define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
166#define BSTP_DEFAULT_HOLD_TIME (1 * 256) 166#define BSTP_DEFAULT_HOLD_TIME (1 * 256)
167#define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000 167#define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
168#define BSTP_DEFAULT_PORT_PRIORITY 0x80 168#define BSTP_DEFAULT_PORT_PRIORITY 0x80
169#define BSTP_DEFAULT_PATH_COST 55 169#define BSTP_DEFAULT_PATH_COST 55
170 170
171/* 171/*
172 * Timeout (in seconds) for entries learned dynamically. 172 * Timeout (in seconds) for entries learned dynamically.
173 */ 173 */
174#ifndef BRIDGE_RTABLE_TIMEOUT 174#ifndef BRIDGE_RTABLE_TIMEOUT
175#define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */ 175#define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */
176#endif 176#endif
177 177
178/* 178/*
179 * Number of seconds between walks of the route list. 179 * Number of seconds between walks of the route list.
180 */ 180 */
181#ifndef BRIDGE_RTABLE_PRUNE_PERIOD 181#ifndef BRIDGE_RTABLE_PRUNE_PERIOD
182#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60) 182#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60)
183#endif 183#endif
184 184
185#define BRIDGE_RT_LOCK(_sc) mutex_enter((_sc)->sc_rtlist_lock) 185#define BRIDGE_RT_LOCK(_sc) mutex_enter((_sc)->sc_rtlist_lock)
186#define BRIDGE_RT_UNLOCK(_sc) mutex_exit((_sc)->sc_rtlist_lock) 186#define BRIDGE_RT_UNLOCK(_sc) mutex_exit((_sc)->sc_rtlist_lock)
187#define BRIDGE_RT_LOCKED(_sc) mutex_owned((_sc)->sc_rtlist_lock) 187#define BRIDGE_RT_LOCKED(_sc) mutex_owned((_sc)->sc_rtlist_lock)
188 188
189#define BRIDGE_RT_PSZ_PERFORM(_sc) \ 189#define BRIDGE_RT_PSZ_PERFORM(_sc) \
190 pserialize_perform((_sc)->sc_rtlist_psz) 190 pserialize_perform((_sc)->sc_rtlist_psz)
191 191
192#define BRIDGE_RT_RENTER(__s) do { __s = pserialize_read_enter(); } while (0) 192#define BRIDGE_RT_RENTER(__s) do { __s = pserialize_read_enter(); } while (0)
193#define BRIDGE_RT_REXIT(__s) do { pserialize_read_exit(__s); } while (0) 193#define BRIDGE_RT_REXIT(__s) do { pserialize_read_exit(__s); } while (0)
194 194
195#define BRIDGE_RTLIST_READER_FOREACH(_brt, _sc) \ 195#define BRIDGE_RTLIST_READER_FOREACH(_brt, _sc) \
196 PSLIST_READER_FOREACH((_brt), &((_sc)->sc_rtlist), \ 196 PSLIST_READER_FOREACH((_brt), &((_sc)->sc_rtlist), \
197 struct bridge_rtnode, brt_list) 197 struct bridge_rtnode, brt_list)
198#define BRIDGE_RTLIST_WRITER_FOREACH(_brt, _sc) \ 198#define BRIDGE_RTLIST_WRITER_FOREACH(_brt, _sc) \
199 PSLIST_WRITER_FOREACH((_brt), &((_sc)->sc_rtlist), \ 199 PSLIST_WRITER_FOREACH((_brt), &((_sc)->sc_rtlist), \
200 struct bridge_rtnode, brt_list) 200 struct bridge_rtnode, brt_list)
201#define BRIDGE_RTLIST_WRITER_INSERT_HEAD(_sc, _brt) \ 201#define BRIDGE_RTLIST_WRITER_INSERT_HEAD(_sc, _brt) \
202 PSLIST_WRITER_INSERT_HEAD(&(_sc)->sc_rtlist, brt, brt_list) 202 PSLIST_WRITER_INSERT_HEAD(&(_sc)->sc_rtlist, brt, brt_list)
203#define BRIDGE_RTLIST_WRITER_REMOVE(_brt) \ 203#define BRIDGE_RTLIST_WRITER_REMOVE(_brt) \
204 PSLIST_WRITER_REMOVE((_brt), brt_list) 204 PSLIST_WRITER_REMOVE((_brt), brt_list)
205 205
206#define BRIDGE_RTHASH_READER_FOREACH(_brt, _sc, _hash) \ 206#define BRIDGE_RTHASH_READER_FOREACH(_brt, _sc, _hash) \
207 PSLIST_READER_FOREACH((_brt), &(_sc)->sc_rthash[(_hash)], \ 207 PSLIST_READER_FOREACH((_brt), &(_sc)->sc_rthash[(_hash)], \
208 struct bridge_rtnode, brt_hash) 208 struct bridge_rtnode, brt_hash)
209#define BRIDGE_RTHASH_WRITER_FOREACH(_brt, _sc, _hash) \ 209#define BRIDGE_RTHASH_WRITER_FOREACH(_brt, _sc, _hash) \
210 PSLIST_WRITER_FOREACH((_brt), &(_sc)->sc_rthash[(_hash)], \ 210 PSLIST_WRITER_FOREACH((_brt), &(_sc)->sc_rthash[(_hash)], \
211 struct bridge_rtnode, brt_hash) 211 struct bridge_rtnode, brt_hash)
212#define BRIDGE_RTHASH_WRITER_INSERT_HEAD(_sc, _hash, _brt) \ 212#define BRIDGE_RTHASH_WRITER_INSERT_HEAD(_sc, _hash, _brt) \
213 PSLIST_WRITER_INSERT_HEAD(&(_sc)->sc_rthash[(_hash)], brt, brt_hash) 213 PSLIST_WRITER_INSERT_HEAD(&(_sc)->sc_rthash[(_hash)], brt, brt_hash)
214#define BRIDGE_RTHASH_WRITER_INSERT_AFTER(_brt, _new) \ 214#define BRIDGE_RTHASH_WRITER_INSERT_AFTER(_brt, _new) \
215 PSLIST_WRITER_INSERT_AFTER((_brt), (_new), brt_hash) 215 PSLIST_WRITER_INSERT_AFTER((_brt), (_new), brt_hash)
216#define BRIDGE_RTHASH_WRITER_REMOVE(_brt) \ 216#define BRIDGE_RTHASH_WRITER_REMOVE(_brt) \
217 PSLIST_WRITER_REMOVE((_brt), brt_hash) 217 PSLIST_WRITER_REMOVE((_brt), brt_hash)
218 218
219#ifdef NET_MPSAFE 219#ifdef NET_MPSAFE
220#define DECLARE_LOCK_VARIABLE 220#define DECLARE_LOCK_VARIABLE
221#define ACQUIRE_GLOBAL_LOCKS() do { } while (0) 221#define ACQUIRE_GLOBAL_LOCKS() do { } while (0)
222#define RELEASE_GLOBAL_LOCKS() do { } while (0) 222#define RELEASE_GLOBAL_LOCKS() do { } while (0)
223#else 223#else
224#define DECLARE_LOCK_VARIABLE int __s 224#define DECLARE_LOCK_VARIABLE int __s
225#define ACQUIRE_GLOBAL_LOCKS() do { \ 225#define ACQUIRE_GLOBAL_LOCKS() do { \
226 KERNEL_LOCK(1, NULL); \ 226 KERNEL_LOCK(1, NULL); \
227 mutex_enter(softnet_lock); \ 227 mutex_enter(softnet_lock); \
228 __s = splsoftnet(); \ 228 __s = splsoftnet(); \
229 } while (0) 229 } while (0)
230#define RELEASE_GLOBAL_LOCKS() do { \ 230#define RELEASE_GLOBAL_LOCKS() do { \
231 splx(__s); \ 231 splx(__s); \
232 mutex_exit(softnet_lock); \ 232 mutex_exit(softnet_lock); \
233 KERNEL_UNLOCK_ONE(NULL); \ 233 KERNEL_UNLOCK_ONE(NULL); \
234 } while (0) 234 } while (0)
235#endif 235#endif
236 236
237struct psref_class *bridge_psref_class __read_mostly; 237struct psref_class *bridge_psref_class __read_mostly;
238 238
239int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; 239int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD;
240 240
241static struct pool bridge_rtnode_pool; 241static struct pool bridge_rtnode_pool;
242 242
243static int bridge_clone_create(struct if_clone *, int); 243static int bridge_clone_create(struct if_clone *, int);
244static int bridge_clone_destroy(struct ifnet *); 244static int bridge_clone_destroy(struct ifnet *);
245 245
246static int bridge_ioctl(struct ifnet *, u_long, void *); 246static int bridge_ioctl(struct ifnet *, u_long, void *);
247static int bridge_init(struct ifnet *); 247static int bridge_init(struct ifnet *);
248static void bridge_stop(struct ifnet *, int); 248static void bridge_stop(struct ifnet *, int);
249static void bridge_start(struct ifnet *); 249static void bridge_start(struct ifnet *);
250 250
251static void bridge_input(struct ifnet *, struct mbuf *); 251static void bridge_input(struct ifnet *, struct mbuf *);
252static void bridge_forward(struct bridge_softc *, struct mbuf *); 252static void bridge_forward(struct bridge_softc *, struct mbuf *);
253 253
254static void bridge_timer(void *); 254static void bridge_timer(void *);
255 255
256static void bridge_broadcast(struct bridge_softc *, struct ifnet *, 256static void bridge_broadcast(struct bridge_softc *, struct ifnet *,
257 struct mbuf *); 257 struct mbuf *);
258 258
259static int bridge_rtupdate(struct bridge_softc *, const uint8_t *, 259static int bridge_rtupdate(struct bridge_softc *, const uint8_t *,
260 struct ifnet *, int, uint8_t); 260 struct ifnet *, int, uint8_t);
261static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *); 261static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *);
262static void bridge_rttrim(struct bridge_softc *); 262static void bridge_rttrim(struct bridge_softc *);
263static void bridge_rtage(struct bridge_softc *); 263static void bridge_rtage(struct bridge_softc *);
264static void bridge_rtage_work(struct work *, void *); 264static void bridge_rtage_work(struct work *, void *);
265static void bridge_rtflush(struct bridge_softc *, int); 265static void bridge_rtflush(struct bridge_softc *, int);
266static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *); 266static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
267static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp); 267static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp);
268 268
269static void bridge_rtable_init(struct bridge_softc *); 269static void bridge_rtable_init(struct bridge_softc *);
270static void bridge_rtable_fini(struct bridge_softc *); 270static void bridge_rtable_fini(struct bridge_softc *);
271 271
272static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *, 272static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
273 const uint8_t *); 273 const uint8_t *);
274static int bridge_rtnode_insert(struct bridge_softc *, 274static int bridge_rtnode_insert(struct bridge_softc *,
275 struct bridge_rtnode *); 275 struct bridge_rtnode *);
276static void bridge_rtnode_remove(struct bridge_softc *, 276static void bridge_rtnode_remove(struct bridge_softc *,
277 struct bridge_rtnode *); 277 struct bridge_rtnode *);
278static void bridge_rtnode_destroy(struct bridge_rtnode *); 278static void bridge_rtnode_destroy(struct bridge_rtnode *);
279 279
280static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *, 280static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *,
281 const char *name, 281 const char *name,
282 struct psref *); 282 struct psref *);
283static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *, 283static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *,
284 struct ifnet *ifp, 284 struct ifnet *ifp,
285 struct psref *); 285 struct psref *);
286static void bridge_release_member(struct bridge_softc *, struct bridge_iflist *, 286static void bridge_release_member(struct bridge_softc *, struct bridge_iflist *,
287 struct psref *); 287 struct psref *);
288static void bridge_delete_member(struct bridge_softc *, 288static void bridge_delete_member(struct bridge_softc *,
289 struct bridge_iflist *); 289 struct bridge_iflist *);
290static void bridge_acquire_member(struct bridge_softc *sc, 290static void bridge_acquire_member(struct bridge_softc *sc,
291 struct bridge_iflist *, 291 struct bridge_iflist *,
292 struct psref *); 292 struct psref *);
293 293
294static int bridge_ioctl_add(struct bridge_softc *, void *); 294static int bridge_ioctl_add(struct bridge_softc *, void *);
295static int bridge_ioctl_del(struct bridge_softc *, void *); 295static int bridge_ioctl_del(struct bridge_softc *, void *);
296static int bridge_ioctl_gifflags(struct bridge_softc *, void *); 296static int bridge_ioctl_gifflags(struct bridge_softc *, void *);
297static int bridge_ioctl_sifflags(struct bridge_softc *, void *); 297static int bridge_ioctl_sifflags(struct bridge_softc *, void *);
298static int bridge_ioctl_scache(struct bridge_softc *, void *); 298static int bridge_ioctl_scache(struct bridge_softc *, void *);
299static int bridge_ioctl_gcache(struct bridge_softc *, void *); 299static int bridge_ioctl_gcache(struct bridge_softc *, void *);
300static int bridge_ioctl_gifs(struct bridge_softc *, void *); 300static int bridge_ioctl_gifs(struct bridge_softc *, void *);
301static int bridge_ioctl_rts(struct bridge_softc *, void *); 301static int bridge_ioctl_rts(struct bridge_softc *, void *);
302static int bridge_ioctl_saddr(struct bridge_softc *, void *); 302static int bridge_ioctl_saddr(struct bridge_softc *, void *);
303static int bridge_ioctl_sto(struct bridge_softc *, void *); 303static int bridge_ioctl_sto(struct bridge_softc *, void *);
304static int bridge_ioctl_gto(struct bridge_softc *, void *); 304static int bridge_ioctl_gto(struct bridge_softc *, void *);
305static int bridge_ioctl_daddr(struct bridge_softc *, void *); 305static int bridge_ioctl_daddr(struct bridge_softc *, void *);
306static int bridge_ioctl_flush(struct bridge_softc *, void *); 306static int bridge_ioctl_flush(struct bridge_softc *, void *);
307static int bridge_ioctl_gpri(struct bridge_softc *, void *); 307static int bridge_ioctl_gpri(struct bridge_softc *, void *);
308static int bridge_ioctl_spri(struct bridge_softc *, void *); 308static int bridge_ioctl_spri(struct bridge_softc *, void *);
309static int bridge_ioctl_ght(struct bridge_softc *, void *); 309static int bridge_ioctl_ght(struct bridge_softc *, void *);
310static int bridge_ioctl_sht(struct bridge_softc *, void *); 310static int bridge_ioctl_sht(struct bridge_softc *, void *);
311static int bridge_ioctl_gfd(struct bridge_softc *, void *); 311static int bridge_ioctl_gfd(struct bridge_softc *, void *);
312static int bridge_ioctl_sfd(struct bridge_softc *, void *); 312static int bridge_ioctl_sfd(struct bridge_softc *, void *);
313static int bridge_ioctl_gma(struct bridge_softc *, void *); 313static int bridge_ioctl_gma(struct bridge_softc *, void *);
314static int bridge_ioctl_sma(struct bridge_softc *, void *); 314static int bridge_ioctl_sma(struct bridge_softc *, void *);
315static int bridge_ioctl_sifprio(struct bridge_softc *, void *); 315static int bridge_ioctl_sifprio(struct bridge_softc *, void *);
316static int bridge_ioctl_sifcost(struct bridge_softc *, void *); 316static int bridge_ioctl_sifcost(struct bridge_softc *, void *);
317#if defined(BRIDGE_IPF) 317#if defined(BRIDGE_IPF)
318static int bridge_ioctl_gfilt(struct bridge_softc *, void *); 318static int bridge_ioctl_gfilt(struct bridge_softc *, void *);
319static int bridge_ioctl_sfilt(struct bridge_softc *, void *); 319static int bridge_ioctl_sfilt(struct bridge_softc *, void *);
320static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int); 320static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int);
321static int bridge_ip_checkbasic(struct mbuf **mp); 321static int bridge_ip_checkbasic(struct mbuf **mp);
322# ifdef INET6 322# ifdef INET6
323static int bridge_ip6_checkbasic(struct mbuf **mp); 323static int bridge_ip6_checkbasic(struct mbuf **mp);
324# endif /* INET6 */ 324# endif /* INET6 */
325#endif /* BRIDGE_IPF */ 325#endif /* BRIDGE_IPF */
326 326
327struct bridge_control { 327struct bridge_control {
328 int (*bc_func)(struct bridge_softc *, void *); 328 int (*bc_func)(struct bridge_softc *, void *);
329 int bc_argsize; 329 int bc_argsize;
330 int bc_flags; 330 int bc_flags;
331}; 331};
332 332
333#define BC_F_COPYIN 0x01 /* copy arguments in */ 333#define BC_F_COPYIN 0x01 /* copy arguments in */
334#define BC_F_COPYOUT 0x02 /* copy arguments out */ 334#define BC_F_COPYOUT 0x02 /* copy arguments out */
335#define BC_F_SUSER 0x04 /* do super-user check */ 335#define BC_F_SUSER 0x04 /* do super-user check */
336#define BC_F_XLATEIN 0x08 /* xlate arguments in */ 336#define BC_F_XLATEIN 0x08 /* xlate arguments in */
337#define BC_F_XLATEOUT 0x10 /* xlate arguments out */ 337#define BC_F_XLATEOUT 0x10 /* xlate arguments out */
338 338
339static const struct bridge_control bridge_control_table[] = { 339static const struct bridge_control bridge_control_table[] = {
340[BRDGADD] = {bridge_ioctl_add, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 340[BRDGADD] = {bridge_ioctl_add, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
341[BRDGDEL] = {bridge_ioctl_del, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},  341[BRDGDEL] = {bridge_ioctl_del, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
342 342
343[BRDGGIFFLGS] = {bridge_ioctl_gifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_COPYOUT},  343[BRDGGIFFLGS] = {bridge_ioctl_gifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_COPYOUT},
344[BRDGSIFFLGS] = {bridge_ioctl_sifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},  344[BRDGSIFFLGS] = {bridge_ioctl_sifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
345 345
346[BRDGSCACHE] = {bridge_ioctl_scache, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  346[BRDGSCACHE] = {bridge_ioctl_scache, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
347[BRDGGCACHE] = {bridge_ioctl_gcache, sizeof(struct ifbrparam), BC_F_COPYOUT},  347[BRDGGCACHE] = {bridge_ioctl_gcache, sizeof(struct ifbrparam), BC_F_COPYOUT},
348 348
349[OBRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_COPYIN|BC_F_COPYOUT},  349[OBRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_COPYIN|BC_F_COPYOUT},
350[OBRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_COPYIN|BC_F_COPYOUT},  350[OBRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_COPYIN|BC_F_COPYOUT},
351 351
352[BRDGSADDR] = {bridge_ioctl_saddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},  352[BRDGSADDR] = {bridge_ioctl_saddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},
353 353
354[BRDGSTO] = {bridge_ioctl_sto, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  354[BRDGSTO] = {bridge_ioctl_sto, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
355[BRDGGTO] = {bridge_ioctl_gto, sizeof(struct ifbrparam), BC_F_COPYOUT},  355[BRDGGTO] = {bridge_ioctl_gto, sizeof(struct ifbrparam), BC_F_COPYOUT},
356 356
357[BRDGDADDR] = {bridge_ioctl_daddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},  357[BRDGDADDR] = {bridge_ioctl_daddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER},
358 358
359[BRDGFLUSH] = {bridge_ioctl_flush, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},  359[BRDGFLUSH] = {bridge_ioctl_flush, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
360 360
361[BRDGGPRI] = {bridge_ioctl_gpri, sizeof(struct ifbrparam), BC_F_COPYOUT},  361[BRDGGPRI] = {bridge_ioctl_gpri, sizeof(struct ifbrparam), BC_F_COPYOUT},
362[BRDGSPRI] = {bridge_ioctl_spri, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  362[BRDGSPRI] = {bridge_ioctl_spri, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
363 363
364[BRDGGHT] = {bridge_ioctl_ght, sizeof(struct ifbrparam), BC_F_COPYOUT},  364[BRDGGHT] = {bridge_ioctl_ght, sizeof(struct ifbrparam), BC_F_COPYOUT},
365[BRDGSHT] = {bridge_ioctl_sht, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  365[BRDGSHT] = {bridge_ioctl_sht, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
366 366
367[BRDGGFD] = {bridge_ioctl_gfd, sizeof(struct ifbrparam), BC_F_COPYOUT},  367[BRDGGFD] = {bridge_ioctl_gfd, sizeof(struct ifbrparam), BC_F_COPYOUT},
368[BRDGSFD] = {bridge_ioctl_sfd, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  368[BRDGSFD] = {bridge_ioctl_sfd, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
369 369
370[BRDGGMA] = {bridge_ioctl_gma, sizeof(struct ifbrparam), BC_F_COPYOUT},  370[BRDGGMA] = {bridge_ioctl_gma, sizeof(struct ifbrparam), BC_F_COPYOUT},
371[BRDGSMA] = {bridge_ioctl_sma, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},  371[BRDGSMA] = {bridge_ioctl_sma, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
372 372
373[BRDGSIFPRIO] = {bridge_ioctl_sifprio, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},  373[BRDGSIFPRIO] = {bridge_ioctl_sifprio, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
374 374
375[BRDGSIFCOST] = {bridge_ioctl_sifcost, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},  375[BRDGSIFCOST] = {bridge_ioctl_sifcost, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER},
376#if defined(BRIDGE_IPF) 376#if defined(BRIDGE_IPF)
377[BRDGGFILT] = {bridge_ioctl_gfilt, sizeof(struct ifbrparam), BC_F_COPYOUT}, 377[BRDGGFILT] = {bridge_ioctl_gfilt, sizeof(struct ifbrparam), BC_F_COPYOUT},
378[BRDGSFILT] = {bridge_ioctl_sfilt, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 378[BRDGSFILT] = {bridge_ioctl_sfilt, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER},
379#endif /* BRIDGE_IPF */ 379#endif /* BRIDGE_IPF */
380[BRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_XLATEIN|BC_F_XLATEOUT}, 380[BRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_XLATEIN|BC_F_XLATEOUT},
381[BRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_XLATEIN|BC_F_XLATEOUT}, 381[BRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_XLATEIN|BC_F_XLATEOUT},
382}; 382};
383 383
384static const int bridge_control_table_size = __arraycount(bridge_control_table); 384static const int bridge_control_table_size = __arraycount(bridge_control_table);
385 385
386static struct if_clone bridge_cloner = 386static struct if_clone bridge_cloner =
387 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy); 387 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
388 388
389/* 389/*
390 * bridgeattach: 390 * bridgeattach:
391 * 391 *
392 * Pseudo-device attach routine. 392 * Pseudo-device attach routine.
393 */ 393 */
394void 394void
395bridgeattach(int n) 395bridgeattach(int n)
396{ 396{
397 397
398 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode), 398 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode),
399 0, 0, 0, "brtpl", NULL, IPL_NET); 399 0, 0, 0, "brtpl", NULL, IPL_NET);
400 400
401 bridge_psref_class = psref_class_create("bridge", IPL_SOFTNET); 401 bridge_psref_class = psref_class_create("bridge", IPL_SOFTNET);
402 402
403 if_clone_attach(&bridge_cloner); 403 if_clone_attach(&bridge_cloner);
404} 404}
405 405
406/* 406/*
407 * bridge_clone_create: 407 * bridge_clone_create:
408 * 408 *
409 * Create a new bridge instance. 409 * Create a new bridge instance.
410 */ 410 */
411static int 411static int
412bridge_clone_create(struct if_clone *ifc, int unit) 412bridge_clone_create(struct if_clone *ifc, int unit)
413{ 413{
414 struct bridge_softc *sc; 414 struct bridge_softc *sc;
415 struct ifnet *ifp; 415 struct ifnet *ifp;
416 int error; 416 int error;
417 417
418 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 418 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
419 ifp = &sc->sc_if; 419 ifp = &sc->sc_if;
420 420
421 sc->sc_brtmax = BRIDGE_RTABLE_MAX; 421 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
422 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT; 422 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
423 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; 423 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
424 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; 424 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
425 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY; 425 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY;
426 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; 426 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
427 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME; 427 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
428 sc->sc_filter_flags = 0; 428 sc->sc_filter_flags = 0;
429 429
430 /* Initialize our routing table. */ 430 /* Initialize our routing table. */
431 bridge_rtable_init(sc); 431 bridge_rtable_init(sc);
432 432
433 error = workqueue_create(&sc->sc_rtage_wq, "bridge_rtage", 433 error = workqueue_create(&sc->sc_rtage_wq, "bridge_rtage",
434 bridge_rtage_work, sc, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE); 434 bridge_rtage_work, sc, PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE);
435 if (error) 435 if (error)
436 panic("%s: workqueue_create %d\n", __func__, error); 436 panic("%s: workqueue_create %d\n", __func__, error);
437 437
438 callout_init(&sc->sc_brcallout, CALLOUT_MPSAFE); 438 callout_init(&sc->sc_brcallout, CALLOUT_MPSAFE);
439 callout_init(&sc->sc_bstpcallout, CALLOUT_MPSAFE); 439 callout_init(&sc->sc_bstpcallout, CALLOUT_MPSAFE);
440 440
441 mutex_init(&sc->sc_iflist_psref.bip_lock, MUTEX_DEFAULT, IPL_NONE); 441 mutex_init(&sc->sc_iflist_psref.bip_lock, MUTEX_DEFAULT, IPL_NONE);
442 PSLIST_INIT(&sc->sc_iflist_psref.bip_iflist); 442 PSLIST_INIT(&sc->sc_iflist_psref.bip_iflist);
443 sc->sc_iflist_psref.bip_psz = pserialize_create(); 443 sc->sc_iflist_psref.bip_psz = pserialize_create();
444 444
445 if_initname(ifp, ifc->ifc_name, unit); 445 if_initname(ifp, ifc->ifc_name, unit);
446 ifp->if_softc = sc; 446 ifp->if_softc = sc;
447 ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE; 447 ifp->if_extflags = IFEF_NO_LINK_STATE_CHANGE;
448#ifdef NET_MPSAFE 448#ifdef NET_MPSAFE
449 ifp->if_extflags |= IFEF_MPSAFE; 449 ifp->if_extflags |= IFEF_MPSAFE;
450#endif 450#endif
451 ifp->if_mtu = ETHERMTU; 451 ifp->if_mtu = ETHERMTU;
452 ifp->if_ioctl = bridge_ioctl; 452 ifp->if_ioctl = bridge_ioctl;
453 ifp->if_output = bridge_output; 453 ifp->if_output = bridge_output;
454 ifp->if_start = bridge_start; 454 ifp->if_start = bridge_start;
455 ifp->if_stop = bridge_stop; 455 ifp->if_stop = bridge_stop;
456 ifp->if_init = bridge_init; 456 ifp->if_init = bridge_init;
457 ifp->if_type = IFT_BRIDGE; 457 ifp->if_type = IFT_BRIDGE;
458 ifp->if_addrlen = 0; 458 ifp->if_addrlen = 0;
459 ifp->if_dlt = DLT_EN10MB; 459 ifp->if_dlt = DLT_EN10MB;
460 ifp->if_hdrlen = ETHER_HDR_LEN; 460 ifp->if_hdrlen = ETHER_HDR_LEN;
461 461
462 error = if_initialize(ifp); 462 error = if_initialize(ifp);
463 if (error != 0) { 463 if (error != 0) {
464 pserialize_destroy(sc->sc_iflist_psref.bip_psz); 464 pserialize_destroy(sc->sc_iflist_psref.bip_psz);
465 mutex_destroy(&sc->sc_iflist_psref.bip_lock); 465 mutex_destroy(&sc->sc_iflist_psref.bip_lock);
466 callout_destroy(&sc->sc_brcallout); 466 callout_destroy(&sc->sc_brcallout);
467 callout_destroy(&sc->sc_bstpcallout); 467 callout_destroy(&sc->sc_bstpcallout);
468 workqueue_destroy(sc->sc_rtage_wq); 468 workqueue_destroy(sc->sc_rtage_wq);
469 bridge_rtable_fini(sc); 469 bridge_rtable_fini(sc);
470 kmem_free(sc, sizeof(*sc)); 470 kmem_free(sc, sizeof(*sc));
471 471
472 return error; 472 return error;
473 } 473 }
474 if_alloc_sadl(ifp); 474 if_alloc_sadl(ifp);
475 if_register(ifp); 475 if_register(ifp);
476 476
477 return 0; 477 return 0;
478} 478}
479 479
480/* 480/*
481 * bridge_clone_destroy: 481 * bridge_clone_destroy:
482 * 482 *
483 * Destroy a bridge instance. 483 * Destroy a bridge instance.
484 */ 484 */
485static int 485static int
486bridge_clone_destroy(struct ifnet *ifp) 486bridge_clone_destroy(struct ifnet *ifp)
487{ 487{
488 struct bridge_softc *sc = ifp->if_softc; 488 struct bridge_softc *sc = ifp->if_softc;
489 struct bridge_iflist *bif; 489 struct bridge_iflist *bif;
490 490
491 if ((ifp->if_flags & IFF_RUNNING) != 0) 491 if ((ifp->if_flags & IFF_RUNNING) != 0)
492 bridge_stop(ifp, 1); 492 bridge_stop(ifp, 1);
493 493
494 BRIDGE_LOCK(sc); 494 BRIDGE_LOCK(sc);
495 for (;;) { 495 for (;;) {
496 bif = PSLIST_WRITER_FIRST(&sc->sc_iflist_psref.bip_iflist, struct bridge_iflist, 496 bif = PSLIST_WRITER_FIRST(&sc->sc_iflist_psref.bip_iflist, struct bridge_iflist,
497 bif_next); 497 bif_next);
498 if (bif == NULL) 498 if (bif == NULL)
499 break; 499 break;
500 bridge_delete_member(sc, bif); 500 bridge_delete_member(sc, bif);
501 } 501 }
502 PSLIST_DESTROY(&sc->sc_iflist_psref.bip_iflist); 502 PSLIST_DESTROY(&sc->sc_iflist_psref.bip_iflist);
503 BRIDGE_UNLOCK(sc); 503 BRIDGE_UNLOCK(sc);
504 504
505 if_detach(ifp); 505 if_detach(ifp);
506 506
507 /* Tear down the routing table. */ 507 /* Tear down the routing table. */
508 bridge_rtable_fini(sc); 508 bridge_rtable_fini(sc);
509 509
510 pserialize_destroy(sc->sc_iflist_psref.bip_psz); 510 pserialize_destroy(sc->sc_iflist_psref.bip_psz);
511 mutex_destroy(&sc->sc_iflist_psref.bip_lock); 511 mutex_destroy(&sc->sc_iflist_psref.bip_lock);
512 callout_destroy(&sc->sc_brcallout); 512 callout_destroy(&sc->sc_brcallout);
513 callout_destroy(&sc->sc_bstpcallout); 513 callout_destroy(&sc->sc_bstpcallout);
514 workqueue_destroy(sc->sc_rtage_wq); 514 workqueue_destroy(sc->sc_rtage_wq);
515 kmem_free(sc, sizeof(*sc)); 515 kmem_free(sc, sizeof(*sc));
516 516
517 return 0; 517 return 0;
518} 518}
519 519
520/* 520/*
521 * bridge_ioctl: 521 * bridge_ioctl:
522 * 522 *
523 * Handle a control request from the operator. 523 * Handle a control request from the operator.
524 */ 524 */
525static int 525static int
526bridge_ioctl(struct ifnet *ifp, u_long cmd, void *data) 526bridge_ioctl(struct ifnet *ifp, u_long cmd, void *data)
527{ 527{
528 struct bridge_softc *sc = ifp->if_softc; 528 struct bridge_softc *sc = ifp->if_softc;
529 struct lwp *l = curlwp; /* XXX */ 529 struct lwp *l = curlwp; /* XXX */
530 union { 530 union {
531 struct ifbreq ifbreq; 531 struct ifbreq ifbreq;
532 struct ifbifconf ifbifconf; 532 struct ifbifconf ifbifconf;
533 struct ifbareq ifbareq; 533 struct ifbareq ifbareq;
534 struct ifbaconf ifbaconf; 534 struct ifbaconf ifbaconf;
535 struct ifbrparam ifbrparam; 535 struct ifbrparam ifbrparam;
536 } args; 536 } args;
537 struct ifdrv *ifd = (struct ifdrv *) data; 537 struct ifdrv *ifd = (struct ifdrv *) data;
538 const struct bridge_control *bc = NULL; /* XXXGCC */ 538 const struct bridge_control *bc = NULL; /* XXXGCC */
539 int s, error = 0; 539 int s, error = 0;
540 540
541 /* Authorize command before calling splsoftnet(). */ 541 /* Authorize command before calling splsoftnet(). */
542 switch (cmd) { 542 switch (cmd) {
543 case SIOCGDRVSPEC: 543 case SIOCGDRVSPEC:
544 case SIOCSDRVSPEC: 544 case SIOCSDRVSPEC:
545 if (ifd->ifd_cmd >= bridge_control_table_size 545 if (ifd->ifd_cmd >= bridge_control_table_size
546 || (bc = &bridge_control_table[ifd->ifd_cmd]) == NULL) { 546 || (bc = &bridge_control_table[ifd->ifd_cmd]) == NULL) {
547 error = EINVAL; 547 error = EINVAL;
548 return error; 548 return error;
549 } 549 }
550 550
551 /* We only care about BC_F_SUSER at this point. */ 551 /* We only care about BC_F_SUSER at this point. */
552 if ((bc->bc_flags & BC_F_SUSER) == 0) 552 if ((bc->bc_flags & BC_F_SUSER) == 0)
553 break; 553 break;
554 554
555 error = kauth_authorize_network(l->l_cred, 555 error = kauth_authorize_network(l->l_cred,
556 KAUTH_NETWORK_INTERFACE_BRIDGE, 556 KAUTH_NETWORK_INTERFACE_BRIDGE,
557 cmd == SIOCGDRVSPEC ? 557 cmd == SIOCGDRVSPEC ?
558 KAUTH_REQ_NETWORK_INTERFACE_BRIDGE_GETPRIV : 558 KAUTH_REQ_NETWORK_INTERFACE_BRIDGE_GETPRIV :
559 KAUTH_REQ_NETWORK_INTERFACE_BRIDGE_SETPRIV, 559 KAUTH_REQ_NETWORK_INTERFACE_BRIDGE_SETPRIV,
560 ifd, NULL, NULL); 560 ifd, NULL, NULL);
561 if (error) 561 if (error)
562 return error; 562 return error;
563 563
564 break; 564 break;
565 } 565 }
566 566
567 s = splsoftnet(); 567 s = splsoftnet();
568 568
569 switch (cmd) { 569 switch (cmd) {
570 case SIOCGDRVSPEC: 570 case SIOCGDRVSPEC:
571 case SIOCSDRVSPEC: 571 case SIOCSDRVSPEC:
572 KASSERT(bc != NULL); 572 KASSERT(bc != NULL);
573 if (cmd == SIOCGDRVSPEC && 573 if (cmd == SIOCGDRVSPEC &&
574 (bc->bc_flags & (BC_F_COPYOUT|BC_F_XLATEOUT)) == 0) { 574 (bc->bc_flags & (BC_F_COPYOUT|BC_F_XLATEOUT)) == 0) {
575 error = EINVAL; 575 error = EINVAL;
576 break; 576 break;
577 } 577 }
578 else if (cmd == SIOCSDRVSPEC && 578 else if (cmd == SIOCSDRVSPEC &&
579 (bc->bc_flags & (BC_F_COPYOUT|BC_F_XLATEOUT)) != 0) { 579 (bc->bc_flags & (BC_F_COPYOUT|BC_F_XLATEOUT)) != 0) {
580 error = EINVAL; 580 error = EINVAL;
581 break; 581 break;
582 } 582 }
583 583
584 /* BC_F_SUSER is checked above, before splsoftnet(). */ 584 /* BC_F_SUSER is checked above, before splsoftnet(). */
585 585
586 if ((bc->bc_flags & (BC_F_XLATEIN|BC_F_XLATEOUT)) == 0 586 if ((bc->bc_flags & (BC_F_XLATEIN|BC_F_XLATEOUT)) == 0
587 && (ifd->ifd_len != bc->bc_argsize 587 && (ifd->ifd_len != bc->bc_argsize
588 || ifd->ifd_len > sizeof(args))) { 588 || ifd->ifd_len > sizeof(args))) {
589 error = EINVAL; 589 error = EINVAL;
590 break; 590 break;
591 } 591 }
592 592
593 memset(&args, 0, sizeof(args)); 593 memset(&args, 0, sizeof(args));
594 if (bc->bc_flags & BC_F_COPYIN) { 594 if (bc->bc_flags & BC_F_COPYIN) {
595 error = copyin(ifd->ifd_data, &args, ifd->ifd_len); 595 error = copyin(ifd->ifd_data, &args, ifd->ifd_len);
596 if (error) 596 if (error)
597 break; 597 break;
598 } else if (bc->bc_flags & BC_F_XLATEIN) { 598 } else if (bc->bc_flags & BC_F_XLATEIN) {
599 args.ifbifconf.ifbic_len = ifd->ifd_len; 599 args.ifbifconf.ifbic_len = ifd->ifd_len;
600 args.ifbifconf.ifbic_buf = ifd->ifd_data; 600 args.ifbifconf.ifbic_buf = ifd->ifd_data;
601 } 601 }
602 602
603 error = (*bc->bc_func)(sc, &args); 603 error = (*bc->bc_func)(sc, &args);
604 if (error) 604 if (error)
605 break; 605 break;
606 606
607 if (bc->bc_flags & BC_F_COPYOUT) { 607 if (bc->bc_flags & BC_F_COPYOUT) {
608 error = copyout(&args, ifd->ifd_data, ifd->ifd_len); 608 error = copyout(&args, ifd->ifd_data, ifd->ifd_len);
609 } else if (bc->bc_flags & BC_F_XLATEOUT) { 609 } else if (bc->bc_flags & BC_F_XLATEOUT) {
610 ifd->ifd_len = args.ifbifconf.ifbic_len; 610 ifd->ifd_len = args.ifbifconf.ifbic_len;
611 ifd->ifd_data = args.ifbifconf.ifbic_buf; 611 ifd->ifd_data = args.ifbifconf.ifbic_buf;
612 } 612 }
613 break; 613 break;
614 614
615 case SIOCSIFFLAGS: 615 case SIOCSIFFLAGS:
616 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 616 if ((error = ifioctl_common(ifp, cmd, data)) != 0)
617 break; 617 break;
618 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 618 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
619 case IFF_RUNNING: 619 case IFF_RUNNING:
620 /* 620 /*
621 * If interface is marked down and it is running, 621 * If interface is marked down and it is running,
622 * then stop and disable it. 622 * then stop and disable it.
623 */ 623 */
624 (*ifp->if_stop)(ifp, 1); 624 (*ifp->if_stop)(ifp, 1);
625 break; 625 break;
626 case IFF_UP: 626 case IFF_UP:
627 /* 627 /*
628 * If interface is marked up and it is stopped, then 628 * If interface is marked up and it is stopped, then
629 * start it. 629 * start it.
630 */ 630 */
631 error = (*ifp->if_init)(ifp); 631 error = (*ifp->if_init)(ifp);
632 break; 632 break;
633 default: 633 default:
634 break; 634 break;
635 } 635 }
636 break; 636 break;
637 637
638 case SIOCSIFMTU: 638 case SIOCSIFMTU:
639 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 639 if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET)
640 error = 0; 640 error = 0;
641 break; 641 break;
642 642
643 default: 643 default:
644 error = ifioctl_common(ifp, cmd, data); 644 error = ifioctl_common(ifp, cmd, data);
645 break; 645 break;
646 } 646 }
647 647
648 splx(s); 648 splx(s);
649 649
650 return error; 650 return error;
651} 651}
652 652
653/* 653/*
654 * bridge_lookup_member: 654 * bridge_lookup_member:
655 * 655 *
656 * Lookup a bridge member interface. 656 * Lookup a bridge member interface.
657 */ 657 */
658static struct bridge_iflist * 658static struct bridge_iflist *
659bridge_lookup_member(struct bridge_softc *sc, const char *name, struct psref *psref) 659bridge_lookup_member(struct bridge_softc *sc, const char *name, struct psref *psref)
660{ 660{
661 struct bridge_iflist *bif; 661 struct bridge_iflist *bif;
662 struct ifnet *ifp; 662 struct ifnet *ifp;
663 int s; 663 int s;
664 664
665 BRIDGE_PSZ_RENTER(s); 665 BRIDGE_PSZ_RENTER(s);
666 666
667 BRIDGE_IFLIST_READER_FOREACH(bif, sc) { 667 BRIDGE_IFLIST_READER_FOREACH(bif, sc) {
668 ifp = bif->bif_ifp; 668 ifp = bif->bif_ifp;
669 if (strcmp(ifp->if_xname, name) == 0) 669 if (strcmp(ifp->if_xname, name) == 0)
670 break; 670 break;
671 } 671 }
672 if (bif != NULL) 672 if (bif != NULL)
673 bridge_acquire_member(sc, bif, psref); 673 bridge_acquire_member(sc, bif, psref);
674 674
675 BRIDGE_PSZ_REXIT(s); 675 BRIDGE_PSZ_REXIT(s);
676 676
677 return bif; 677 return bif;
678} 678}
679 679
680/* 680/*
681 * bridge_lookup_member_if: 681 * bridge_lookup_member_if:
682 * 682 *
683 * Lookup a bridge member interface by ifnet*. 683 * Lookup a bridge member interface by ifnet*.
684 */ 684 */
685static struct bridge_iflist * 685static struct bridge_iflist *
686bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp, 686bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp,
687 struct psref *psref) 687 struct psref *psref)
688{ 688{
689 struct bridge_iflist *bif; 689 struct bridge_iflist *bif;
690 int s; 690 int s;
691 691
692 BRIDGE_PSZ_RENTER(s); 692 BRIDGE_PSZ_RENTER(s);
693 693
694 bif = member_ifp->if_bridgeif; 694 bif = member_ifp->if_bridgeif;
695 if (bif != NULL) { 695 if (bif != NULL) {
696 psref_acquire(psref, &bif->bif_psref, 696 psref_acquire(psref, &bif->bif_psref,
697 bridge_psref_class); 697 bridge_psref_class);
698 } 698 }
699 699
700 BRIDGE_PSZ_REXIT(s); 700 BRIDGE_PSZ_REXIT(s);
701 701
702 return bif; 702 return bif;
703} 703}
704 704
705static void 705static void
706bridge_acquire_member(struct bridge_softc *sc, struct bridge_iflist *bif, 706bridge_acquire_member(struct bridge_softc *sc, struct bridge_iflist *bif,
707 struct psref *psref) 707 struct psref *psref)
708{ 708{
709 709
710 psref_acquire(psref, &bif->bif_psref, bridge_psref_class); 710 psref_acquire(psref, &bif->bif_psref, bridge_psref_class);
711} 711}
712 712
713/* 713/*
714 * bridge_release_member: 714 * bridge_release_member:
715 * 715 *
716 * Release the specified member interface. 716 * Release the specified member interface.
717 */ 717 */
718static void 718static void
719bridge_release_member(struct bridge_softc *sc, struct bridge_iflist *bif, 719bridge_release_member(struct bridge_softc *sc, struct bridge_iflist *bif,
720 struct psref *psref) 720 struct psref *psref)
721{ 721{
722 722
723 psref_release(psref, &bif->bif_psref, bridge_psref_class); 723 psref_release(psref, &bif->bif_psref, bridge_psref_class);
724} 724}
725 725
726/* 726/*
727 * bridge_delete_member: 727 * bridge_delete_member:
728 * 728 *
729 * Delete the specified member interface. 729 * Delete the specified member interface.
730 */ 730 */
731static void 731static void
732bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif) 732bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif)
733{ 733{
734 struct ifnet *ifs = bif->bif_ifp; 734 struct ifnet *ifs = bif->bif_ifp;
735 735
736 KASSERT(BRIDGE_LOCKED(sc)); 736 KASSERT(BRIDGE_LOCKED(sc));
737 737
738 ifs->_if_input = ether_input; 738 ifs->_if_input = ether_input;
739 ifs->if_bridge = NULL; 739 ifs->if_bridge = NULL;
740 ifs->if_bridgeif = NULL; 740 ifs->if_bridgeif = NULL;
741 741
742 PSLIST_WRITER_REMOVE(bif, bif_next); 742 PSLIST_WRITER_REMOVE(bif, bif_next);
743 BRIDGE_PSZ_PERFORM(sc); 743 BRIDGE_PSZ_PERFORM(sc);
744 BRIDGE_UNLOCK(sc); 744 BRIDGE_UNLOCK(sc);
745 745
 746 switch (ifs->if_type) {
 747 case IFT_ETHER:
 748 case IFT_L2TP:
 749 /*
 750 * Take the interface out of promiscuous mode.
 751 * Don't call it with holding a spin lock.
 752 */
 753 (void) ifpromisc(ifs, 0);
 754 IFNET_LOCK(ifs);
 755 (void) ether_disable_vlan_mtu(ifs);
 756 IFNET_UNLOCK(ifs);
 757 break;
 758 default:
 759#ifdef DIAGNOSTIC
 760 panic("%s: impossible", __func__);
 761#endif
 762 break;
 763 }
 764
746 psref_target_destroy(&bif->bif_psref, bridge_psref_class); 765 psref_target_destroy(&bif->bif_psref, bridge_psref_class);
747 766
748 PSLIST_ENTRY_DESTROY(bif, bif_next); 767 PSLIST_ENTRY_DESTROY(bif, bif_next);
749 kmem_free(bif, sizeof(*bif)); 768 kmem_free(bif, sizeof(*bif));
750 769
751 BRIDGE_LOCK(sc); 770 BRIDGE_LOCK(sc);
752} 771}
753 772
754/* 773/*
755 * bridge_calc_csum_flags: 774 * bridge_calc_csum_flags:
756 * 775 *
757 * Calculate logical and b/w csum flags each member interface supports. 776 * Calculate logical and b/w csum flags each member interface supports.
758 */ 777 */
759void 778void
760bridge_calc_csum_flags(struct bridge_softc *sc) 779bridge_calc_csum_flags(struct bridge_softc *sc)
761{ 780{
762 struct bridge_iflist *bif; 781 struct bridge_iflist *bif;
763 struct ifnet *ifs; 782 struct ifnet *ifs;
764 int flags = ~0; 783 int flags = ~0;
765 784
766 BRIDGE_LOCK(sc); 785 BRIDGE_LOCK(sc);
767 BRIDGE_IFLIST_READER_FOREACH(bif, sc) { 786 BRIDGE_IFLIST_READER_FOREACH(bif, sc) {
768 ifs = bif->bif_ifp; 787 ifs = bif->bif_ifp;
769 flags &= ifs->if_csum_flags_tx; 788 flags &= ifs->if_csum_flags_tx;
770 } 789 }
771 sc->sc_csum_flags_tx = flags; 790 sc->sc_csum_flags_tx = flags;
772 BRIDGE_UNLOCK(sc); 791 BRIDGE_UNLOCK(sc);
773#ifdef DEBUG 792#ifdef DEBUG
774 printf("%s: 0x%x\n", __func__, flags); 793 printf("%s: 0x%x\n", __func__, flags);
775#endif 794#endif
776} 795}
777 796
778static int 797static int
779bridge_ioctl_add(struct bridge_softc *sc, void *arg) 798bridge_ioctl_add(struct bridge_softc *sc, void *arg)
780{ 799{
781 struct ifbreq *req = arg; 800 struct ifbreq *req = arg;
782 struct bridge_iflist *bif = NULL; 801 struct bridge_iflist *bif = NULL;
783 struct ifnet *ifs; 802 struct ifnet *ifs;
784 int error = 0; 803 int error = 0;
785 struct psref psref; 804 struct psref psref;
786 805
787 ifs = if_get(req->ifbr_ifsname, &psref); 806 ifs = if_get(req->ifbr_ifsname, &psref);
788 if (ifs == NULL) 807 if (ifs == NULL)
789 return ENOENT; 808 return ENOENT;
790 809
791 if (ifs->if_bridge == sc) { 810 if (ifs->if_bridge == sc) {
792 error = EEXIST; 811 error = EEXIST;
793 goto out; 812 goto out;
794 } 813 }
795 814
796 if (ifs->if_bridge != NULL) { 815 if (ifs->if_bridge != NULL) {
797 error = EBUSY; 816 error = EBUSY;
798 goto out; 817 goto out;
799 } 818 }
800 819
801 if (ifs->_if_input != ether_input) { 820 if (ifs->_if_input != ether_input) {
802 error = EINVAL; 821 error = EINVAL;
803 goto out; 822 goto out;
804 } 823 }
805 824
806 /* FIXME: doesn't work with non-IFF_SIMPLEX interfaces */ 825 /* FIXME: doesn't work with non-IFF_SIMPLEX interfaces */
807 if ((ifs->if_flags & IFF_SIMPLEX) == 0) { 826 if ((ifs->if_flags & IFF_SIMPLEX) == 0) {
808 error = EINVAL; 827 error = EINVAL;
809 goto out; 828 goto out;
810 } 829 }
811 830
812 bif = kmem_alloc(sizeof(*bif), KM_SLEEP); 831 bif = kmem_alloc(sizeof(*bif), KM_SLEEP);
813 832
814 switch (ifs->if_type) { 833 switch (ifs->if_type) {
815 case IFT_ETHER: 834 case IFT_ETHER:
816 if (sc->sc_if.if_mtu != ifs->if_mtu) { 835 if (sc->sc_if.if_mtu != ifs->if_mtu) {
817 error = EINVAL; 836 error = EINVAL;
818 goto out; 837 goto out;
819 } 838 }
820 /* FALLTHROUGH */ 839 /* FALLTHROUGH */
821 case IFT_L2TP: 840 case IFT_L2TP:
822 IFNET_LOCK(ifs); 841 IFNET_LOCK(ifs);
823 error = ether_enable_vlan_mtu(ifs); 842 error = ether_enable_vlan_mtu(ifs);
824 IFNET_UNLOCK(ifs); 843 IFNET_UNLOCK(ifs);
825 if (error > 0) 844 if (error > 0)
826 goto out; 845 goto out;
827 /* 846 /*
828 * Place the interface into promiscuous mode. 847 * Place the interface into promiscuous mode.
829 */ 848 */
830 error = ifpromisc(ifs, 1); 849 error = ifpromisc(ifs, 1);
831 if (error) 850 if (error)
832 goto out; 851 goto out;
833 break; 852 break;
834 default: 853 default:
835 error = EINVAL; 854 error = EINVAL;
836 goto out; 855 goto out;
837 } 856 }
838 857
839 bif->bif_ifp = ifs; 858 bif->bif_ifp = ifs;
840 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; 859 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
841 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; 860 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
842 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST; 861 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST;
843 PSLIST_ENTRY_INIT(bif, bif_next); 862 PSLIST_ENTRY_INIT(bif, bif_next);
844 psref_target_init(&bif->bif_psref, bridge_psref_class); 863 psref_target_init(&bif->bif_psref, bridge_psref_class);
845 864
846 BRIDGE_LOCK(sc); 865 BRIDGE_LOCK(sc);
847 866
848 ifs->if_bridge = sc; 867 ifs->if_bridge = sc;
849 ifs->if_bridgeif = bif; 868 ifs->if_bridgeif = bif;
850 PSLIST_WRITER_INSERT_HEAD(&sc->sc_iflist_psref.bip_iflist, bif, bif_next); 869 PSLIST_WRITER_INSERT_HEAD(&sc->sc_iflist_psref.bip_iflist, bif, bif_next);
851 ifs->_if_input = bridge_input; 870 ifs->_if_input = bridge_input;
852 871
853 BRIDGE_UNLOCK(sc); 872 BRIDGE_UNLOCK(sc);
854 873
855 bridge_calc_csum_flags(sc); 874 bridge_calc_csum_flags(sc);
856 875
857 if (sc->sc_if.if_flags & IFF_RUNNING) 876 if (sc->sc_if.if_flags & IFF_RUNNING)
858 bstp_initialization(sc); 877 bstp_initialization(sc);
859 else 878 else
860 bstp_stop(sc); 879 bstp_stop(sc);
861 880
862out: 881out:
863 if_put(ifs, &psref); 882 if_put(ifs, &psref);
864 if (error) { 883 if (error) {
865 if (bif != NULL) 884 if (bif != NULL)
866 kmem_free(bif, sizeof(*bif)); 885 kmem_free(bif, sizeof(*bif));
867 } 886 }
868 return error; 887 return error;
869} 888}
870 889
871static int 890static int
872bridge_ioctl_del(struct bridge_softc *sc, void *arg) 891bridge_ioctl_del(struct bridge_softc *sc, void *arg)
873{ 892{
874 struct ifbreq *req = arg; 893 struct ifbreq *req = arg;
875 const char *name = req->ifbr_ifsname; 894 const char *name = req->ifbr_ifsname;
876 struct bridge_iflist *bif; 895 struct bridge_iflist *bif;
877 struct ifnet *ifs; 896 struct ifnet *ifs;
878 897
879 BRIDGE_LOCK(sc); 898 BRIDGE_LOCK(sc);
880 899
881 /* 900 /*
882 * Don't use bridge_lookup_member. We want to get a member 901 * Don't use bridge_lookup_member. We want to get a member
883 * with bif_refs == 0. 902 * with bif_refs == 0.
884 */ 903 */
885 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) { 904 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) {
886 ifs = bif->bif_ifp; 905 ifs = bif->bif_ifp;
887 if (strcmp(ifs->if_xname, name) == 0) 906 if (strcmp(ifs->if_xname, name) == 0)
888 break; 907 break;
889 } 908 }
890 909
891 if (bif == NULL) { 910 if (bif == NULL) {
892 BRIDGE_UNLOCK(sc); 911 BRIDGE_UNLOCK(sc);
893 return ENOENT; 912 return ENOENT;
894 } 913 }
895 914
896 bridge_delete_member(sc, bif); 915 bridge_delete_member(sc, bif);
897 916
898 BRIDGE_UNLOCK(sc); 917 BRIDGE_UNLOCK(sc);
899 918
900 switch (ifs->if_type) { 
901 case IFT_ETHER: 
902 case IFT_L2TP: 
903 /* 
904 * Take the interface out of promiscuous mode. 
905 * Don't call it with holding a spin lock. 
906 */ 
907 (void) ifpromisc(ifs, 0); 
908 IFNET_LOCK(ifs); 
909 (void) ether_disable_vlan_mtu(ifs); 
910 IFNET_UNLOCK(ifs); 
911 break; 
912 default: 
913#ifdef DIAGNOSTIC 
914 panic("bridge_delete_member: impossible"); 
915#endif 
916 break; 
917 } 
918 
919 bridge_rtdelete(sc, ifs); 919 bridge_rtdelete(sc, ifs);
920 bridge_calc_csum_flags(sc); 920 bridge_calc_csum_flags(sc);
921 921
922 if (sc->sc_if.if_flags & IFF_RUNNING) 922 if (sc->sc_if.if_flags & IFF_RUNNING)
923 bstp_initialization(sc); 923 bstp_initialization(sc);
924 924
925 return 0; 925 return 0;
926} 926}
927 927
928static int 928static int
929bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg) 929bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg)
930{ 930{
931 struct ifbreq *req = arg; 931 struct ifbreq *req = arg;
932 struct bridge_iflist *bif; 932 struct bridge_iflist *bif;
933 struct psref psref; 933 struct psref psref;
934 934
935 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref); 935 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref);
936 if (bif == NULL) 936 if (bif == NULL)
937 return ENOENT; 937 return ENOENT;
938 938
939 req->ifbr_ifsflags = bif->bif_flags; 939 req->ifbr_ifsflags = bif->bif_flags;
940 req->ifbr_state = bif->bif_state; 940 req->ifbr_state = bif->bif_state;
941 req->ifbr_priority = bif->bif_priority; 941 req->ifbr_priority = bif->bif_priority;
942 req->ifbr_path_cost = bif->bif_path_cost; 942 req->ifbr_path_cost = bif->bif_path_cost;
943 req->ifbr_portno = bif->bif_ifp->if_index & 0xff; 943 req->ifbr_portno = bif->bif_ifp->if_index & 0xff;
944 944
945 bridge_release_member(sc, bif, &psref); 945 bridge_release_member(sc, bif, &psref);
946 946
947 return 0; 947 return 0;
948} 948}
949 949
950static int 950static int
951bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg) 951bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg)
952{ 952{
953 struct ifbreq *req = arg; 953 struct ifbreq *req = arg;
954 struct bridge_iflist *bif; 954 struct bridge_iflist *bif;
955 struct psref psref; 955 struct psref psref;
956 956
957 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref); 957 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref);
958 if (bif == NULL) 958 if (bif == NULL)
959 return ENOENT; 959 return ENOENT;
960 960
961 if (req->ifbr_ifsflags & IFBIF_STP) { 961 if (req->ifbr_ifsflags & IFBIF_STP) {
962 switch (bif->bif_ifp->if_type) { 962 switch (bif->bif_ifp->if_type) {
963 case IFT_ETHER: 963 case IFT_ETHER:
964 case IFT_L2TP: 964 case IFT_L2TP:
965 /* These can do spanning tree. */ 965 /* These can do spanning tree. */
966 break; 966 break;
967 967
968 default: 968 default:
969 /* Nothing else can. */ 969 /* Nothing else can. */
970 bridge_release_member(sc, bif, &psref); 970 bridge_release_member(sc, bif, &psref);
971 return EINVAL; 971 return EINVAL;
972 } 972 }
973 } 973 }
974 974
975 bif->bif_flags = req->ifbr_ifsflags; 975 bif->bif_flags = req->ifbr_ifsflags;
976 976
977 bridge_release_member(sc, bif, &psref); 977 bridge_release_member(sc, bif, &psref);
978 978
979 if (sc->sc_if.if_flags & IFF_RUNNING) 979 if (sc->sc_if.if_flags & IFF_RUNNING)
980 bstp_initialization(sc); 980 bstp_initialization(sc);
981 981
982 return 0; 982 return 0;
983} 983}
984 984
985static int 985static int
986bridge_ioctl_scache(struct bridge_softc *sc, void *arg) 986bridge_ioctl_scache(struct bridge_softc *sc, void *arg)
987{ 987{
988 struct ifbrparam *param = arg; 988 struct ifbrparam *param = arg;
989 989
990 sc->sc_brtmax = param->ifbrp_csize; 990 sc->sc_brtmax = param->ifbrp_csize;
991 bridge_rttrim(sc); 991 bridge_rttrim(sc);
992 992
993 return 0; 993 return 0;
994} 994}
995 995
996static int 996static int
997bridge_ioctl_gcache(struct bridge_softc *sc, void *arg) 997bridge_ioctl_gcache(struct bridge_softc *sc, void *arg)
998{ 998{
999 struct ifbrparam *param = arg; 999 struct ifbrparam *param = arg;
1000 1000
1001 param->ifbrp_csize = sc->sc_brtmax; 1001 param->ifbrp_csize = sc->sc_brtmax;
1002 1002
1003 return 0; 1003 return 0;
1004} 1004}
1005 1005
1006static int 1006static int
1007bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) 1007bridge_ioctl_gifs(struct bridge_softc *sc, void *arg)
1008{ 1008{
1009 struct ifbifconf *bifc = arg; 1009 struct ifbifconf *bifc = arg;
1010 struct bridge_iflist *bif; 1010 struct bridge_iflist *bif;
1011 struct ifbreq *breqs; 1011 struct ifbreq *breqs;
1012 int i, count, error = 0; 1012 int i, count, error = 0;
1013 1013
1014retry: 1014retry:
1015 BRIDGE_LOCK(sc); 1015 BRIDGE_LOCK(sc);
1016 count = 0; 1016 count = 0;
1017 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) 1017 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc)
1018 count++; 1018 count++;
1019 BRIDGE_UNLOCK(sc); 1019 BRIDGE_UNLOCK(sc);
1020 1020
1021 if (count == 0) { 1021 if (count == 0) {
1022 bifc->ifbic_len = 0; 1022 bifc->ifbic_len = 0;
1023 return 0; 1023 return 0;
1024 } 1024 }
1025 1025
1026 if (bifc->ifbic_len == 0 || bifc->ifbic_len < (sizeof(*breqs) * count)) { 1026 if (bifc->ifbic_len == 0 || bifc->ifbic_len < (sizeof(*breqs) * count)) {
1027 /* Tell that a larger buffer is needed */ 1027 /* Tell that a larger buffer is needed */
1028 bifc->ifbic_len = sizeof(*breqs) * count; 1028 bifc->ifbic_len = sizeof(*breqs) * count;
1029 return 0; 1029 return 0;
1030 } 1030 }
1031 1031
1032 breqs = kmem_alloc(sizeof(*breqs) * count, KM_SLEEP); 1032 breqs = kmem_alloc(sizeof(*breqs) * count, KM_SLEEP);
1033 1033
1034 BRIDGE_LOCK(sc); 1034 BRIDGE_LOCK(sc);
1035 1035
1036 i = 0; 1036 i = 0;
1037 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) 1037 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc)
1038 i++; 1038 i++;
1039 if (i > count) { 1039 if (i > count) {
1040 /* 1040 /*
1041 * The number of members has been increased. 1041 * The number of members has been increased.
1042 * We need more memory! 1042 * We need more memory!
1043 */ 1043 */
1044 BRIDGE_UNLOCK(sc); 1044 BRIDGE_UNLOCK(sc);
1045 kmem_free(breqs, sizeof(*breqs) * count); 1045 kmem_free(breqs, sizeof(*breqs) * count);
1046 goto retry; 1046 goto retry;
1047 } 1047 }
1048 1048
1049 i = 0; 1049 i = 0;
1050 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) { 1050 BRIDGE_IFLIST_WRITER_FOREACH(bif, sc) {
1051 struct ifbreq *breq = &breqs[i++]; 1051 struct ifbreq *breq = &breqs[i++];
1052 memset(breq, 0, sizeof(*breq)); 1052 memset(breq, 0, sizeof(*breq));
1053 1053
1054 strlcpy(breq->ifbr_ifsname, bif->bif_ifp->if_xname, 1054 strlcpy(breq->ifbr_ifsname, bif->bif_ifp->if_xname,
1055 sizeof(breq->ifbr_ifsname)); 1055 sizeof(breq->ifbr_ifsname));
1056 breq->ifbr_ifsflags = bif->bif_flags; 1056 breq->ifbr_ifsflags = bif->bif_flags;
1057 breq->ifbr_state = bif->bif_state; 1057 breq->ifbr_state = bif->bif_state;
1058 breq->ifbr_priority = bif->bif_priority; 1058 breq->ifbr_priority = bif->bif_priority;
1059 breq->ifbr_path_cost = bif->bif_path_cost; 1059 breq->ifbr_path_cost = bif->bif_path_cost;
1060 breq->ifbr_portno = bif->bif_ifp->if_index & 0xff; 1060 breq->ifbr_portno = bif->bif_ifp->if_index & 0xff;
1061 } 1061 }
1062 1062
1063 /* Don't call copyout with holding the mutex */ 1063 /* Don't call copyout with holding the mutex */
1064 BRIDGE_UNLOCK(sc); 1064 BRIDGE_UNLOCK(sc);
1065 1065
1066 for (i = 0; i < count; i++) { 1066 for (i = 0; i < count; i++) {
1067 error = copyout(&breqs[i], bifc->ifbic_req + i, sizeof(*breqs)); 1067 error = copyout(&breqs[i], bifc->ifbic_req + i, sizeof(*breqs));
1068 if (error) 1068 if (error)
1069 break; 1069 break;
1070 } 1070 }
1071 bifc->ifbic_len = sizeof(*breqs) * i; 1071 bifc->ifbic_len = sizeof(*breqs) * i;
1072 1072
1073 kmem_free(breqs, sizeof(*breqs) * count); 1073 kmem_free(breqs, sizeof(*breqs) * count);
1074 1074
1075 return error; 1075 return error;
1076} 1076}
1077 1077
1078static int 1078static int
1079bridge_ioctl_rts(struct bridge_softc *sc, void *arg) 1079bridge_ioctl_rts(struct bridge_softc *sc, void *arg)
1080{ 1080{
1081 struct ifbaconf *bac = arg; 1081 struct ifbaconf *bac = arg;
1082 struct bridge_rtnode *brt; 1082 struct bridge_rtnode *brt;
1083 struct ifbareq bareq; 1083 struct ifbareq bareq;
1084 int count = 0, error = 0, len; 1084 int count = 0, error = 0, len;
1085 1085
1086 if (bac->ifbac_len == 0) 1086 if (bac->ifbac_len == 0)
1087 return 0; 1087 return 0;
1088 1088
1089 BRIDGE_RT_LOCK(sc); 1089 BRIDGE_RT_LOCK(sc);
1090 1090
1091 /* The passed buffer is not enough, tell a required size. */ 1091 /* The passed buffer is not enough, tell a required size. */
1092 if (bac->ifbac_len < (sizeof(bareq) * sc->sc_brtcnt)) { 1092 if (bac->ifbac_len < (sizeof(bareq) * sc->sc_brtcnt)) {
1093 count = sc->sc_brtcnt; 1093 count = sc->sc_brtcnt;
1094 goto out; 1094 goto out;
1095 } 1095 }
1096 1096
1097 len = bac->ifbac_len; 1097 len = bac->ifbac_len;
1098 BRIDGE_RTLIST_WRITER_FOREACH(brt, sc) { 1098 BRIDGE_RTLIST_WRITER_FOREACH(brt, sc) {
1099 if (len < sizeof(bareq)) 1099 if (len < sizeof(bareq))
1100 goto out; 1100 goto out;
1101 memset(&bareq, 0, sizeof(bareq)); 1101 memset(&bareq, 0, sizeof(bareq));
1102 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname, 1102 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname,
1103 sizeof(bareq.ifba_ifsname)); 1103 sizeof(bareq.ifba_ifsname));
1104 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr)); 1104 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr));
1105 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { 1105 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1106 bareq.ifba_expire = brt->brt_expire - time_uptime; 1106 bareq.ifba_expire = brt->brt_expire - time_uptime;
1107 } else 1107 } else
1108 bareq.ifba_expire = 0; 1108 bareq.ifba_expire = 0;
1109 bareq.ifba_flags = brt->brt_flags; 1109 bareq.ifba_flags = brt->brt_flags;
1110 1110
1111 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq)); 1111 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq));
1112 if (error) 1112 if (error)
1113 goto out; 1113 goto out;
1114 count++; 1114 count++;
1115 len -= sizeof(bareq); 1115 len -= sizeof(bareq);
1116 } 1116 }
1117out: 1117out:
1118 BRIDGE_RT_UNLOCK(sc); 1118 BRIDGE_RT_UNLOCK(sc);
1119 1119
1120 bac->ifbac_len = sizeof(bareq) * count; 1120 bac->ifbac_len = sizeof(bareq) * count;
1121 return error; 1121 return error;
1122} 1122}
1123 1123
1124static int 1124static int
1125bridge_ioctl_saddr(struct bridge_softc *sc, void *arg) 1125bridge_ioctl_saddr(struct bridge_softc *sc, void *arg)
1126{ 1126{
1127 struct ifbareq *req = arg; 1127 struct ifbareq *req = arg;
1128 struct bridge_iflist *bif; 1128 struct bridge_iflist *bif;
1129 int error; 1129 int error;
1130 struct psref psref; 1130 struct psref psref;
1131 1131
1132 bif = bridge_lookup_member(sc, req->ifba_ifsname, &psref); 1132 bif = bridge_lookup_member(sc, req->ifba_ifsname, &psref);
1133 if (bif == NULL) 1133 if (bif == NULL)
1134 return ENOENT; 1134 return ENOENT;
1135 1135
1136 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1, 1136 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1,
1137 req->ifba_flags); 1137 req->ifba_flags);
1138 1138
1139 bridge_release_member(sc, bif, &psref); 1139 bridge_release_member(sc, bif, &psref);
1140 1140
1141 return error; 1141 return error;
1142} 1142}
1143 1143
1144static int 1144static int
1145bridge_ioctl_sto(struct bridge_softc *sc, void *arg) 1145bridge_ioctl_sto(struct bridge_softc *sc, void *arg)
1146{ 1146{
1147 struct ifbrparam *param = arg; 1147 struct ifbrparam *param = arg;
1148 1148
1149 sc->sc_brttimeout = param->ifbrp_ctime; 1149 sc->sc_brttimeout = param->ifbrp_ctime;
1150 1150
1151 return 0; 1151 return 0;
1152} 1152}
1153 1153
1154static int 1154static int
1155bridge_ioctl_gto(struct bridge_softc *sc, void *arg) 1155bridge_ioctl_gto(struct bridge_softc *sc, void *arg)
1156{ 1156{
1157 struct ifbrparam *param = arg; 1157 struct ifbrparam *param = arg;
1158 1158
1159 param->ifbrp_ctime = sc->sc_brttimeout; 1159 param->ifbrp_ctime = sc->sc_brttimeout;
1160 1160
1161 return 0; 1161 return 0;
1162} 1162}
1163 1163
1164static int 1164static int
1165bridge_ioctl_daddr(struct bridge_softc *sc, void *arg) 1165bridge_ioctl_daddr(struct bridge_softc *sc, void *arg)
1166{ 1166{
1167 struct ifbareq *req = arg; 1167 struct ifbareq *req = arg;
1168 1168
1169 return (bridge_rtdaddr(sc, req->ifba_dst)); 1169 return (bridge_rtdaddr(sc, req->ifba_dst));
1170} 1170}
1171 1171
1172static int 1172static int
1173bridge_ioctl_flush(struct bridge_softc *sc, void *arg) 1173bridge_ioctl_flush(struct bridge_softc *sc, void *arg)
1174{ 1174{
1175 struct ifbreq *req = arg; 1175 struct ifbreq *req = arg;
1176 1176
1177 bridge_rtflush(sc, req->ifbr_ifsflags); 1177 bridge_rtflush(sc, req->ifbr_ifsflags);
1178 1178
1179 return 0; 1179 return 0;
1180} 1180}
1181 1181
1182static int 1182static int
1183bridge_ioctl_gpri(struct bridge_softc *sc, void *arg) 1183bridge_ioctl_gpri(struct bridge_softc *sc, void *arg)
1184{ 1184{
1185 struct ifbrparam *param = arg; 1185 struct ifbrparam *param = arg;
1186 1186
1187 param->ifbrp_prio = sc->sc_bridge_priority; 1187 param->ifbrp_prio = sc->sc_bridge_priority;
1188 1188
1189 return 0; 1189 return 0;
1190} 1190}
1191 1191
1192static int 1192static int
1193bridge_ioctl_spri(struct bridge_softc *sc, void *arg) 1193bridge_ioctl_spri(struct bridge_softc *sc, void *arg)
1194{ 1194{
1195 struct ifbrparam *param = arg; 1195 struct ifbrparam *param = arg;
1196 1196
1197 sc->sc_bridge_priority = param->ifbrp_prio; 1197 sc->sc_bridge_priority = param->ifbrp_prio;
1198 1198
1199 if (sc->sc_if.if_flags & IFF_RUNNING) 1199 if (sc->sc_if.if_flags & IFF_RUNNING)
1200 bstp_initialization(sc); 1200 bstp_initialization(sc);
1201 1201
1202 return 0; 1202 return 0;
1203} 1203}
1204 1204
1205static int 1205static int
1206bridge_ioctl_ght(struct bridge_softc *sc, void *arg) 1206bridge_ioctl_ght(struct bridge_softc *sc, void *arg)
1207{ 1207{
1208 struct ifbrparam *param = arg; 1208 struct ifbrparam *param = arg;
1209 1209
1210 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8; 1210 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8;
1211 1211
1212 return 0; 1212 return 0;
1213} 1213}
1214 1214
1215static int 1215static int
1216bridge_ioctl_sht(struct bridge_softc *sc, void *arg) 1216bridge_ioctl_sht(struct bridge_softc *sc, void *arg)
1217{ 1217{
1218 struct ifbrparam *param = arg; 1218 struct ifbrparam *param = arg;
1219 1219
1220 if (param->ifbrp_hellotime == 0) 1220 if (param->ifbrp_hellotime == 0)
1221 return EINVAL; 1221 return EINVAL;
1222 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8; 1222 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8;
1223 1223
1224 if (sc->sc_if.if_flags & IFF_RUNNING) 1224 if (sc->sc_if.if_flags & IFF_RUNNING)
1225 bstp_initialization(sc); 1225 bstp_initialization(sc);
1226 1226
1227 return 0; 1227 return 0;
1228} 1228}
1229 1229
1230static int 1230static int
1231bridge_ioctl_gfd(struct bridge_softc *sc, void *arg) 1231bridge_ioctl_gfd(struct bridge_softc *sc, void *arg)
1232{ 1232{
1233 struct ifbrparam *param = arg; 1233 struct ifbrparam *param = arg;
1234 1234
1235 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8; 1235 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8;
1236 1236
1237 return 0; 1237 return 0;
1238} 1238}
1239 1239
1240static int 1240static int
1241bridge_ioctl_sfd(struct bridge_softc *sc, void *arg) 1241bridge_ioctl_sfd(struct bridge_softc *sc, void *arg)
1242{ 1242{
1243 struct ifbrparam *param = arg; 1243 struct ifbrparam *param = arg;
1244 1244
1245 if (param->ifbrp_fwddelay == 0) 1245 if (param->ifbrp_fwddelay == 0)
1246 return EINVAL; 1246 return EINVAL;
1247 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8; 1247 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8;
1248 1248
1249 if (sc->sc_if.if_flags & IFF_RUNNING) 1249 if (sc->sc_if.if_flags & IFF_RUNNING)
1250 bstp_initialization(sc); 1250 bstp_initialization(sc);
1251 1251
1252 return 0; 1252 return 0;
1253} 1253}
1254 1254
1255static int 1255static int
1256bridge_ioctl_gma(struct bridge_softc *sc, void *arg) 1256bridge_ioctl_gma(struct bridge_softc *sc, void *arg)
1257{ 1257{
1258 struct ifbrparam *param = arg; 1258 struct ifbrparam *param = arg;
1259 1259
1260 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8; 1260 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8;
1261 1261
1262 return 0; 1262 return 0;
1263} 1263}
1264 1264
1265static int 1265static int
1266bridge_ioctl_sma(struct bridge_softc *sc, void *arg) 1266bridge_ioctl_sma(struct bridge_softc *sc, void *arg)
1267{ 1267{
1268 struct ifbrparam *param = arg; 1268 struct ifbrparam *param = arg;
1269 1269
1270 if (param->ifbrp_maxage == 0) 1270 if (param->ifbrp_maxage == 0)
1271 return EINVAL; 1271 return EINVAL;
1272 sc->sc_bridge_max_age = param->ifbrp_maxage << 8; 1272 sc->sc_bridge_max_age = param->ifbrp_maxage << 8;
1273 1273
1274 if (sc->sc_if.if_flags & IFF_RUNNING) 1274 if (sc->sc_if.if_flags & IFF_RUNNING)
1275 bstp_initialization(sc); 1275 bstp_initialization(sc);
1276 1276
1277 return 0; 1277 return 0;
1278} 1278}
1279 1279
1280static int 1280static int
1281bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg) 1281bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg)
1282{ 1282{
1283 struct ifbreq *req = arg; 1283 struct ifbreq *req = arg;
1284 struct bridge_iflist *bif; 1284 struct bridge_iflist *bif;
1285 struct psref psref; 1285 struct psref psref;
1286 1286
1287 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref); 1287 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref);
1288 if (bif == NULL) 1288 if (bif == NULL)
1289 return ENOENT; 1289 return ENOENT;
1290 1290
1291 bif->bif_priority = req->ifbr_priority; 1291 bif->bif_priority = req->ifbr_priority;
1292 1292
1293 if (sc->sc_if.if_flags & IFF_RUNNING) 1293 if (sc->sc_if.if_flags & IFF_RUNNING)
1294 bstp_initialization(sc); 1294 bstp_initialization(sc);
1295 1295
1296 bridge_release_member(sc, bif, &psref); 1296 bridge_release_member(sc, bif, &psref);
1297 1297
1298 return 0; 1298 return 0;
1299} 1299}
1300 1300
1301#if defined(BRIDGE_IPF) 1301#if defined(BRIDGE_IPF)
1302static int 1302static int
1303bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg) 1303bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg)
1304{ 1304{
1305 struct ifbrparam *param = arg; 1305 struct ifbrparam *param = arg;
1306 1306
1307 param->ifbrp_filter = sc->sc_filter_flags; 1307 param->ifbrp_filter = sc->sc_filter_flags;
1308 1308
1309 return 0; 1309 return 0;
1310} 1310}
1311 1311
1312static int 1312static int
1313bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg) 1313bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg)
1314{ 1314{
1315 struct ifbrparam *param = arg; 1315 struct ifbrparam *param = arg;
1316 uint32_t nflags, oflags; 1316 uint32_t nflags, oflags;
1317 1317
1318 if (param->ifbrp_filter & ~IFBF_FILT_MASK) 1318 if (param->ifbrp_filter & ~IFBF_FILT_MASK)
1319 return EINVAL; 1319 return EINVAL;
1320 1320
1321 nflags = param->ifbrp_filter; 1321 nflags = param->ifbrp_filter;
1322 oflags = sc->sc_filter_flags; 1322 oflags = sc->sc_filter_flags;
1323 1323
1324 if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) { 1324 if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) {
1325 pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT, 1325 pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1326 sc->sc_if.if_pfil); 1326 sc->sc_if.if_pfil);
1327 } 1327 }
1328 if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) { 1328 if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) {
1329 pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT, 1329 pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT,
1330 sc->sc_if.if_pfil); 1330 sc->sc_if.if_pfil);
1331 } 1331 }
1332 1332
1333 sc->sc_filter_flags = nflags; 1333 sc->sc_filter_flags = nflags;
1334 1334
1335 return 0; 1335 return 0;
1336} 1336}
1337#endif /* BRIDGE_IPF */ 1337#endif /* BRIDGE_IPF */
1338 1338
1339static int 1339static int
1340bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg) 1340bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg)
1341{ 1341{
1342 struct ifbreq *req = arg; 1342 struct ifbreq *req = arg;
1343 struct bridge_iflist *bif; 1343 struct bridge_iflist *bif;
1344 struct psref psref; 1344 struct psref psref;
1345 1345
1346 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref); 1346 bif = bridge_lookup_member(sc, req->ifbr_ifsname, &psref);
1347 if (bif == NULL) 1347 if (bif == NULL)
1348 return ENOENT; 1348 return ENOENT;
1349 1349
1350 bif->bif_path_cost = req->ifbr_path_cost; 1350 bif->bif_path_cost = req->ifbr_path_cost;
1351 1351
1352 if (sc->sc_if.if_flags & IFF_RUNNING) 1352 if (sc->sc_if.if_flags & IFF_RUNNING)
1353 bstp_initialization(sc); 1353 bstp_initialization(sc);
1354 1354
1355 bridge_release_member(sc, bif, &psref); 1355 bridge_release_member(sc, bif, &psref);
1356 1356
1357 return 0; 1357 return 0;
1358} 1358}
1359 1359
1360/* 1360/*
1361 * bridge_ifdetach: 1361 * bridge_ifdetach:
1362 * 1362 *
1363 * Detach an interface from a bridge. Called when a member 1363 * Detach an interface from a bridge. Called when a member
1364 * interface is detaching. 1364 * interface is detaching.
1365 */ 1365 */
1366void 1366void
1367bridge_ifdetach(struct ifnet *ifp) 1367bridge_ifdetach(struct ifnet *ifp)
1368{ 1368{
1369 struct bridge_softc *sc = ifp->if_bridge; 1369 struct bridge_softc *sc = ifp->if_bridge;
1370 struct ifbreq breq; 1370 struct ifbreq breq;
1371 1371
1372 /* ioctl_lock should prevent this from happening */ 1372 /* ioctl_lock should prevent this from happening */
1373 KASSERT(sc != NULL); 1373 KASSERT(sc != NULL);
1374 1374
1375 memset(&breq, 0, sizeof(breq)); 1375 memset(&breq, 0, sizeof(breq));
1376 strlcpy(breq.ifbr_ifsname, ifp->if_xname, sizeof(breq.ifbr_ifsname)); 1376 strlcpy(breq.ifbr_ifsname, ifp->if_xname, sizeof(breq.ifbr_ifsname));
1377 1377
1378 (void) bridge_ioctl_del(sc, &breq); 1378 (void) bridge_ioctl_del(sc, &breq);
1379} 1379}
1380 1380
1381/* 1381/*
1382 * bridge_init: 1382 * bridge_init:
1383 * 1383 *
1384 * Initialize a bridge interface. 1384 * Initialize a bridge interface.
1385 */ 1385 */
1386static int 1386static int
1387bridge_init(struct ifnet *ifp) 1387bridge_init(struct ifnet *ifp)
1388{ 1388{
1389 struct bridge_softc *sc = ifp->if_softc; 1389 struct bridge_softc *sc = ifp->if_softc;
1390 1390
1391 KASSERT((ifp->if_flags & IFF_RUNNING) == 0); 1391 KASSERT((ifp->if_flags & IFF_RUNNING) == 0);
1392 1392
1393 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz, 1393 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz,
1394 bridge_timer, sc); 1394 bridge_timer, sc);
1395 bstp_initialization(sc); 1395 bstp_initialization(sc);
1396 1396
1397 ifp->if_flags |= IFF_RUNNING; 1397 ifp->if_flags |= IFF_RUNNING;
1398 return 0; 1398 return 0;
1399} 1399}
1400 1400
1401/* 1401/*
1402 * bridge_stop: 1402 * bridge_stop:
1403 * 1403 *
1404 * Stop the bridge interface. 1404 * Stop the bridge interface.
1405 */ 1405 */
1406static void 1406static void
1407bridge_stop(struct ifnet *ifp, int disable) 1407bridge_stop(struct ifnet *ifp, int disable)
1408{ 1408{
1409 struct bridge_softc *sc = ifp->if_softc; 1409 struct bridge_softc *sc = ifp->if_softc;
1410 1410
1411 KASSERT((ifp->if_flags & IFF_RUNNING) != 0); 1411 KASSERT((ifp->if_flags & IFF_RUNNING) != 0);
1412 ifp->if_flags &= ~IFF_RUNNING; 1412 ifp->if_flags &= ~IFF_RUNNING;
1413 1413
1414 callout_halt(&sc->sc_brcallout, NULL); 1414 callout_halt(&sc->sc_brcallout, NULL);
1415 workqueue_wait(sc->sc_rtage_wq, &sc->sc_rtage_wk); 1415 workqueue_wait(sc->sc_rtage_wq, &sc->sc_rtage_wk);
1416 bstp_stop(sc); 1416 bstp_stop(sc);
1417 bridge_rtflush(sc, IFBF_FLUSHDYN); 1417 bridge_rtflush(sc, IFBF_FLUSHDYN);
1418} 1418}
1419 1419
1420/* 1420/*
1421 * bridge_enqueue: 1421 * bridge_enqueue:
1422 * 1422 *
1423 * Enqueue a packet on a bridge member interface. 1423 * Enqueue a packet on a bridge member interface.
1424 */ 1424 */
1425void 1425void
1426bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m, 1426bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m,
1427 int runfilt) 1427 int runfilt)
1428{ 1428{
1429 int len, error; 1429 int len, error;
1430 short mflags; 1430 short mflags;
1431 1431
1432 if (runfilt) { 1432 if (runfilt) {
1433 if (pfil_run_hooks(sc->sc_if.if_pfil, &m, 1433 if (pfil_run_hooks(sc->sc_if.if_pfil, &m,
1434 dst_ifp, PFIL_OUT) != 0) { 1434 dst_ifp, PFIL_OUT) != 0) {
1435 if (m != NULL) 1435 if (m != NULL)
1436 m_freem(m); 1436 m_freem(m);
1437 return; 1437 return;
1438 } 1438 }
1439 if (m == NULL) 1439 if (m == NULL)
1440 return; 1440 return;
1441 } 1441 }
1442 1442
1443#ifdef ALTQ 1443#ifdef ALTQ
1444 KERNEL_LOCK(1, NULL); 1444 KERNEL_LOCK(1, NULL);
1445 /* 1445 /*
1446 * If ALTQ is enabled on the member interface, do 1446 * If ALTQ is enabled on the member interface, do
1447 * classification; the queueing discipline might 1447 * classification; the queueing discipline might
1448 * not require classification, but might require 1448 * not require classification, but might require
1449 * the address family/header pointer in the pktattr. 1449 * the address family/header pointer in the pktattr.
1450 */ 1450 */
1451 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) { 1451 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) {
1452 /* XXX IFT_ETHER */ 1452 /* XXX IFT_ETHER */
1453 altq_etherclassify(&dst_ifp->if_snd, m); 1453 altq_etherclassify(&dst_ifp->if_snd, m);
1454 } 1454 }
1455 KERNEL_UNLOCK_ONE(NULL); 1455 KERNEL_UNLOCK_ONE(NULL);
1456#endif /* ALTQ */ 1456#endif /* ALTQ */
1457 1457
1458 len = m->m_pkthdr.len; 1458 len = m->m_pkthdr.len;
1459 mflags = m->m_flags; 1459 mflags = m->m_flags;
1460 1460
1461 error = if_transmit_lock(dst_ifp, m); 1461 error = if_transmit_lock(dst_ifp, m);
1462 if (error) { 1462 if (error) {
1463 /* mbuf is already freed */ 1463 /* mbuf is already freed */
1464 sc->sc_if.if_oerrors++; 1464 sc->sc_if.if_oerrors++;
1465 return; 1465 return;
1466 } 1466 }
1467 1467
1468 sc->sc_if.if_opackets++; 1468 sc->sc_if.if_opackets++;
1469 sc->sc_if.if_obytes += len; 1469 sc->sc_if.if_obytes += len;
1470 if (mflags & M_MCAST) 1470 if (mflags & M_MCAST)
1471 sc->sc_if.if_omcasts++; 1471 sc->sc_if.if_omcasts++;
1472} 1472}
1473 1473
1474/* 1474/*
1475 * bridge_output: 1475 * bridge_output:
1476 * 1476 *
1477 * Send output from a bridge member interface. This 1477 * Send output from a bridge member interface. This
1478 * performs the bridging function for locally originated 1478 * performs the bridging function for locally originated
1479 * packets. 1479 * packets.
1480 * 1480 *
1481 * The mbuf has the Ethernet header already attached. We must 1481 * The mbuf has the Ethernet header already attached. We must
1482 * enqueue or free the mbuf before returning. 1482 * enqueue or free the mbuf before returning.
1483 */ 1483 */
1484int 1484int
1485bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa, 1485bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa,
1486 const struct rtentry *rt) 1486 const struct rtentry *rt)
1487{ 1487{
1488 struct ether_header *eh; 1488 struct ether_header *eh;
1489 struct ifnet *dst_if; 1489 struct ifnet *dst_if;
1490 struct bridge_softc *sc; 1490 struct bridge_softc *sc;
1491 struct mbuf *n; 1491 struct mbuf *n;
1492 int s; 1492 int s;
1493 1493
1494 /* 1494 /*
1495 * bridge_output() is called from ether_output(), furthermore 1495 * bridge_output() is called from ether_output(), furthermore
1496 * ifp argument doesn't point to bridge(4). So, don't assert 1496 * ifp argument doesn't point to bridge(4). So, don't assert
1497 * IFEF_MPSAFE here. 1497 * IFEF_MPSAFE here.
1498 */ 1498 */
1499 1499
1500 if (m->m_len < ETHER_HDR_LEN) { 1500 if (m->m_len < ETHER_HDR_LEN) {
1501 m = m_pullup(m, ETHER_HDR_LEN); 1501 m = m_pullup(m, ETHER_HDR_LEN);
1502 if (m == NULL) 1502 if (m == NULL)
1503 return 0; 1503 return 0;
1504 } 1504 }
1505 1505
1506 eh = mtod(m, struct ether_header *); 1506 eh = mtod(m, struct ether_header *);
1507 sc = ifp->if_bridge; 1507 sc = ifp->if_bridge;
1508 1508
1509 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 1509 if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
1510 if (memcmp(etherbroadcastaddr, 1510 if (memcmp(etherbroadcastaddr,
1511 eh->ether_dhost, ETHER_ADDR_LEN) == 0) 1511 eh->ether_dhost, ETHER_ADDR_LEN) == 0)
1512 m->m_flags |= M_BCAST; 1512 m->m_flags |= M_BCAST;
1513 else 1513 else
1514 m->m_flags |= M_MCAST; 1514 m->m_flags |= M_MCAST;
1515 } 1515 }
1516 1516
1517 /* 1517 /*
1518 * If bridge is down, but the original output interface is up, 1518 * If bridge is down, but the original output interface is up,
1519 * go ahead and send out that interface. Otherwise, the packet 1519 * go ahead and send out that interface. Otherwise, the packet
1520 * is dropped below. 1520 * is dropped below.
1521 */ 1521 */
1522 if (__predict_false(sc == NULL) || 1522 if (__predict_false(sc == NULL) ||
1523 (sc->sc_if.if_flags & IFF_RUNNING) == 0) { 1523 (sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1524 dst_if = ifp; 1524 dst_if = ifp;
1525 goto unicast_asis; 1525 goto unicast_asis;
1526 } 1526 }
1527 1527
1528 /* 1528 /*
1529 * If the packet is a multicast, or we don't know a better way to 1529 * If the packet is a multicast, or we don't know a better way to
1530 * get there, send to all interfaces. 1530 * get there, send to all interfaces.
1531 */ 1531 */
1532 if ((m->m_flags & (M_MCAST | M_BCAST)) != 0) 1532 if ((m->m_flags & (M_MCAST | M_BCAST)) != 0)
1533 dst_if = NULL; 1533 dst_if = NULL;
1534 else 1534 else
1535 dst_if = bridge_rtlookup(sc, eh->ether_dhost); 1535 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1536 1536
1537 /* 1537 /*
1538 * In general, we need to handle TX offload in software before 1538 * In general, we need to handle TX offload in software before
1539 * enqueueing a packet. However, we can send it as is in the 1539 * enqueueing a packet. However, we can send it as is in the
1540 * cases of unicast via (1) the source interface, or (2) an 1540 * cases of unicast via (1) the source interface, or (2) an
1541 * interface which supports the specified offload options. 1541 * interface which supports the specified offload options.
1542 * For multicast or broadcast, send it as is only if (3) all 1542 * For multicast or broadcast, send it as is only if (3) all
1543 * the member interfaces support the specified options. 1543 * the member interfaces support the specified options.
1544 */ 1544 */
1545 1545
1546 /* 1546 /*
1547 * Unicast via the source interface. 1547 * Unicast via the source interface.
1548 */ 1548 */
1549 if (dst_if == ifp) 1549 if (dst_if == ifp)
1550 goto unicast_asis; 1550 goto unicast_asis;
1551 1551
1552 /* 1552 /*
1553 * Unicast via other interface. 1553 * Unicast via other interface.
1554 */ 1554 */
1555 if (dst_if != NULL) { 1555 if (dst_if != NULL) {
1556 KASSERT(m->m_flags & M_PKTHDR); 1556 KASSERT(m->m_flags & M_PKTHDR);
1557 if (TX_OFFLOAD_SUPPORTED(dst_if->if_csum_flags_tx, 1557 if (TX_OFFLOAD_SUPPORTED(dst_if->if_csum_flags_tx,
1558 m->m_pkthdr.csum_flags)) { 1558 m->m_pkthdr.csum_flags)) {
1559 /* 1559 /*
1560 * Unicast via an interface which supports the 1560 * Unicast via an interface which supports the
1561 * specified offload options. 1561 * specified offload options.
1562 */ 1562 */
1563 goto unicast_asis; 1563 goto unicast_asis;
1564 } 1564 }
1565 1565
1566 /* 1566 /*
1567 * Handle TX offload in software. For TSO, a packet is 1567 * Handle TX offload in software. For TSO, a packet is
1568 * split into multiple chunks. Thus, the return value of 1568 * split into multiple chunks. Thus, the return value of
1569 * ether_sw_offload_tx() is mbuf queue consists of them. 1569 * ether_sw_offload_tx() is mbuf queue consists of them.
1570 */ 1570 */
1571 m = ether_sw_offload_tx(ifp, m); 1571 m = ether_sw_offload_tx(ifp, m);
1572 if (m == NULL) 1572 if (m == NULL)
1573 return 0; 1573 return 0;
1574 1574
1575 do { 1575 do {
1576 n = m->m_nextpkt; 1576 n = m->m_nextpkt;
1577 if ((dst_if->if_flags & IFF_RUNNING) == 0) 1577 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1578 m_freem(m); 1578 m_freem(m);
1579 else 1579 else
1580 bridge_enqueue(sc, dst_if, m, 0); 1580 bridge_enqueue(sc, dst_if, m, 0);
1581 m = n; 1581 m = n;
1582 } while (m != NULL); 1582 } while (m != NULL);
1583 1583
1584 return 0; 1584 return 0;
1585 } 1585 }
1586 1586
1587 /* 1587 /*
1588 * Multicast or broadcast. 1588 * Multicast or broadcast.
1589 */ 1589 */
1590 if (TX_OFFLOAD_SUPPORTED(sc->sc_csum_flags_tx, 1590 if (TX_OFFLOAD_SUPPORTED(sc->sc_csum_flags_tx,
1591 m->m_pkthdr.csum_flags)) { 1591 m->m_pkthdr.csum_flags)) {
1592 /* 1592 /*
1593 * Specified TX offload options are supported by all 1593 * Specified TX offload options are supported by all
1594 * the member interfaces of this bridge. 1594 * the member interfaces of this bridge.
1595 */ 1595 */
1596 m->m_nextpkt = NULL; /* XXX */ 1596 m->m_nextpkt = NULL; /* XXX */
1597 } else { 1597 } else {
1598 /* 1598 /*
1599 * Otherwise, handle TX offload in software. 1599 * Otherwise, handle TX offload in software.
1600 */ 1600 */
1601 m = ether_sw_offload_tx(ifp, m); 1601 m = ether_sw_offload_tx(ifp, m);
1602 if (m == NULL) 1602 if (m == NULL)
1603 return 0; 1603 return 0;
1604 } 1604 }
1605 1605
1606 do { 1606 do {
1607 /* XXX Should call bridge_broadcast, but there are locking 1607 /* XXX Should call bridge_broadcast, but there are locking
1608 * issues which need resolving first. */ 1608 * issues which need resolving first. */
1609 struct bridge_iflist *bif; 1609 struct bridge_iflist *bif;
1610 struct mbuf *mc; 1610 struct mbuf *mc;
1611 bool used = false; 1611 bool used = false;
1612 1612
1613 n = m->m_nextpkt; 1613 n = m->m_nextpkt;
1614 1614
1615 BRIDGE_PSZ_RENTER(s); 1615 BRIDGE_PSZ_RENTER(s);
1616 BRIDGE_IFLIST_READER_FOREACH(bif, sc) { 1616 BRIDGE_IFLIST_READER_FOREACH(bif, sc) {
1617 struct psref psref; 1617 struct psref psref;
1618 1618
1619 bridge_acquire_member(sc, bif, &psref); 1619 bridge_acquire_member(sc, bif, &psref);
1620 BRIDGE_PSZ_REXIT(s); 1620 BRIDGE_PSZ_REXIT(s);
1621 1621
1622 dst_if = bif->bif_ifp; 1622 dst_if = bif->bif_ifp;
1623 if ((dst_if->if_flags & IFF_RUNNING) == 0) 1623 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1624 goto next; 1624 goto next;
1625 1625
1626 /* 1626 /*
1627 * If this is not the original output interface, 1627 * If this is not the original output interface,
1628 * and the interface is participating in spanning 1628 * and the interface is participating in spanning
1629 * tree, make sure the port is in a state that 1629 * tree, make sure the port is in a state that
1630 * allows forwarding. 1630 * allows forwarding.
1631 */ 1631 */
1632 if (dst_if != ifp && 1632 if (dst_if != ifp &&
1633 (bif->bif_flags & IFBIF_STP) != 0) { 1633 (bif->bif_flags & IFBIF_STP) != 0) {
1634 switch (bif->bif_state) { 1634 switch (bif->bif_state) {
1635 case BSTP_IFSTATE_BLOCKING: 1635 case BSTP_IFSTATE_BLOCKING:
1636 case BSTP_IFSTATE_LISTENING: 1636 case BSTP_IFSTATE_LISTENING:
1637 case BSTP_IFSTATE_DISABLED: 1637 case BSTP_IFSTATE_DISABLED:
1638 goto next; 1638 goto next;
1639 } 1639 }
1640 } 1640 }
1641 1641
1642 if (PSLIST_READER_NEXT(bif, struct bridge_iflist, 1642 if (PSLIST_READER_NEXT(bif, struct bridge_iflist,
1643 bif_next) == NULL && 1643 bif_next) == NULL &&
1644 ((m->m_flags & (M_MCAST | M_BCAST)) == 0 || 1644 ((m->m_flags & (M_MCAST | M_BCAST)) == 0 ||
1645 dst_if == ifp)) 1645 dst_if == ifp))
1646 { 1646 {
1647 used = true; 1647 used = true;
1648 mc = m; 1648 mc = m;
1649 } else { 1649 } else {
1650 mc = m_copypacket(m, M_DONTWAIT); 1650 mc = m_copypacket(m, M_DONTWAIT);
1651 if (mc == NULL) { 1651 if (mc == NULL) {
1652 sc->sc_if.if_oerrors++; 1652 sc->sc_if.if_oerrors++;
1653 goto next; 1653 goto next;
1654 } 1654 }
1655 } 1655 }
1656 1656
1657 bridge_enqueue(sc, dst_if, mc, 0); 1657 bridge_enqueue(sc, dst_if, mc, 0);
1658 1658
1659 if ((m->m_flags & (M_MCAST | M_BCAST)) != 0 && 1659 if ((m->m_flags & (M_MCAST | M_BCAST)) != 0 &&
1660 dst_if != ifp) 1660 dst_if != ifp)
1661 { 1661 {
1662 if (PSLIST_READER_NEXT(bif, 1662 if (PSLIST_READER_NEXT(bif,
1663 struct bridge_iflist, bif_next) == NULL) 1663 struct bridge_iflist, bif_next) == NULL)
1664 { 1664 {
1665 used = true; 1665 used = true;
1666 mc = m; 1666 mc = m;
1667 } else { 1667 } else {
1668 mc = m_copypacket(m, M_DONTWAIT); 1668 mc = m_copypacket(m, M_DONTWAIT);
1669 if (mc == NULL) { 1669 if (mc == NULL) {
1670 sc->sc_if.if_oerrors++; 1670 sc->sc_if.if_oerrors++;
1671 goto next; 1671 goto next;
1672 } 1672 }
1673 } 1673 }
1674 1674
1675 m_set_rcvif(mc, dst_if); 1675 m_set_rcvif(mc, dst_if);
1676 mc->m_flags &= ~M_PROMISC; 1676 mc->m_flags &= ~M_PROMISC;
1677 1677
1678 s = splsoftnet(); 1678 s = splsoftnet();
1679 KERNEL_LOCK_UNLESS_IFP_MPSAFE(dst_if); 1679 KERNEL_LOCK_UNLESS_IFP_MPSAFE(dst_if);
1680 ether_input(dst_if, mc); 1680 ether_input(dst_if, mc);
1681 KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(dst_if); 1681 KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(dst_if);
1682 splx(s); 1682 splx(s);
1683 } 1683 }
1684 1684
1685next: 1685next:
1686 BRIDGE_PSZ_RENTER(s); 1686 BRIDGE_PSZ_RENTER(s);
1687 bridge_release_member(sc, bif, &psref); 1687 bridge_release_member(sc, bif, &psref);
1688 1688
1689 /* Guarantee we don't re-enter the loop as we already 1689 /* Guarantee we don't re-enter the loop as we already
1690 * decided we're at the end. */ 1690 * decided we're at the end. */
1691 if (used) 1691 if (used)
1692 break; 1692 break;
1693 } 1693 }
1694 BRIDGE_PSZ_REXIT(s); 1694 BRIDGE_PSZ_REXIT(s);
1695 1695
1696 if (!used) 1696 if (!used)
1697 m_freem(m); 1697 m_freem(m);
1698 1698
1699 m = n; 1699 m = n;
1700 } while (m != NULL); 1700 } while (m != NULL);
1701 return 0; 1701 return 0;
1702 1702
1703unicast_asis: 1703unicast_asis:
1704 /* 1704 /*
1705 * XXX Spanning tree consideration here? 1705 * XXX Spanning tree consideration here?
1706 */ 1706 */
1707 if ((dst_if->if_flags & IFF_RUNNING) == 0) 1707 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1708 m_freem(m); 1708 m_freem(m);
1709 else 1709 else
1710 bridge_enqueue(sc, dst_if, m, 0); 1710 bridge_enqueue(sc, dst_if, m, 0);
1711 return 0; 1711 return 0;
1712} 1712}
1713 1713
1714/* 1714/*
1715 * bridge_start: 1715 * bridge_start:
1716 * 1716 *
1717 * Start output on a bridge. 1717 * Start output on a bridge.
1718 * 1718 *
1719 * NOTE: This routine should never be called in this implementation. 1719 * NOTE: This routine should never be called in this implementation.
1720 */ 1720 */
1721static void 1721static void
1722bridge_start(struct ifnet *ifp) 1722bridge_start(struct ifnet *ifp)
1723{ 1723{
1724 1724
1725 printf("%s: bridge_start() called\n", ifp->if_xname); 1725 printf("%s: bridge_start() called\n", ifp->if_xname);
1726} 1726}
1727 1727
1728/* 1728/*
1729 * bridge_forward: 1729 * bridge_forward:
1730 * 1730 *
1731 * The forwarding function of the bridge. 1731 * The forwarding function of the bridge.
1732 */ 1732 */
1733static void 1733static void
1734bridge_forward(struct bridge_softc *sc, struct mbuf *m) 1734bridge_forward(struct bridge_softc *sc, struct mbuf *m)
1735{ 1735{
1736 struct bridge_iflist *bif; 1736 struct bridge_iflist *bif;
1737 struct ifnet *src_if, *dst_if; 1737 struct ifnet *src_if, *dst_if;
1738 struct ether_header *eh; 1738 struct ether_header *eh;
1739 struct psref psref; 1739 struct psref psref;
1740 struct psref psref_src; 1740 struct psref psref_src;
1741 DECLARE_LOCK_VARIABLE; 1741 DECLARE_LOCK_VARIABLE;
1742 1742
1743 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 1743 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1744 return; 1744 return;
1745 1745
1746 src_if = m_get_rcvif_psref(m, &psref_src); 1746 src_if = m_get_rcvif_psref(m, &psref_src);
1747 if (src_if == NULL) { 1747 if (src_if == NULL) {
1748 /* Interface is being destroyed? */ 1748 /* Interface is being destroyed? */
1749 m_freem(m); 1749 m_freem(m);
1750 goto out; 1750 goto out;
1751 } 1751 }
1752 1752
1753 sc->sc_if.if_ipackets++; 1753 sc->sc_if.if_ipackets++;
1754 sc->sc_if.if_ibytes += m->m_pkthdr.len; 1754 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1755 1755
1756 /* 1756 /*
1757 * Look up the bridge_iflist. 1757 * Look up the bridge_iflist.
1758 */ 1758 */
1759 bif = bridge_lookup_member_if(sc, src_if, &psref); 1759 bif = bridge_lookup_member_if(sc, src_if, &psref);
1760 if (bif == NULL) { 1760 if (bif == NULL) {
1761 /* Interface is not a bridge member (anymore?) */ 1761 /* Interface is not a bridge member (anymore?) */
1762 m_freem(m); 1762 m_freem(m);
1763 goto out; 1763 goto out;
1764 } 1764 }
1765 1765
1766 if (bif->bif_flags & IFBIF_STP) { 1766 if (bif->bif_flags & IFBIF_STP) {
1767 switch (bif->bif_state) { 1767 switch (bif->bif_state) {
1768 case BSTP_IFSTATE_BLOCKING: 1768 case BSTP_IFSTATE_BLOCKING:
1769 case BSTP_IFSTATE_LISTENING: 1769 case BSTP_IFSTATE_LISTENING:
1770 case BSTP_IFSTATE_DISABLED: 1770 case BSTP_IFSTATE_DISABLED:
1771 m_freem(m); 1771 m_freem(m);
1772 bridge_release_member(sc, bif, &psref); 1772 bridge_release_member(sc, bif, &psref);
1773 goto out; 1773 goto out;
1774 } 1774 }
1775 } 1775 }
1776 1776
1777 eh = mtod(m, struct ether_header *); 1777 eh = mtod(m, struct ether_header *);
1778 1778
1779 /* 1779 /*
1780 * If the interface is learning, and the source 1780 * If the interface is learning, and the source
1781 * address is valid and not multicast, record 1781 * address is valid and not multicast, record
1782 * the address. 1782 * the address.
1783 */ 1783 */
1784 if ((bif->bif_flags & IFBIF_LEARNING) != 0 && 1784 if ((bif->bif_flags & IFBIF_LEARNING) != 0 &&
1785 ETHER_IS_MULTICAST(eh->ether_shost) == 0 && 1785 ETHER_IS_MULTICAST(eh->ether_shost) == 0 &&
1786 (eh->ether_shost[0] == 0 && 1786 (eh->ether_shost[0] == 0 &&
1787 eh->ether_shost[1] == 0 && 1787 eh->ether_shost[1] == 0 &&
1788 eh->ether_shost[2] == 0 && 1788 eh->ether_shost[2] == 0 &&
1789 eh->ether_shost[3] == 0 && 1789 eh->ether_shost[3] == 0 &&
1790 eh->ether_shost[4] == 0 && 1790 eh->ether_shost[4] == 0 &&
1791 eh->ether_shost[5] == 0) == 0) { 1791 eh->ether_shost[5] == 0) == 0) {
1792 (void) bridge_rtupdate(sc, eh->ether_shost, 1792 (void) bridge_rtupdate(sc, eh->ether_shost,
1793 src_if, 0, IFBAF_DYNAMIC); 1793 src_if, 0, IFBAF_DYNAMIC);
1794 } 1794 }
1795 1795
1796 if ((bif->bif_flags & IFBIF_STP) != 0 && 1796 if ((bif->bif_flags & IFBIF_STP) != 0 &&
1797 bif->bif_state == BSTP_IFSTATE_LEARNING) { 1797 bif->bif_state == BSTP_IFSTATE_LEARNING) {
1798 m_freem(m); 1798 m_freem(m);
1799 bridge_release_member(sc, bif, &psref); 1799 bridge_release_member(sc, bif, &psref);
1800 goto out; 1800 goto out;
1801 } 1801 }
1802 1802
1803 bridge_release_member(sc, bif, &psref); 1803 bridge_release_member(sc, bif, &psref);
1804 1804
1805 /* 1805 /*
1806 * At this point, the port either doesn't participate 1806 * At this point, the port either doesn't participate
1807 * in spanning tree or it is in the forwarding state. 1807 * in spanning tree or it is in the forwarding state.
1808 */ 1808 */
1809 1809
1810 /* 1810 /*
1811 * If the packet is unicast, destined for someone on 1811 * If the packet is unicast, destined for someone on
1812 * "this" side of the bridge, drop it. 1812 * "this" side of the bridge, drop it.
1813 */ 1813 */
1814 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) { 1814 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) {
1815 dst_if = bridge_rtlookup(sc, eh->ether_dhost); 1815 dst_if = bridge_rtlookup(sc, eh->ether_dhost);
1816 if (src_if == dst_if) { 1816 if (src_if == dst_if) {
1817 m_freem(m); 1817 m_freem(m);
1818 goto out; 1818 goto out;
1819 } 1819 }
1820 } else { 1820 } else {
1821 /* ...forward it to all interfaces. */ 1821 /* ...forward it to all interfaces. */
1822 sc->sc_if.if_imcasts++; 1822 sc->sc_if.if_imcasts++;
1823 dst_if = NULL; 1823 dst_if = NULL;
1824 } 1824 }
1825 1825
1826 if (pfil_run_hooks(sc->sc_if.if_pfil, &m, src_if, PFIL_IN) != 0) { 1826 if (pfil_run_hooks(sc->sc_if.if_pfil, &m, src_if, PFIL_IN) != 0) {
1827 if (m != NULL) 1827 if (m != NULL)
1828 m_freem(m); 1828 m_freem(m);
1829 goto out; 1829 goto out;
1830 } 1830 }
1831 if (m == NULL) 1831 if (m == NULL)
1832 goto out; 1832 goto out;
1833 1833
1834 if (dst_if == NULL) { 1834 if (dst_if == NULL) {
1835 bridge_broadcast(sc, src_if, m); 1835 bridge_broadcast(sc, src_if, m);
1836 goto out; 1836 goto out;
1837 } 1837 }
1838 1838
1839 m_put_rcvif_psref(src_if, &psref_src); 1839 m_put_rcvif_psref(src_if, &psref_src);
1840 src_if = NULL; 1840 src_if = NULL;
1841 1841
1842 /* 1842 /*
1843 * At this point, we're dealing with a unicast frame 1843 * At this point, we're dealing with a unicast frame
1844 * going to a different interface. 1844 * going to a different interface.
1845 */ 1845 */
1846 if ((dst_if->if_flags & IFF_RUNNING) == 0) { 1846 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1847 m_freem(m); 1847 m_freem(m);
1848 goto out; 1848 goto out;
1849 } 1849 }
1850 1850
1851 bif = bridge_lookup_member_if(sc, dst_if, &psref); 1851 bif = bridge_lookup_member_if(sc, dst_if, &psref);
1852 if (bif == NULL) { 1852 if (bif == NULL) {
1853 /* Not a member of the bridge (anymore?) */ 1853 /* Not a member of the bridge (anymore?) */
1854 m_freem(m); 1854 m_freem(m);
1855 goto out; 1855 goto out;
1856 } 1856 }
1857 1857
1858 if (bif->bif_flags & IFBIF_STP) { 1858 if (bif->bif_flags & IFBIF_STP) {
1859 switch (bif->bif_state) { 1859 switch (bif->bif_state) {
1860 case BSTP_IFSTATE_DISABLED: 1860 case BSTP_IFSTATE_DISABLED:
1861 case BSTP_IFSTATE_BLOCKING: 1861 case BSTP_IFSTATE_BLOCKING:
1862 m_freem(m); 1862 m_freem(m);
1863 bridge_release_member(sc, bif, &psref); 1863 bridge_release_member(sc, bif, &psref);
1864 goto out; 1864 goto out;
1865 } 1865 }
1866 } 1866 }
1867 1867
1868 bridge_release_member(sc, bif, &psref); 1868 bridge_release_member(sc, bif, &psref);
1869 1869
1870 /* 1870 /*
1871 * Before enqueueing this packet to the destination interface, 1871 * Before enqueueing this packet to the destination interface,
1872 * clear any in-bound checksum flags to prevent them from being 1872 * clear any in-bound checksum flags to prevent them from being
1873 * misused as out-bound flags. 1873 * misused as out-bound flags.
1874 */ 1874 */
1875 m->m_pkthdr.csum_flags = 0; 1875 m->m_pkthdr.csum_flags = 0;
1876 1876
1877 ACQUIRE_GLOBAL_LOCKS(); 1877 ACQUIRE_GLOBAL_LOCKS();
1878 bridge_enqueue(sc, dst_if, m, 1); 1878 bridge_enqueue(sc, dst_if, m, 1);
1879 RELEASE_GLOBAL_LOCKS(); 1879 RELEASE_GLOBAL_LOCKS();
1880out: 1880out:
1881 if (src_if != NULL) 1881 if (src_if != NULL)
1882 m_put_rcvif_psref(src_if, &psref_src); 1882 m_put_rcvif_psref(src_if, &psref_src);
1883 return; 1883 return;
1884} 1884}
1885 1885
1886static bool 1886static bool
1887bstp_state_before_learning(struct bridge_iflist *bif) 1887bstp_state_before_learning(struct bridge_iflist *bif)
1888{ 1888{
1889 if (bif->bif_flags & IFBIF_STP) { 1889 if (bif->bif_flags & IFBIF_STP) {
1890 switch (bif->bif_state) { 1890 switch (bif->bif_state) {
1891 case BSTP_IFSTATE_BLOCKING: 1891 case BSTP_IFSTATE_BLOCKING:
1892 case BSTP_IFSTATE_LISTENING: 1892 case BSTP_IFSTATE_LISTENING:
1893 case BSTP_IFSTATE_DISABLED: 1893 case BSTP_IFSTATE_DISABLED:
1894 return true; 1894 return true;
1895 } 1895 }
1896 } 1896 }
1897 return false; 1897 return false;
1898} 1898}
1899 1899
1900static bool 1900static bool
1901bridge_ourether(struct bridge_iflist *bif, struct ether_header *eh, int src) 1901bridge_ourether(struct bridge_iflist *bif, struct ether_header *eh, int src)
1902{ 1902{
1903 uint8_t *ether = src ? eh->ether_shost : eh->ether_dhost; 1903 uint8_t *ether = src ? eh->ether_shost : eh->ether_dhost;
1904 1904
1905 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), ether, ETHER_ADDR_LEN) == 0 1905 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), ether, ETHER_ADDR_LEN) == 0
1906#if NCARP > 0 1906#if NCARP > 0
1907 || (bif->bif_ifp->if_carp && 1907 || (bif->bif_ifp->if_carp &&
1908 carp_ourether(bif->bif_ifp->if_carp, eh, IFT_ETHER, src) != NULL) 1908 carp_ourether(bif->bif_ifp->if_carp, eh, IFT_ETHER, src) != NULL)
1909#endif /* NCARP > 0 */ 1909#endif /* NCARP > 0 */
1910 ) 1910 )
1911 return true; 1911 return true;
1912 1912
1913 return false; 1913 return false;
1914} 1914}
1915 1915
1916/* 1916/*
1917 * bridge_input: 1917 * bridge_input: