Bug Summary

File:net/if_bridge.c
Warning:line 1634, column 5
Value stored to 'error' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_bridge.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/net/if_bridge.c
1/* $OpenBSD: if_bridge.c,v 1.363 2022/01/04 06:32:39 yasuoka Exp $ */
2
3/*
4 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Effort sponsored in part by the Defense Advanced Research Projects
29 * Agency (DARPA) and Air Force Research Laboratory, Air Force
30 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
31 *
32 */
33
34#include "bpfilter.h"
35#include "gif.h"
36#include "pf.h"
37#include "carp.h"
38#include "vlan.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/mbuf.h>
43#include <sys/socket.h>
44#include <sys/ioctl.h>
45#include <sys/kernel.h>
46
47#include <net/if.h>
48#include <net/if_types.h>
49#include <net/if_llc.h>
50#include <net/netisr.h>
51
52#include <netinet/in.h>
53#include <netinet/ip.h>
54#include <netinet/ip_var.h>
55#include <netinet/if_ether.h>
56#include <netinet/ip_icmp.h>
57
58#ifdef IPSEC1
59#include <netinet/ip_ipsp.h>
60#include <net/if_enc.h>
61#endif
62
63#ifdef INET61
64#include <netinet6/in6_var.h>
65#include <netinet/ip6.h>
66#include <netinet6/ip6_var.h>
67#endif
68
69#if NPF1 > 0
70#include <net/pfvar.h>
71#define BRIDGE_INPF_IN PF_IN
72#define BRIDGE_OUTPF_OUT PF_OUT
73#else
74#define BRIDGE_INPF_IN 0
75#define BRIDGE_OUTPF_OUT 1
76#endif
77
78#if NBPFILTER1 > 0
79#include <net/bpf.h>
80#endif
81
82#if NCARP1 > 0
83#include <netinet/ip_carp.h>
84#endif
85
86#if NVLAN1 > 0
87#include <net/if_vlan_var.h>
88#endif
89
90#include <net/if_bridge.h>
91
92/*
93 * Maximum number of addresses to cache
94 */
95#ifndef BRIDGE_RTABLE_MAX100
96#define BRIDGE_RTABLE_MAX100 100
97#endif
98
99/*
100 * Timeout (in seconds) for entries learned dynamically
101 */
102#ifndef BRIDGE_RTABLE_TIMEOUT240
103#define BRIDGE_RTABLE_TIMEOUT240 240
104#endif
105
106void bridgeattach(int);
107int bridge_ioctl(struct ifnet *, u_long, caddr_t);
108void bridge_ifdetach(void *);
109void bridge_spandetach(void *);
110int bridge_ifremove(struct bridge_iflist *);
111void bridge_spanremove(struct bridge_iflist *);
112struct mbuf *
113 bridge_input(struct ifnet *, struct mbuf *, uint64_t, void *);
114void bridge_process(struct ifnet *, struct mbuf *);
115void bridgeintr_frame(struct ifnet *, struct ifnet *, struct mbuf *);
116void bridge_bifgetstp(struct bridge_softc *, struct bridge_iflist *,
117 struct ifbreq *);
118void bridge_broadcast(struct bridge_softc *, struct ifnet *,
119 struct ether_header *, struct mbuf *);
120int bridge_localbroadcast(struct ifnet *, struct ether_header *,
121 struct mbuf *);
122void bridge_span(struct ifnet *, struct mbuf *);
123void bridge_stop(struct bridge_softc *);
124void bridge_init(struct bridge_softc *);
125int bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
126int bridge_blocknonip(struct ether_header *, struct mbuf *);
127void bridge_ifinput(struct ifnet *, struct mbuf *);
128int bridge_dummy_output(struct ifnet *, struct mbuf *, struct sockaddr *,
129 struct rtentry *);
130void bridge_send_icmp_err(struct ifnet *, struct ether_header *,
131 struct mbuf *, int, struct llc *, int, int, int);
132int bridge_ifenqueue(struct ifnet *, struct ifnet *, struct mbuf *);
133struct mbuf *bridge_ip(struct ifnet *, int, struct ifnet *,
134 struct ether_header *, struct mbuf *);
135#ifdef IPSEC1
136int bridge_ipsec(struct ifnet *, struct ether_header *, int, struct llc *,
137 int, int, int, struct mbuf *);
138#endif
139int bridge_clone_create(struct if_clone *, int);
140int bridge_clone_destroy(struct ifnet *);
141void bridge_take(void *);
142void bridge_rele(void *);
143
144#define ETHERADDR_IS_IP_MCAST(a)((a)->ether_addr_octet[0] == 0x01 && (a)->ether_addr_octet
[1] == 0x00 && (a)->ether_addr_octet[2] == 0x5e)
\
145 /* struct etheraddr *a; */ \
146 ((a)->ether_addr_octet[0] == 0x01 && \
147 (a)->ether_addr_octet[1] == 0x00 && \
148 (a)->ether_addr_octet[2] == 0x5e)
149
150struct niqueue bridgeintrq = NIQUEUE_INITIALIZER(1024, NETISR_BRIDGE){ { { ((void *)0), ((((0x7)) > 0x0 && ((0x7)) <
0x9) ? 0x9 : ((0x7))), 0x0 }, { ((void *)0), ((void *)0), 0 }
, ((1024)), 0 }, (29) }
;
151
152struct if_clone bridge_cloner =
153 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy){ .ifc_list = { ((void *)0), ((void *)0) }, .ifc_name = "bridge"
, .ifc_namelen = sizeof("bridge") - 1, .ifc_create = bridge_clone_create
, .ifc_destroy = bridge_clone_destroy, }
;
154
155const struct ether_brport bridge_brport = {
156 bridge_input,
157 bridge_take,
158 bridge_rele,
159 NULL((void *)0),
160};
161
162void
163bridgeattach(int n)
164{
165 if_clone_attach(&bridge_cloner);
166}
167
168int
169bridge_clone_create(struct if_clone *ifc, int unit)
170{
171 struct bridge_softc *sc;
172 struct ifnet *ifp;
173 int i;
174
175 sc = malloc(sizeof(*sc), M_DEVBUF2, M_WAITOK0x0001|M_ZERO0x0008);
176 sc->sc_stp = bstp_create();
177 if (!sc->sc_stp) {
178 free(sc, M_DEVBUF2, sizeof *sc);
179 return (ENOMEM12);
180 }
181
182 sc->sc_brtmax = BRIDGE_RTABLE_MAX100;
183 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT240;
184 timeout_set(&sc->sc_brtimeout, bridge_rtage, sc);
185 SMR_SLIST_INIT(&sc->sc_iflist)do { (&sc->sc_iflist)->smr_slh_first = ((void *)0);
} while (0)
;
186 SMR_SLIST_INIT(&sc->sc_spanlist)do { (&sc->sc_spanlist)->smr_slh_first = ((void *)0
); } while (0)
;
187 mtx_init(&sc->sc_mtx, IPL_MPFLOOR)do { (void)(((void *)0)); (void)(0); __mtx_init((&sc->
sc_mtx), ((((0x9)) > 0x0 && ((0x9)) < 0x9) ? 0x9
: ((0x9)))); } while (0)
;
188 for (i = 0; i < BRIDGE_RTABLE_SIZE1024; i++)
189 LIST_INIT(&sc->sc_rts[i])do { ((&sc->sc_rts[i])->lh_first) = ((void *)0); } while
(0)
;
190 arc4random_buf(&sc->sc_hashkey, sizeof(sc->sc_hashkey));
191 ifp = &sc->sc_if;
192 snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
193 unit);
194 ifp->if_softc = sc;
195 ifp->if_mtuif_data.ifi_mtu = ETHERMTU(1518 - ((6 * 2) + 2) - 4);
196 ifp->if_ioctl = bridge_ioctl;
197 ifp->if_output = bridge_dummy_output;
198 ifp->if_xflags = IFXF_CLONED0x2;
199 ifp->if_start = NULL((void *)0);
200 ifp->if_typeif_data.ifi_type = IFT_BRIDGE0xd1;
201 ifp->if_hdrlenif_data.ifi_hdrlen = ETHER_HDR_LEN((6 * 2) + 2);
202
203 if_attach(ifp);
204 if_alloc_sadl(ifp);
205
206#if NBPFILTER1 > 0
207 bpfattach(&sc->sc_if.if_bpf, ifp,
208 DLT_EN10MB1, ETHER_HDR_LEN((6 * 2) + 2));
209#endif
210
211 return (0);
212}
213
214int
215bridge_dummy_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
216 struct rtentry *rt)
217{
218 m_freem(m);
219 return (EAFNOSUPPORT47);
220}
221
222int
223bridge_clone_destroy(struct ifnet *ifp)
224{
225 struct bridge_softc *sc = ifp->if_softc;
226 struct bridge_iflist *bif;
227
228 /*
229 * bridge(4) detach hook doesn't need the NET_LOCK(), worst the
230 * use of smr_barrier() while holding the lock might lead to a
231 * deadlock situation.
232 */
233 NET_ASSERT_UNLOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s == 0x0001UL)) splassert_fail(0, 0x0001UL, __func__
); } while (0)
;
234
235 bridge_stop(sc);
236 bridge_rtflush(sc, IFBF_FLUSHALL0x1);
237 while ((bif = SMR_SLIST_FIRST_LOCKED(&sc->sc_iflist)(*(&(&sc->sc_iflist)->smr_slh_first))) != NULL((void *)0))
238 bridge_ifremove(bif);
239 while ((bif = SMR_SLIST_FIRST_LOCKED(&sc->sc_spanlist)(*(&(&sc->sc_spanlist)->smr_slh_first))) != NULL((void *)0))
240 bridge_spanremove(bif);
241
242 bstp_destroy(sc->sc_stp);
243
244 if_detach(ifp);
245
246 free(sc, M_DEVBUF2, sizeof *sc);
247 return (0);
248}
249
250int
251bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
252{
253 struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
254 struct ifbreq *req = (struct ifbreq *)data;
255 struct ifbropreq *brop = (struct ifbropreq *)data;
256 struct ifnet *ifs;
257 struct bridge_iflist *bif;
258 struct bstp_port *bp;
259 struct bstp_state *bs = sc->sc_stp;
260 int error = 0;
261
262 /*
263 * bridge(4) data structure aren't protected by the NET_LOCK().
264 * Idealy it shouldn't be taken before calling `ifp->if_ioctl'
265 * but we aren't there yet.
266 */
267 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
268
269 switch (cmd) {
270 case SIOCBRDGADD((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((60)))
:
271 /* bridge(4) does not distinguish between routing/forwarding ports */
272 case SIOCBRDGADDL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((73)))
:
273 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
274 break;
275
276 ifs = if_unit(req->ifbr_ifsname);
277 if (ifs == NULL((void *)0)) { /* no such interface */
278 error = ENOENT2;
279 break;
280 }
281 if (ifs->if_typeif_data.ifi_type != IFT_ETHER0x06) {
282 if_put(ifs);
283 error = EINVAL22;
284 break;
285 }
286 if (ifs->if_bridgeidx != 0) {
287 if (ifs->if_bridgeidx == ifp->if_index)
288 error = EEXIST17;
289 else
290 error = EBUSY16;
291 if_put(ifs);
292 break;
293 }
294
295 error = ether_brport_isset(ifs);
296 if (error != 0) {
297 if_put(ifs);
298 break;
299 }
300
301 /* If it's in the span list, it can't be a member. */
302 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next)for ((bif) = (*(&(&sc->sc_spanlist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
303 if (bif->ifp == ifs)
304 break;
305 }
306 if (bif != NULL((void *)0)) {
307 if_put(ifs);
308 error = EBUSY16;
309 break;
310 }
311
312 bif = malloc(sizeof(*bif), M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
313 if (bif == NULL((void *)0)) {
314 if_put(ifs);
315 error = ENOMEM12;
316 break;
317 }
318
319 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
320 error = ifpromisc(ifs, 1);
321 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
322 if (error != 0) {
323 if_put(ifs);
324 free(bif, M_DEVBUF2, sizeof(*bif));
325 break;
326 }
327
328 /*
329 * XXX If the NET_LOCK() or ifpromisc() calls above
330 * had to sleep, then something else could have come
331 * along and taken over ifs while the kernel lock was
332 * released.
333 */
334
335 bif->bridge_sc = sc;
336 bif->ifp = ifs;
337 bif->bif_flags = IFBIF_LEARNING0x0001 | IFBIF_DISCOVER0x0002;
338 SIMPLEQ_INIT(&bif->bif_brlin)do { (&bif->bif_brlin)->sqh_first = ((void *)0); (&
bif->bif_brlin)->sqh_last = &(&bif->bif_brlin
)->sqh_first; } while (0)
;
339 SIMPLEQ_INIT(&bif->bif_brlout)do { (&bif->bif_brlout)->sqh_first = ((void *)0); (
&bif->bif_brlout)->sqh_last = &(&bif->bif_brlout
)->sqh_first; } while (0)
;
340 ifs->if_bridgeidx = ifp->if_index;
341 task_set(&bif->bif_dtask, bridge_ifdetach, bif);
342 if_detachhook_add(ifs, &bif->bif_dtask);
343 ether_brport_set(bif->ifp, &bridge_brport);
344 SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_iflist, bif, bif_next)do { (bif)->bif_next.smr_sle_next = (&sc->sc_iflist
)->smr_slh_first; do { __asm volatile("" ::: "memory"); } while
(0); (&sc->sc_iflist)->smr_slh_first = (bif); } while
(0)
;
345 break;
346 case SIOCBRDGDEL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((61)))
:
347 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
348 break;
349 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
350 if (error != 0)
351 break;
352 bridge_ifremove(bif);
353 break;
354 case SIOCBRDGIFS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((66)))
:
355 error = bridge_bifconf(sc, (struct ifbifconf *)data);
356 break;
357 case SIOCBRDGADDS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((65)))
:
358 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
359 break;
360 ifs = if_unit(req->ifbr_ifsname);
361 if (ifs == NULL((void *)0)) { /* no such interface */
362 error = ENOENT2;
363 break;
364 }
365 if (ifs->if_typeif_data.ifi_type != IFT_ETHER0x06) {
366 if_put(ifs);
367 error = EINVAL22;
368 break;
369 }
370 if (ifs->if_bridgeidx != 0) {
371 if (ifs->if_bridgeidx == ifp->if_index)
372 error = EEXIST17;
373 else
374 error = EBUSY16;
375 if_put(ifs);
376 break;
377 }
378 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next)for ((bif) = (*(&(&sc->sc_spanlist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
379 if (bif->ifp == ifs)
380 break;
381 }
382 if (bif != NULL((void *)0)) {
383 if_put(ifs);
384 error = EEXIST17;
385 break;
386 }
387 bif = malloc(sizeof(*bif), M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
388 if (bif == NULL((void *)0)) {
389 if_put(ifs);
390 error = ENOMEM12;
391 break;
392 }
393 bif->bridge_sc = sc;
394 bif->ifp = ifs;
395 bif->bif_flags = IFBIF_SPAN0x0100;
396 SIMPLEQ_INIT(&bif->bif_brlin)do { (&bif->bif_brlin)->sqh_first = ((void *)0); (&
bif->bif_brlin)->sqh_last = &(&bif->bif_brlin
)->sqh_first; } while (0)
;
397 SIMPLEQ_INIT(&bif->bif_brlout)do { (&bif->bif_brlout)->sqh_first = ((void *)0); (
&bif->bif_brlout)->sqh_last = &(&bif->bif_brlout
)->sqh_first; } while (0)
;
398 task_set(&bif->bif_dtask, bridge_spandetach, bif);
399 if_detachhook_add(ifs, &bif->bif_dtask);
400 SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_spanlist, bif, bif_next)do { (bif)->bif_next.smr_sle_next = (&sc->sc_spanlist
)->smr_slh_first; do { __asm volatile("" ::: "memory"); } while
(0); (&sc->sc_spanlist)->smr_slh_first = (bif); } while
(0)
;
401 break;
402 case SIOCBRDGDELS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((66)))
:
403 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
404 break;
405 ifs = if_unit(req->ifbr_ifsname);
406 if (ifs == NULL((void *)0)) {
407 error = ENOENT2;
408 break;
409 }
410 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next)for ((bif) = (*(&(&sc->sc_spanlist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
411 if (bif->ifp == ifs)
412 break;
413 }
414 if_put(ifs);
415 if (bif == NULL((void *)0)) {
416 error = ESRCH3;
417 break;
418 }
419 bridge_spanremove(bif);
420 break;
421 case SIOCBRDGGIFFLGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((62)))
:
422 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
423 if (error != 0)
424 break;
425 req->ifbr_ifsflags = bif->bif_flags;
426 req->ifbr_portno = bif->ifp->if_index & 0xfff;
427 req->ifbr_protected = bif->bif_protected;
428 if (bif->bif_flags & IFBIF_STP0x0008)
429 bridge_bifgetstp(sc, bif, req);
430 break;
431 case SIOCBRDGSIFFLGS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((63)))
:
432 if (req->ifbr_ifsflags & IFBIF_RO_MASK0x0f00) {
433 error = EINVAL22;
434 break;
435 }
436 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0)
437 break;
438 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
439 if (error != 0)
440 break;
441 if (req->ifbr_ifsflags & IFBIF_STP0x0008) {
442 if ((bif->bif_flags & IFBIF_STP0x0008) == 0) {
443 /* Enable STP */
444 if ((bif->bif_stp = bstp_add(sc->sc_stp,
445 bif->ifp)) == NULL((void *)0)) {
446 error = ENOMEM12;
447 break;
448 }
449 } else {
450 /* Update STP flags */
451 bstp_ifsflags(bif->bif_stp, req->ifbr_ifsflags);
452 }
453 } else if (bif->bif_flags & IFBIF_STP0x0008) {
454 bstp_delete(bif->bif_stp);
455 bif->bif_stp = NULL((void *)0);
456 }
457 bif->bif_flags = req->ifbr_ifsflags;
458 break;
459 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
460 if ((ifp->if_flags & IFF_UP0x1) == IFF_UP0x1)
461 bridge_init(sc);
462
463 if ((ifp->if_flags & IFF_UP0x1) == 0)
464 bridge_stop(sc);
465
466 break;
467 case SIOCBRDGGPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbropreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((88)))
:
468 if ((bp = bs->bs_root_port) == NULL((void *)0))
469 brop->ifbop_root_port = 0;
470 else
471 brop->ifbop_root_port = bp->bp_ifindex;
472 brop->ifbop_maxage = bs->bs_bridge_max_age >> 8;
473 brop->ifbop_hellotime = bs->bs_bridge_htime >> 8;
474 brop->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8;
475 brop->ifbop_holdcount = bs->bs_txholdcount;
476 brop->ifbop_priority = bs->bs_bridge_priority;
477 brop->ifbop_protocol = bs->bs_protover;
478 brop->ifbop_root_bridge = bs->bs_root_pv.pv_root_id;
479 brop->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
480 brop->ifbop_root_port = bs->bs_root_pv.pv_port_id;
481 brop->ifbop_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
482 brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
483 brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
484 break;
485 case SIOCBRDGSIFPROT((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((74)))
:
486 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
487 if (error != 0)
488 break;
489 bif->bif_protected = req->ifbr_protected;
490 break;
491 case SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbaconf) & 0x1fff) << 16) | ((('i')) <<
8) | ((67)))
:
492 case SIOCBRDGGCACHE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((65)))
:
493 case SIOCBRDGGPRI(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((80)))
:
494 case SIOCBRDGGMA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((83)))
:
495 case SIOCBRDGGHT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((81)))
:
496 case SIOCBRDGGFD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((82)))
:
497 case SIOCBRDGGTO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((70)))
:
498 case SIOCBRDGGRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrlconf) & 0x1fff) << 16) | ((('i')) <<
8) | ((79)))
:
499 break;
500 case SIOCBRDGFLUSH((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((72)))
:
501 case SIOCBRDGSADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((68)))
:
502 case SIOCBRDGDADDR((unsigned long)0x80000000 | ((sizeof(struct ifbareq) & 0x1fff
) << 16) | ((('i')) << 8) | ((71)))
:
503 case SIOCBRDGSCACHE((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((64)))
:
504 case SIOCBRDGSTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((69)))
:
505 case SIOCBRDGARL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((77)))
:
506 case SIOCBRDGFRL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((78)))
:
507 case SIOCBRDGSPRI((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((80)))
:
508 case SIOCBRDGSFD((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((82)))
:
509 case SIOCBRDGSMA((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((83)))
:
510 case SIOCBRDGSHT((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((81)))
:
511 case SIOCBRDGSTXHC((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((89)))
:
512 case SIOCBRDGSPROTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((90)))
:
513 case SIOCBRDGSIFPRIO((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((84)))
:
514 case SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((85)))
:
515 error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
516 break;
517 default:
518 error = ENOTTY25;
519 break;
520 }
521
522 if (!error)
523 error = bridgectl_ioctl(ifp, cmd, data);
524
525 if (!error)
526 error = bstp_ioctl(ifp, cmd, data);
527
528 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
529 return (error);
530}
531
532/* Detach an interface from a bridge. */
533int
534bridge_ifremove(struct bridge_iflist *bif)
535{
536 struct bridge_softc *sc = bif->bridge_sc;
537 int error;
538
539 SMR_SLIST_REMOVE_LOCKED(&sc->sc_iflist, bif, bridge_iflist, bif_next)do { if ((&sc->sc_iflist)->smr_slh_first == (bif)) {
do { ((&sc->sc_iflist))->smr_slh_first = ((&sc
->sc_iflist))->smr_slh_first->bif_next.smr_sle_next;
} while (0); } else { struct bridge_iflist *curelm = (&sc
->sc_iflist)->smr_slh_first; while (curelm->bif_next
.smr_sle_next != (bif)) curelm = curelm->bif_next.smr_sle_next
; curelm->bif_next.smr_sle_next = curelm->bif_next.smr_sle_next
->bif_next.smr_sle_next; } } while (0)
;
540 if_detachhook_del(bif->ifp, &bif->bif_dtask);
541 ether_brport_clr(bif->ifp);
542
543 smr_barrier()smr_barrier_impl(0);
544
545 if (bif->bif_flags & IFBIF_STP0x0008) {
546 bstp_delete(bif->bif_stp);
547 bif->bif_stp = NULL((void *)0);
548 }
549
550 bif->ifp->if_bridgeidx = 0;
551 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
552 error = ifpromisc(bif->ifp, 0);
553 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
554
555 bridge_rtdelete(sc, bif->ifp, 0);
556 bridge_flushrule(bif);
557
558 if_put(bif->ifp);
559 bif->ifp = NULL((void *)0);
560 free(bif, M_DEVBUF2, sizeof(*bif));
561
562 return (error);
563}
564
565void
566bridge_spanremove(struct bridge_iflist *bif)
567{
568 struct bridge_softc *sc = bif->bridge_sc;
569
570 SMR_SLIST_REMOVE_LOCKED(&sc->sc_spanlist, bif, bridge_iflist, bif_next)do { if ((&sc->sc_spanlist)->smr_slh_first == (bif)
) { do { ((&sc->sc_spanlist))->smr_slh_first = ((&
sc->sc_spanlist))->smr_slh_first->bif_next.smr_sle_next
;} while (0); } else { struct bridge_iflist *curelm = (&sc
->sc_spanlist)->smr_slh_first; while (curelm->bif_next
.smr_sle_next != (bif)) curelm = curelm->bif_next.smr_sle_next
; curelm->bif_next.smr_sle_next = curelm->bif_next.smr_sle_next
->bif_next.smr_sle_next; } } while (0)
;
571 if_detachhook_del(bif->ifp, &bif->bif_dtask);
572
573 smr_barrier()smr_barrier_impl(0);
574
575 if_put(bif->ifp);
576 bif->ifp = NULL((void *)0);
577 free(bif, M_DEVBUF2, sizeof(*bif));
578}
579
580void
581bridge_ifdetach(void *xbif)
582{
583 struct bridge_iflist *bif = xbif;
584
585 /*
586 * bridge(4) detach hook doesn't need the NET_LOCK(), worst the
587 * use of smr_barrier() while holding the lock might lead to a
588 * deadlock situation.
589 */
590 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
591 bridge_ifremove(bif);
592 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
593}
594
595void
596bridge_spandetach(void *xbif)
597{
598 struct bridge_iflist *bif = xbif;
599
600 /*
601 * bridge(4) detach hook doesn't need the NET_LOCK(), worst the
602 * use of smr_barrier() while holding the lock might lead to a
603 * deadlock situation.
604 */
605 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
606 bridge_spanremove(bif);
607 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
608}
609
610void
611bridge_bifgetstp(struct bridge_softc *sc, struct bridge_iflist *bif,
612 struct ifbreq *breq)
613{
614 struct bstp_state *bs = sc->sc_stp;
615 struct bstp_port *bp = bif->bif_stp;
616
617 breq->ifbr_state = bstp_getstate(bs, bp);
618 breq->ifbr_priority = bp->bp_priority;
619 breq->ifbr_path_cost = bp->bp_path_cost;
620 breq->ifbr_proto = bp->bp_protover;
621 breq->ifbr_role = bp->bp_role;
622 breq->ifbr_stpflags = bp->bp_flags;
623 breq->ifbr_fwd_trans = bp->bp_forward_transitions;
624 breq->ifbr_root_bridge = bs->bs_root_pv.pv_root_id;
625 breq->ifbr_root_cost = bs->bs_root_pv.pv_cost;
626 breq->ifbr_root_port = bs->bs_root_pv.pv_port_id;
627 breq->ifbr_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
628 breq->ifbr_desg_port = bs->bs_root_pv.pv_dport_id;
629
630 /* Copy STP state options as flags */
631 if (bp->bp_operedge)
632 breq->ifbr_ifsflags |= IFBIF_BSTP_EDGE0x0010;
633 if (bp->bp_flags & BSTP_PORT_AUTOEDGE0x0010)
634 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE0x0020;
635 if (bp->bp_ptp_link)
636 breq->ifbr_ifsflags |= IFBIF_BSTP_PTP0x0040;
637 if (bp->bp_flags & BSTP_PORT_AUTOPTP0x0020)
638 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP0x0080;
639}
640
641int
642bridge_bifconf(struct bridge_softc *sc, struct ifbifconf *bifc)
643{
644 struct bridge_iflist *bif;
645 u_int32_t total = 0, i = 0;
646 int error = 0;
647 struct ifbreq *breq, *breqs = NULL((void *)0);
648
649 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
650 total++;
651
652 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next)for ((bif) = (*(&(&sc->sc_spanlist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
653 total++;
654
655 if (bifc->ifbic_len == 0) {
656 i = total;
657 goto done;
658 }
659
660 breqs = mallocarray(total, sizeof(*breqs), M_TEMP127, M_NOWAIT0x0002|M_ZERO0x0008);
661 if (breqs == NULL((void *)0))
662 goto done;
663
664 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
665 if (bifc->ifbic_len < (i + 1) * sizeof(*breqs))
666 break;
667 breq = &breqs[i];
668 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ16);
669 strlcpy(breq->ifbr_ifsname, bif->ifp->if_xname, IFNAMSIZ16);
670 breq->ifbr_ifsflags = bif->bif_flags;
671 breq->ifbr_portno = bif->ifp->if_index & 0xfff;
672 breq->ifbr_protected = bif->bif_protected;
673 if (bif->bif_flags & IFBIF_STP0x0008)
674 bridge_bifgetstp(sc, bif, breq);
675 i++;
676 }
677 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next)for ((bif) = (*(&(&sc->sc_spanlist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
678 if (bifc->ifbic_len < (i + 1) * sizeof(*breqs))
679 break;
680 breq = &breqs[i];
681 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ16);
682 strlcpy(breq->ifbr_ifsname, bif->ifp->if_xname, IFNAMSIZ16);
683 breq->ifbr_ifsflags = bif->bif_flags | IFBIF_SPAN0x0100;
684 breq->ifbr_portno = bif->ifp->if_index & 0xfff;
685 i++;
686 }
687
688 error = copyout(breqs, bifc->ifbic_reqifbic_ifbicu.ifbicu_req, i * sizeof(*breqs));
689done:
690 free(breqs, M_TEMP127, total * sizeof(*breq));
691 bifc->ifbic_len = i * sizeof(*breq);
692 return (error);
693}
694
695int
696bridge_findbif(struct bridge_softc *sc, const char *name,
697 struct bridge_iflist **rbif)
698{
699 struct ifnet *ifp;
700 struct bridge_iflist *bif;
701 int error = 0;
702
703 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 703, "_kernel_lock_held()"))
;
704
705 if ((ifp = if_unit(name)) == NULL((void *)0))
706 return (ENOENT2);
707
708 if (ifp->if_bridgeidx != sc->sc_if.if_index) {
709 error = ESRCH3;
710 goto put;
711 }
712
713 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
714 if (bif->ifp == ifp)
715 break;
716 }
717
718 if (bif == NULL((void *)0)) {
719 error = ENOENT2;
720 goto put;
721 }
722
723 *rbif = bif;
724put:
725 if_put(ifp);
726
727 return (error);
728}
729
730struct bridge_iflist *
731bridge_getbif(struct ifnet *ifp)
732{
733 struct bridge_iflist *bif;
734 struct bridge_softc *sc;
735 struct ifnet *bifp;
736
737 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 737, "_kernel_lock_held()"))
;
738
739 bifp = if_get(ifp->if_bridgeidx);
740 if (bifp == NULL((void *)0))
741 return (NULL((void *)0));
742
743 sc = bifp->if_softc;
744 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
745 if (bif->ifp == ifp)
746 break;
747 }
748
749 if_put(bifp);
750
751 return (bif);
752}
753
754void
755bridge_init(struct bridge_softc *sc)
756{
757 struct ifnet *ifp = &sc->sc_if;
758
759 if (ISSET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) & (0x40)))
760 return;
761
762 bstp_enable(sc->sc_stp, ifp->if_index);
763
764 if (sc->sc_brttimeout != 0)
765 timeout_add_sec(&sc->sc_brtimeout, sc->sc_brttimeout);
766
767 SET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) |= (0x40));
768}
769
770/*
771 * Stop the bridge and deallocate the routing table.
772 */
773void
774bridge_stop(struct bridge_softc *sc)
775{
776 struct ifnet *ifp = &sc->sc_if;
777
778 if (!ISSET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) & (0x40)))
779 return;
780
781 CLR(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) &= ~(0x40));
782
783 bstp_disable(sc->sc_stp);
784
785 timeout_del_barrier(&sc->sc_brtimeout);
786
787 bridge_rtflush(sc, IFBF_FLUSHDYN0x0);
788}
789
790/*
791 * Send output from the bridge. The mbuf has the ethernet header
792 * already attached. We must enqueue or free the mbuf before exiting.
793 */
794int
795bridge_enqueue(struct ifnet *ifp, struct mbuf *m)
796{
797 struct ifnet *brifp;
798 struct ether_header *eh;
799 struct ifnet *dst_if = NULL((void *)0);
800 unsigned int dst_ifidx = 0;
801#if NBPFILTER1 > 0
802 caddr_t if_bpf;
803#endif
804 int error = 0;
805
806 if (m->m_lenm_hdr.mh_len < sizeof(*eh)) {
807 m = m_pullup(m, sizeof(*eh));
808 if (m == NULL((void *)0))
809 return (ENOBUFS55);
810 }
811
812 /* ifp must be a member interface of the bridge. */
813 brifp = if_get(ifp->if_bridgeidx);
814 if (brifp == NULL((void *)0)) {
815 m_freem(m);
816 return (EINVAL22);
817 }
818
819 /*
820 * If bridge is down, but original output interface is up,
821 * go ahead and send out that interface. Otherwise the packet
822 * is dropped below.
823 */
824 if (!ISSET(brifp->if_flags, IFF_RUNNING)((brifp->if_flags) & (0x40))) {
825 /* Loop prevention. */
826 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
827 error = if_enqueue(ifp, m);
828 if_put(brifp);
829 return (error);
830 }
831
832#if NBPFILTER1 > 0
833 if_bpf = brifp->if_bpf;
834 if (if_bpf)
835 bpf_mtap(if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
836#endif
837 ifp->if_opacketsif_data.ifi_opackets++;
838 ifp->if_obytesif_data.ifi_obytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
839
840 bridge_span(brifp, m);
841
842 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
843 if (!ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
844 struct ether_addr *dst;
845
846 dst = (struct ether_addr *)&eh->ether_dhost[0];
847 dst_ifidx = bridge_rtlookup(brifp, dst, m);
848 }
849
850 /*
851 * If the packet is a broadcast or we don't know a better way to
852 * get there, send to all interfaces.
853 */
854 if (dst_ifidx == 0) {
855 struct bridge_softc *sc = brifp->if_softc;
856 struct bridge_iflist *bif;
857 struct mbuf *mc;
858
859 smr_read_enter();
860 SMR_SLIST_FOREACH(bif, &sc->sc_iflist, bif_next)for ((bif) = ({ typeof(*&(&sc->sc_iflist)->smr_slh_first
) __tmp = *(volatile typeof(*&(&sc->sc_iflist)->
smr_slh_first) *)&(*&(&sc->sc_iflist)->smr_slh_first
); membar_datadep_consumer(); __tmp; }); (bif) != ((void *)0)
; (bif) = ({ typeof(*&(bif)->bif_next.smr_sle_next) __tmp
= *(volatile typeof(*&(bif)->bif_next.smr_sle_next) *
)&(*&(bif)->bif_next.smr_sle_next); membar_datadep_consumer
(); __tmp; }))
{
861 dst_if = bif->ifp;
862 if ((dst_if->if_flags & IFF_RUNNING0x40) == 0)
863 continue;
864
865 /*
866 * If this is not the original output interface,
867 * and the interface is participating in spanning
868 * tree, make sure the port is in a state that
869 * allows forwarding.
870 */
871 if (dst_if != ifp &&
872 (bif->bif_flags & IFBIF_STP0x0008) &&
873 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
874 continue;
875 if ((bif->bif_flags & IFBIF_DISCOVER0x0002) == 0 &&
876 (m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) == 0)
877 continue;
878
879 if (bridge_filterrule(&bif->bif_brlout, eh, m) ==
880 BRL_ACTION_BLOCK0x01)
881 continue;
882
883 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
884 if (mc == NULL((void *)0)) {
885 brifp->if_oerrorsif_data.ifi_oerrors++;
886 continue;
887 }
888
889 error = bridge_ifenqueue(brifp, dst_if, mc);
890 if (error)
891 continue;
892 }
893 smr_read_leave();
894 m_freem(m);
895 goto out;
896 }
897
898 dst_if = if_get(dst_ifidx);
899 if ((dst_if == NULL((void *)0)) || !ISSET(dst_if->if_flags, IFF_RUNNING)((dst_if->if_flags) & (0x40))) {
900 m_freem(m);
901 if_put(dst_if);
902 error = ENETDOWN50;
903 goto out;
904 }
905
906 bridge_ifenqueue(brifp, dst_if, m);
907 if_put(dst_if);
908out:
909 if_put(brifp);
910 return (error);
911}
912
913/*
914 * Loop through each bridge interface and process their input queues.
915 */
916void
917bridgeintr(void)
918{
919 struct mbuf_list ml;
920 struct mbuf *m;
921 struct ifnet *ifp;
922
923 niq_delist(&bridgeintrq, &ml)mq_delist(&(&bridgeintrq)->ni_q, (&ml));
924 if (ml_empty(&ml)((&ml)->ml_len == 0))
925 return;
926
927 KERNEL_LOCK()_kernel_lock();
928 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
929
930 ifp = if_get(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx);
931 if (ifp == NULL((void *)0)) {
932 m_freem(m);
933 continue;
934 }
935
936 bridge_process(ifp, m);
937
938 if_put(ifp);
939 }
940 KERNEL_UNLOCK()_kernel_unlock();
941}
942
943/*
944 * Process a single frame. Frame must be freed or queued before returning.
945 */
946void
947bridgeintr_frame(struct ifnet *brifp, struct ifnet *src_if, struct mbuf *m)
948{
949 struct bridge_softc *sc = brifp->if_softc;
950 struct ifnet *dst_if = NULL((void *)0);
951 struct bridge_iflist *bif;
952 struct ether_addr *dst, *src;
953 struct ether_header eh;
954 unsigned int dst_ifidx;
955 u_int32_t protected;
956 int len;
957
958
959 sc->sc_if.if_ipacketsif_data.ifi_ipackets++;
960 sc->sc_if.if_ibytesif_data.ifi_ibytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
961
962 bif = bridge_getbif(src_if);
963 KASSERT(bif != NULL)((bif != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 963, "bif != NULL"))
;
964
965 m_copydata(m, 0, ETHER_HDR_LEN((6 * 2) + 2), &eh);
966 dst = (struct ether_addr *)&eh.ether_dhost[0];
967 src = (struct ether_addr *)&eh.ether_shost[0];
968
969 /*
970 * If interface is learning, and if source address
971 * is not broadcast or multicast, record its address.
972 */
973 if ((bif->bif_flags & IFBIF_LEARNING0x0001) &&
974 !ETHER_IS_MULTICAST(eh.ether_shost)(*(eh.ether_shost) & 0x01) &&
975 !ETHER_IS_ANYADDR(eh.ether_shost)(((eh.ether_shost)[0] | (eh.ether_shost)[1] | (eh.ether_shost
)[2] | (eh.ether_shost)[3] | (eh.ether_shost)[4] | (eh.ether_shost
)[5]) == 0x00)
)
976 bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC0x00, m);
977
978 if ((bif->bif_flags & IFBIF_STP0x0008) &&
979 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_LEARNING2)) {
980 m_freem(m);
981 return;
982 }
983
984 /*
985 * At this point, the port either doesn't participate in stp or
986 * it's in the forwarding state
987 */
988
989 /*
990 * If packet is unicast, destined for someone on "this"
991 * side of the bridge, drop it.
992 */
993 if (!ETHER_IS_MULTICAST(eh.ether_dhost)(*(eh.ether_dhost) & 0x01)) {
994 dst_ifidx = bridge_rtlookup(brifp, dst, NULL((void *)0));
995 if (dst_ifidx == src_if->if_index) {
996 m_freem(m);
997 return;
998 }
999 } else {
1000 if (ETHER_IS_BROADCAST(eh.ether_dhost)(((eh.ether_dhost)[0] & (eh.ether_dhost)[1] & (eh.ether_dhost
)[2] & (eh.ether_dhost)[3] & (eh.ether_dhost)[4] &
(eh.ether_dhost)[5]) == 0xff)
)
1001 m->m_flagsm_hdr.mh_flags |= M_BCAST0x0100;
1002 else
1003 m->m_flagsm_hdr.mh_flags |= M_MCAST0x0200;
1004 }
1005
1006 /*
1007 * Multicast packets get handled a little differently:
1008 * If interface is:
1009 * -link0,-link1 (default) Forward all multicast
1010 * as broadcast.
1011 * -link0,link1 Drop non-IP multicast, forward
1012 * as broadcast IP multicast.
1013 * link0,-link1 Drop IP multicast, forward as
1014 * broadcast non-IP multicast.
1015 * link0,link1 Drop all multicast.
1016 */
1017 if (m->m_flagsm_hdr.mh_flags & M_MCAST0x0200) {
1018 if ((sc->sc_if.if_flags &
1019 (IFF_LINK00x1000 | IFF_LINK10x2000)) ==
1020 (IFF_LINK00x1000 | IFF_LINK10x2000)) {
1021 m_freem(m);
1022 return;
1023 }
1024 if (sc->sc_if.if_flags & IFF_LINK00x1000 &&
1025 ETHERADDR_IS_IP_MCAST(dst)((dst)->ether_addr_octet[0] == 0x01 && (dst)->ether_addr_octet
[1] == 0x00 && (dst)->ether_addr_octet[2] == 0x5e)
) {
1026 m_freem(m);
1027 return;
1028 }
1029 if (sc->sc_if.if_flags & IFF_LINK10x2000 &&
1030 !ETHERADDR_IS_IP_MCAST(dst)((dst)->ether_addr_octet[0] == 0x01 && (dst)->ether_addr_octet
[1] == 0x00 && (dst)->ether_addr_octet[2] == 0x5e)
) {
1031 m_freem(m);
1032 return;
1033 }
1034 }
1035
1036 if (bif->bif_flags & IFBIF_BLOCKNONIP0x0004 && bridge_blocknonip(&eh, m)) {
1037 m_freem(m);
1038 return;
1039 }
1040
1041 if (bridge_filterrule(&bif->bif_brlin, &eh, m) == BRL_ACTION_BLOCK0x01) {
1042 m_freem(m);
1043 return;
1044 }
1045 m = bridge_ip(&sc->sc_if, BRIDGE_INPF_IN, src_if, &eh, m);
1046 if (m == NULL((void *)0))
1047 return;
1048 /*
1049 * If the packet is a multicast or broadcast OR if we don't
1050 * know any better, forward it to all interfaces.
1051 */
1052 if ((m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) || dst_ifidx == 0) {
1053 sc->sc_if.if_imcastsif_data.ifi_imcasts++;
1054 bridge_broadcast(sc, src_if, &eh, m);
1055 return;
1056 }
1057 protected = bif->bif_protected;
1058
1059 dst_if = if_get(dst_ifidx);
1060 if (dst_if == NULL((void *)0))
1061 goto bad;
1062
1063 /*
1064 * At this point, we're dealing with a unicast frame going to a
1065 * different interface
1066 */
1067 if (!ISSET(dst_if->if_flags, IFF_RUNNING)((dst_if->if_flags) & (0x40)))
1068 goto bad;
1069 bif = bridge_getbif(dst_if);
1070 if ((bif == NULL((void *)0)) || ((bif->bif_flags & IFBIF_STP0x0008) &&
1071 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5)))
1072 goto bad;
1073 /*
1074 * Do not transmit if both ports are part of the same protected
1075 * domain.
1076 */
1077 if (protected != 0 && (protected & bif->bif_protected))
1078 goto bad;
1079 if (bridge_filterrule(&bif->bif_brlout, &eh, m) == BRL_ACTION_BLOCK0x01)
1080 goto bad;
1081 m = bridge_ip(&sc->sc_if, BRIDGE_OUTPF_OUT, dst_if, &eh, m);
1082 if (m == NULL((void *)0))
1083 goto bad;
1084
1085 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1086#if NVLAN1 > 0
1087 if ((m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) &&
1088 (dst_if->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_HWTAGGING0x00000020) == 0)
1089 len += ETHER_VLAN_ENCAP_LEN4;
1090#endif
1091 if ((len - ETHER_HDR_LEN((6 * 2) + 2)) > dst_if->if_mtuif_data.ifi_mtu)
1092 bridge_fragment(&sc->sc_if, dst_if, &eh, m);
1093 else {
1094 bridge_ifenqueue(&sc->sc_if, dst_if, m);
1095 }
1096 m = NULL((void *)0);
1097bad:
1098 if_put(dst_if);
1099 m_freem(m);
1100}
1101
1102/*
1103 * Return 1 if `ena' belongs to `bif', 0 otherwise.
1104 */
1105int
1106bridge_ourether(struct ifnet *ifp, uint8_t *ena)
1107{
1108 struct arpcom *ac = (struct arpcom *)ifp;
1109
1110 if (memcmp(ac->ac_enaddr, ena, ETHER_ADDR_LEN)__builtin_memcmp((ac->ac_enaddr), (ena), (6)) == 0)
1111 return (1);
1112
1113#if NCARP1 > 0
1114 if (carp_ourether(ifp, ena))
1115 return (1);
1116#endif
1117
1118 return (0);
1119}
1120
1121/*
1122 * Receive input from an interface. Queue the packet for bridging if its
1123 * not for us, and schedule an interrupt.
1124 */
1125struct mbuf *
1126bridge_input(struct ifnet *ifp, struct mbuf *m, uint64_t dst, void *null)
1127{
1128 KASSERT(m->m_flags & M_PKTHDR)((m->m_hdr.mh_flags & 0x0002) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/if_bridge.c", 1128, "m->m_flags & M_PKTHDR"
))
;
1129
1130 if (m->m_flagsm_hdr.mh_flags & M_PROTO10x0010) {
1131 m->m_flagsm_hdr.mh_flags &= ~M_PROTO10x0010;
1132 return (m);
1133 }
1134
1135 niq_enqueue(&bridgeintrq, m);
1136
1137 return (NULL((void *)0));
1138}
1139
1140void
1141bridge_process(struct ifnet *ifp, struct mbuf *m)
1142{
1143 struct ifnet *brifp;
1144 struct bridge_softc *sc;
1145 struct bridge_iflist *bif = NULL((void *)0), *bif0 = NULL((void *)0);
1146 struct ether_header *eh;
1147 struct mbuf *mc;
1148#if NBPFILTER1 > 0
1149 caddr_t if_bpf;
1150#endif
1151
1152 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 1152, "_kernel_lock_held()"))
;
1153
1154 brifp = if_get(ifp->if_bridgeidx);
1155 if ((brifp == NULL((void *)0)) || !ISSET(brifp->if_flags, IFF_RUNNING)((brifp->if_flags) & (0x40)))
1156 goto reenqueue;
1157
1158 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < sizeof(*eh))
1159 goto bad;
1160
1161#if NVLAN1 > 0
1162 /*
1163 * If the underlying interface removed the VLAN header itself,
1164 * add it back.
1165 */
1166 if (ISSET(m->m_flags, M_VLANTAG)((m->m_hdr.mh_flags) & (0x0020))) {
1167 m = vlan_inject(m, ETHERTYPE_VLAN0x8100, m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag);
1168 if (m == NULL((void *)0))
1169 goto bad;
1170 }
1171#endif
1172
1173#if NBPFILTER1 > 0
1174 if_bpf = brifp->if_bpf;
1175 if (if_bpf)
1176 bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_IN(1 << 0));
1177#endif
1178
1179 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
1180
1181 sc = brifp->if_softc;
1182 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
1183 struct arpcom *ac = (struct arpcom *)bif->ifp;
1184 if (memcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN)__builtin_memcmp((ac->ac_enaddr), (eh->ether_shost), (6
))
== 0)
1185 goto bad;
1186 if (bif->ifp == ifp)
1187 bif0 = bif;
1188 }
1189 if (bif0 == NULL((void *)0))
1190 goto reenqueue;
1191
1192 bridge_span(brifp, m);
1193
1194 if (ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
1195 /*
1196 * Reserved destination MAC addresses (01:80:C2:00:00:0x)
1197 * should not be forwarded to bridge members according to
1198 * section 7.12.6 of the 802.1D-2004 specification. The
1199 * STP destination address (as stored in bstp_etheraddr)
1200 * is the first of these.
1201 */
1202 if (memcmp(eh->ether_dhost, bstp_etheraddr,__builtin_memcmp((eh->ether_dhost), (bstp_etheraddr), (6 -
1))
1203 ETHER_ADDR_LEN - 1)__builtin_memcmp((eh->ether_dhost), (bstp_etheraddr), (6 -
1))
== 0) {
1204 if (eh->ether_dhost[ETHER_ADDR_LEN6 - 1] == 0) {
1205 /* STP traffic */
1206 m = bstp_input(sc->sc_stp, bif0->bif_stp, eh,
1207 m);
1208 if (m == NULL((void *)0))
1209 goto bad;
1210 } else if (eh->ether_dhost[ETHER_ADDR_LEN6 - 1] <= 0xf)
1211 goto bad;
1212 }
1213
1214 /*
1215 * No need to process frames for ifs in the discarding state
1216 */
1217 if ((bif0->bif_flags & IFBIF_STP0x0008) &&
1218 (bif0->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
1219 goto reenqueue;
1220
1221 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1222 if (mc == NULL((void *)0))
1223 goto reenqueue;
1224
1225 bridge_ifinput(ifp, mc);
1226
1227 bridgeintr_frame(brifp, ifp, m);
1228 if_put(brifp);
1229 return;
1230 }
1231
1232 /*
1233 * Unicast, make sure it's not for us.
1234 */
1235 if (bridge_ourether(bif0->ifp, eh->ether_dhost)) {
1236 bif = bif0;
1237 } else {
1238 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
1239 if (bif->ifp == ifp)
1240 continue;
1241 if (bridge_ourether(bif->ifp, eh->ether_dhost))
1242 break;
1243 }
1244 }
1245 if (bif != NULL((void *)0)) {
1246 if (bif0->bif_flags & IFBIF_LEARNING0x0001)
1247 bridge_rtupdate(sc,
1248 (struct ether_addr *)&eh->ether_shost,
1249 ifp, 0, IFBAF_DYNAMIC0x00, m);
1250 if (bridge_filterrule(&bif0->bif_brlin, eh, m) ==
1251 BRL_ACTION_BLOCK0x01) {
1252 goto bad;
1253 }
1254
1255 /* Count for the bridge */
1256 brifp->if_ipacketsif_data.ifi_ipackets++;
1257 brifp->if_ibytesif_data.ifi_ibytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1258
1259 ifp = bif->ifp;
1260 goto reenqueue;
1261 }
1262
1263 bridgeintr_frame(brifp, ifp, m);
1264 if_put(brifp);
1265 return;
1266
1267reenqueue:
1268 bridge_ifinput(ifp, m);
1269 m = NULL((void *)0);
1270bad:
1271 m_freem(m);
1272 if_put(brifp);
1273}
1274
1275/*
1276 * Send a frame to all interfaces that are members of the bridge
1277 * (except the one it came in on).
1278 */
1279void
1280bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
1281 struct ether_header *eh, struct mbuf *m)
1282{
1283 struct bridge_iflist *bif;
1284 struct mbuf *mc;
1285 struct ifnet *dst_if;
1286 int len, used = 0;
1287 u_int32_t protected;
1288
1289 bif = bridge_getbif(ifp);
1290 KASSERT(bif != NULL)((bif != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 1290, "bif != NULL"))
;
1291 protected = bif->bif_protected;
1292
1293 SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_iflist, bif_next)for ((bif) = (*(&(&sc->sc_iflist)->smr_slh_first
)); (bif) != ((void *)0); (bif) = (*(&(bif)->bif_next.
smr_sle_next)))
{
1294 dst_if = bif->ifp;
1295
1296 if ((dst_if->if_flags & IFF_RUNNING0x40) == 0)
1297 continue;
1298
1299 if ((bif->bif_flags & IFBIF_STP0x0008) &&
1300 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
1301 continue;
1302
1303 if ((bif->bif_flags & IFBIF_DISCOVER0x0002) == 0 &&
1304 (m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) == 0)
1305 continue;
1306
1307 /* Drop non-IP frames if the appropriate flag is set. */
1308 if (bif->bif_flags & IFBIF_BLOCKNONIP0x0004 &&
1309 bridge_blocknonip(eh, m))
1310 continue;
1311
1312 /*
1313 * Do not transmit if both ports are part of the same
1314 * protected domain.
1315 */
1316 if (protected != 0 && (protected & bif->bif_protected))
1317 continue;
1318
1319 if (bridge_filterrule(&bif->bif_brlout, eh, m) ==
1320 BRL_ACTION_BLOCK0x01)
1321 continue;
1322
1323 /*
1324 * Don't retransmit out of the same interface where
1325 * the packet was received from.
1326 */
1327 if (dst_if->if_index == ifp->if_index)
1328 continue;
1329
1330 if (bridge_localbroadcast(dst_if, eh, m))
1331 sc->sc_if.if_oerrorsif_data.ifi_oerrors++;
1332
1333 /* If last one, reuse the passed-in mbuf */
1334 if (SMR_SLIST_NEXT_LOCKED(bif, bif_next)(*(&(bif)->bif_next.smr_sle_next)) == NULL((void *)0)) {
1335 mc = m;
1336 used = 1;
1337 } else {
1338 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1339 if (mc == NULL((void *)0)) {
1340 sc->sc_if.if_oerrorsif_data.ifi_oerrors++;
1341 continue;
1342 }
1343 }
1344
1345 mc = bridge_ip(&sc->sc_if, BRIDGE_OUTPF_OUT, dst_if, eh, mc);
1346 if (mc == NULL((void *)0))
1347 continue;
1348
1349 len = mc->m_pkthdrM_dat.MH.MH_pkthdr.len;
1350#if NVLAN1 > 0
1351 if ((mc->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) &&
1352 (dst_if->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_HWTAGGING0x00000020) == 0)
1353 len += ETHER_VLAN_ENCAP_LEN4;
1354#endif
1355 if ((len - ETHER_HDR_LEN((6 * 2) + 2)) > dst_if->if_mtuif_data.ifi_mtu)
1356 bridge_fragment(&sc->sc_if, dst_if, eh, mc);
1357 else {
1358 bridge_ifenqueue(&sc->sc_if, dst_if, mc);
1359 }
1360 }
1361
1362 if (!used)
1363 m_freem(m);
1364}
1365
1366int
1367bridge_localbroadcast(struct ifnet *ifp, struct ether_header *eh,
1368 struct mbuf *m)
1369{
1370 struct mbuf *m1;
1371 u_int16_t etype;
1372
1373 /*
1374 * quick optimisation, don't send packets up the stack if no
1375 * corresponding address has been specified.
1376 */
1377 etype = ntohs(eh->ether_type)(__uint16_t)(__builtin_constant_p(eh->ether_type) ? (__uint16_t
)(((__uint16_t)(eh->ether_type) & 0xffU) << 8 | (
(__uint16_t)(eh->ether_type) & 0xff00U) >> 8) : __swap16md
(eh->ether_type))
;
1378 if (!(m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) && etype == ETHERTYPE_IP0x0800) {
1379 struct ifaddr *ifa;
1380 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
1381 if (ifa->ifa_addr->sa_family == AF_INET2)
1382 break;
1383 }
1384 if (ifa == NULL((void *)0))
1385 return (0);
1386 }
1387
1388 m1 = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1389 if (m1 == NULL((void *)0))
1390 return (1);
1391
1392#if NPF1 > 0
1393 pf_pkt_addr_changed(m1);
1394#endif /* NPF */
1395
1396 bridge_ifinput(ifp, m1);
1397
1398 return (0);
1399}
1400
1401void
1402bridge_span(struct ifnet *brifp, struct mbuf *m)
1403{
1404 struct bridge_softc *sc = brifp->if_softc;
1405 struct bridge_iflist *bif;
1406 struct ifnet *ifp;
1407 struct mbuf *mc;
1408 int error;
1409
1410 smr_read_enter();
1411 SMR_SLIST_FOREACH(bif, &sc->sc_spanlist, bif_next)for ((bif) = ({ typeof(*&(&sc->sc_spanlist)->smr_slh_first
) __tmp = *(volatile typeof(*&(&sc->sc_spanlist)->
smr_slh_first) *)&(*&(&sc->sc_spanlist)->smr_slh_first
); membar_datadep_consumer(); __tmp; }); (bif) != ((void *)0)
; (bif) = ({ typeof(*&(bif)->bif_next.smr_sle_next) __tmp
= *(volatile typeof(*&(bif)->bif_next.smr_sle_next) *
)&(*&(bif)->bif_next.smr_sle_next); membar_datadep_consumer
(); __tmp; }))
{
1412 ifp = bif->ifp;
1413
1414 if ((ifp->if_flags & IFF_RUNNING0x40) == 0)
1415 continue;
1416
1417 mc = m_copym(m, 0, M_COPYALL1000000000, M_DONTWAIT0x0002);
1418 if (mc == NULL((void *)0)) {
1419 brifp->if_oerrorsif_data.ifi_oerrors++;
1420 continue;
1421 }
1422
1423 error = bridge_ifenqueue(brifp, ifp, mc);
1424 if (error)
1425 continue;
1426 }
1427 smr_read_leave();
1428}
1429
1430/*
1431 * Block non-ip frames:
1432 * Returns 0 if frame is ip, and 1 if it should be dropped.
1433 */
1434int
1435bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
1436{
1437 struct llc llc;
1438 u_int16_t etype;
1439
1440 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < ETHER_HDR_LEN((6 * 2) + 2))
1441 return (1);
1442
1443#if NVLAN1 > 0
1444 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1445 return (1);
1446#endif
1447
1448 etype = ntohs(eh->ether_type)(__uint16_t)(__builtin_constant_p(eh->ether_type) ? (__uint16_t
)(((__uint16_t)(eh->ether_type) & 0xffU) << 8 | (
(__uint16_t)(eh->ether_type) & 0xff00U) >> 8) : __swap16md
(eh->ether_type))
;
1449 switch (etype) {
1450 case ETHERTYPE_ARP0x0806:
1451 case ETHERTYPE_REVARP0x8035:
1452 case ETHERTYPE_IP0x0800:
1453 case ETHERTYPE_IPV60x86DD:
1454 return (0);
1455 }
1456
1457 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4))
1458 return (1);
1459
1460 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len <
1461 (ETHER_HDR_LEN((6 * 2) + 2) + LLC_SNAPFRAMELEN8))
1462 return (1);
1463
1464 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1465
1466 etype = ntohs(llc.llc_snap.ether_type)(__uint16_t)(__builtin_constant_p(llc.llc_un.type_snap.ether_type
) ? (__uint16_t)(((__uint16_t)(llc.llc_un.type_snap.ether_type
) & 0xffU) << 8 | ((__uint16_t)(llc.llc_un.type_snap
.ether_type) & 0xff00U) >> 8) : __swap16md(llc.llc_un
.type_snap.ether_type))
;
1467 if (llc.llc_dsap == LLC_SNAP_LSAP0xaa &&
1468 llc.llc_ssap == LLC_SNAP_LSAP0xaa &&
1469 llc.llc_controlllc_un.type_u.control == LLC_UI0x3 &&
1470 llc.llc_snapllc_un.type_snap.org_code[0] == 0 &&
1471 llc.llc_snapllc_un.type_snap.org_code[1] == 0 &&
1472 llc.llc_snapllc_un.type_snap.org_code[2] == 0 &&
1473 (etype == ETHERTYPE_ARP0x0806 || etype == ETHERTYPE_REVARP0x8035 ||
1474 etype == ETHERTYPE_IP0x0800 || etype == ETHERTYPE_IPV60x86DD)) {
1475 return (0);
1476 }
1477
1478 return (1);
1479}
1480
1481#ifdef IPSEC1
1482int
1483bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap,
1484 struct llc *llc, int dir, int af, int hlen, struct mbuf *m)
1485{
1486 union sockaddr_union dst;
1487 struct tdb *tdb;
1488 u_int32_t spi;
1489 u_int16_t cpi;
1490 int error, off, prot;
1491 u_int8_t proto = 0;
1492 struct ip *ip;
1493#ifdef INET61
1494 struct ip6_hdr *ip6;
1495#endif /* INET6 */
1496#if NPF1 > 0
1497 struct ifnet *encif;
1498#endif
1499
1500 if (dir == BRIDGE_INPF_IN) {
1501 switch (af) {
1502 case AF_INET2:
1503 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1504 goto skiplookup;
1505
1506 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1507 proto = ip->ip_p;
1508 off = offsetof(struct ip, ip_p)__builtin_offsetof(struct ip, ip_p);
1509
1510 if (proto != IPPROTO_ESP50 && proto != IPPROTO_AH51 &&
1511 proto != IPPROTO_IPCOMP108)
1512 goto skiplookup;
1513
1514 bzero(&dst, sizeof(union sockaddr_union))__builtin_bzero((&dst), (sizeof(union sockaddr_union)));
1515 dst.sa.sa_family = AF_INET2;
1516 dst.sin.sin_len = sizeof(struct sockaddr_in);
1517 m_copydata(m, offsetof(struct ip, ip_dst)__builtin_offsetof(struct ip, ip_dst),
1518 sizeof(struct in_addr), &dst.sin.sin_addr);
1519
1520 break;
1521#ifdef INET61
1522 case AF_INET624:
1523 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1524 goto skiplookup;
1525
1526 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1527
1528 /* XXX We should chase down the header chain */
1529 proto = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
1530 off = offsetof(struct ip6_hdr, ip6_nxt)__builtin_offsetof(struct ip6_hdr, ip6_ctlun.ip6_un1.ip6_un1_nxt
)
;
1531
1532 if (proto != IPPROTO_ESP50 && proto != IPPROTO_AH51 &&
1533 proto != IPPROTO_IPCOMP108)
1534 goto skiplookup;
1535
1536 bzero(&dst, sizeof(union sockaddr_union))__builtin_bzero((&dst), (sizeof(union sockaddr_union)));
1537 dst.sa.sa_family = AF_INET624;
1538 dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
1539 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst)__builtin_offsetof(struct ip6_hdr, ip6_dst),
1540 sizeof(struct in6_addr), &dst.sin6.sin6_addr);
1541
1542 break;
1543#endif /* INET6 */
1544 default:
1545 return (0);
1546 }
1547
1548 switch (proto) {
1549 case IPPROTO_ESP50:
1550 m_copydata(m, hlen, sizeof(u_int32_t), &spi);
1551 break;
1552 case IPPROTO_AH51:
1553 m_copydata(m, hlen + sizeof(u_int32_t),
1554 sizeof(u_int32_t), &spi);
1555 break;
1556 case IPPROTO_IPCOMP108:
1557 m_copydata(m, hlen + sizeof(u_int16_t),
1558 sizeof(u_int16_t), &cpi);
1559 spi = htonl(ntohs(cpi))(__uint32_t)(__builtin_constant_p((__uint16_t)(__builtin_constant_p
(cpi) ? (__uint16_t)(((__uint16_t)(cpi) & 0xffU) <<
8 | ((__uint16_t)(cpi) & 0xff00U) >> 8) : __swap16md
(cpi))) ? (__uint32_t)(((__uint32_t)((__uint16_t)(__builtin_constant_p
(cpi) ? (__uint16_t)(((__uint16_t)(cpi) & 0xffU) <<
8 | ((__uint16_t)(cpi) & 0xff00U) >> 8) : __swap16md
(cpi))) & 0xff) << 24 | ((__uint32_t)((__uint16_t)(
__builtin_constant_p(cpi) ? (__uint16_t)(((__uint16_t)(cpi) &
0xffU) << 8 | ((__uint16_t)(cpi) & 0xff00U) >>
8) : __swap16md(cpi))) & 0xff00) << 8 | ((__uint32_t
)((__uint16_t)(__builtin_constant_p(cpi) ? (__uint16_t)(((__uint16_t
)(cpi) & 0xffU) << 8 | ((__uint16_t)(cpi) & 0xff00U
) >> 8) : __swap16md(cpi))) & 0xff0000) >> 8 |
((__uint32_t)((__uint16_t)(__builtin_constant_p(cpi) ? (__uint16_t
)(((__uint16_t)(cpi) & 0xffU) << 8 | ((__uint16_t)(
cpi) & 0xff00U) >> 8) : __swap16md(cpi))) & 0xff000000
) >> 24) : __swap32md((__uint16_t)(__builtin_constant_p
(cpi) ? (__uint16_t)(((__uint16_t)(cpi) & 0xffU) <<
8 | ((__uint16_t)(cpi) & 0xff00U) >> 8) : __swap16md
(cpi))))
;
1560 break;
1561 }
1562
1563 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
1564
1565 tdb = gettdb(ifp->if_rdomain, spi, &dst, proto)gettdb_dir((ifp->if_data.ifi_rdomain),(spi),(&dst),(proto
),0)
;
1566 if (tdb != NULL((void *)0) && (tdb->tdb_flags & TDBF_INVALID0x00010) == 0 &&
1567 tdb->tdb_xform != NULL((void *)0)) {
1568 if (tdb->tdb_first_use == 0) {
1569 tdb->tdb_first_use = gettime();
1570 if (tdb->tdb_flags & TDBF_FIRSTUSE0x00020) {
1571 if (timeout_add_sec(
1572 &tdb->tdb_first_tmo,
1573 tdb->tdb_exp_first_use))
1574 tdb_ref(tdb);
1575 }
1576 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE0x00400) {
1577 if (timeout_add_sec(
1578 &tdb->tdb_sfirst_tmo,
1579 tdb->tdb_soft_first_use))
1580 tdb_ref(tdb);
1581 }
1582 }
1583
1584 prot = (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen,
1585 off);
1586 tdb_unref(tdb);
1587 if (prot != IPPROTO_DONE257)
1588 ip_deliver(&m, &hlen, prot, af);
1589 return (1);
1590 } else {
1591 tdb_unref(tdb);
1592 skiplookup:
1593 /* XXX do an input policy lookup */
1594 return (0);
1595 }
1596 } else { /* Outgoing from the bridge. */
1597 error = ipsp_spd_lookup(m, af, hlen, IPSP_DIRECTION_OUT0x2,
1598 NULL((void *)0), NULL((void *)0), &tdb, NULL((void *)0));
1599 if (error == 0 && tdb != NULL((void *)0)) {
1600 /*
1601 * We don't need to do loop detection, the
1602 * bridge will do that for us.
1603 */
1604#if NPF1 > 0
1605 if ((encif = enc_getif(tdb->tdb_rdomain,
1606 tdb->tdb_tap)) == NULL((void *)0) ||
1607 pf_test(af, dir, encif, &m) != PF_PASS) {
1608 m_freem(m);
1609 tdb_unref(tdb);
1610 return (1);
1611 }
1612 if (m == NULL((void *)0)) {
1613 tdb_unref(tdb);
1614 return (1);
1615 }
1616 if (af == AF_INET2)
1617 in_proto_cksum_out(m, encif);
1618#ifdef INET61
1619 else if (af == AF_INET624)
1620 in6_proto_cksum_out(m, encif);
1621#endif /* INET6 */
1622#endif /* NPF */
1623
1624 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1625 if ((af == AF_INET2) &&
1626 ip_mtudisc && (ip->ip_off & htons(IP_DF)(__uint16_t)(__builtin_constant_p(0x4000) ? (__uint16_t)(((__uint16_t
)(0x4000) & 0xffU) << 8 | ((__uint16_t)(0x4000) &
0xff00U) >> 8) : __swap16md(0x4000))
) &&
1627 tdb->tdb_mtu && ntohs(ip->ip_len)(__uint16_t)(__builtin_constant_p(ip->ip_len) ? (__uint16_t
)(((__uint16_t)(ip->ip_len) & 0xffU) << 8 | ((__uint16_t
)(ip->ip_len) & 0xff00U) >> 8) : __swap16md(ip->
ip_len))
> tdb->tdb_mtu &&
1628 tdb->tdb_mtutimeout > gettime()) {
1629 bridge_send_icmp_err(ifp, eh, m,
1630 hassnap, llc, tdb->tdb_mtu,
1631 ICMP_UNREACH3, ICMP_UNREACH_NEEDFRAG4);
1632 } else {
1633 KERNEL_LOCK()_kernel_lock();
1634 error = ipsp_process_packet(m, tdb, af, 0);
Value stored to 'error' is never read
1635 KERNEL_UNLOCK()_kernel_unlock();
1636 }
1637 tdb_unref(tdb);
1638 return (1);
1639 } else
1640 return (0);
1641 }
1642
1643 return (0);
1644}
1645#endif /* IPSEC */
1646
1647/*
1648 * Filter IP packets by peeking into the ethernet frame. This violates
1649 * the ISO model, but allows us to act as a IP filter at the data link
1650 * layer. As a result, most of this code will look familiar to those
1651 * who've read net/if_ethersubr.c and netinet/ip_input.c
1652 */
1653struct mbuf *
1654bridge_ip(struct ifnet *brifp, int dir, struct ifnet *ifp,
1655 struct ether_header *eh, struct mbuf *m)
1656{
1657 struct llc llc;
1658 int hassnap = 0;
1659 struct ip *ip;
1660 int hlen;
1661 u_int16_t etype;
1662
1663#if NVLAN1 > 0
1664 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1665 return (m);
1666#endif
1667
1668 etype = ntohs(eh->ether_type)(__uint16_t)(__builtin_constant_p(eh->ether_type) ? (__uint16_t
)(((__uint16_t)(eh->ether_type) & 0xffU) << 8 | (
(__uint16_t)(eh->ether_type) & 0xff00U) >> 8) : __swap16md
(eh->ether_type))
;
1669
1670 if (etype != ETHERTYPE_IP0x0800 && etype != ETHERTYPE_IPV60x86DD) {
1671 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4) ||
1672 m->m_pkthdrM_dat.MH.MH_pkthdr.len < (LLC_SNAPFRAMELEN8 +
1673 ETHER_HDR_LEN((6 * 2) + 2)))
1674 return (m);
1675
1676 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1677
1678 if (llc.llc_dsap != LLC_SNAP_LSAP0xaa ||
1679 llc.llc_ssap != LLC_SNAP_LSAP0xaa ||
1680 llc.llc_controlllc_un.type_u.control != LLC_UI0x3 ||
1681 llc.llc_snapllc_un.type_snap.org_code[0] ||
1682 llc.llc_snapllc_un.type_snap.org_code[1] ||
1683 llc.llc_snapllc_un.type_snap.org_code[2])
1684 return (m);
1685
1686 etype = ntohs(llc.llc_snap.ether_type)(__uint16_t)(__builtin_constant_p(llc.llc_un.type_snap.ether_type
) ? (__uint16_t)(((__uint16_t)(llc.llc_un.type_snap.ether_type
) & 0xffU) << 8 | ((__uint16_t)(llc.llc_un.type_snap
.ether_type) & 0xff00U) >> 8) : __swap16md(llc.llc_un
.type_snap.ether_type))
;
1687 if (etype != ETHERTYPE_IP0x0800 && etype != ETHERTYPE_IPV60x86DD)
1688 return (m);
1689 hassnap = 1;
1690 }
1691
1692 m_adj(m, ETHER_HDR_LEN((6 * 2) + 2));
1693 if (hassnap)
1694 m_adj(m, LLC_SNAPFRAMELEN8);
1695
1696 switch (etype) {
1697
1698 case ETHERTYPE_IP0x0800:
1699 m = ipv4_check(ifp, m);
1700 if (m == NULL((void *)0))
1701 return (NULL((void *)0));
1702
1703 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1704 hlen = ip->ip_hl << 2;
1705
1706#ifdef IPSEC1
1707 if ((brifp->if_flags & IFF_LINK20x4000) == IFF_LINK20x4000 &&
1708 bridge_ipsec(ifp, eh, hassnap, &llc, dir, AF_INET2, hlen, m))
1709 return (NULL((void *)0));
1710#endif /* IPSEC */
1711#if NPF1 > 0
1712 /* Finally, we get to filter the packet! */
1713 if (pf_test(AF_INET2, dir, ifp, &m) != PF_PASS)
1714 goto dropit;
1715 if (m == NULL((void *)0))
1716 goto dropit;
1717#endif /* NPF > 0 */
1718
1719 /* Rebuild the IP header */
1720 if (m->m_lenm_hdr.mh_len < hlen && ((m = m_pullup(m, hlen)) == NULL((void *)0)))
1721 return (NULL((void *)0));
1722 if (m->m_lenm_hdr.mh_len < sizeof(struct ip))
1723 goto dropit;
1724 in_proto_cksum_out(m, ifp);
1725 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1726 ip->ip_sum = 0;
1727 if (0 && (ifp->if_capabilitiesif_data.ifi_capabilities & IFCAP_CSUM_IPv40x00000001))
1728 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_IPV4_CSUM_OUT0x0001;
1729 else {
1730 ipstat_inc(ips_outswcsum);
1731 ip->ip_sum = in_cksum(m, hlen);
1732 }
1733
1734#if NPF1 > 0
1735 if (dir == BRIDGE_INPF_IN &&
1736 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_DIVERTED0x08) {
1737 m_resethdr(m);
1738 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
1739 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1740 ipv4_input(ifp, m);
1741 return (NULL((void *)0));
1742 }
1743#endif /* NPF > 0 */
1744
1745 break;
1746
1747#ifdef INET61
1748 case ETHERTYPE_IPV60x86DD:
1749 m = ipv6_check(ifp, m);
1750 if (m == NULL((void *)0))
1751 return (NULL((void *)0));
1752
1753#ifdef IPSEC1
1754 hlen = sizeof(struct ip6_hdr);
1755
1756 if ((brifp->if_flags & IFF_LINK20x4000) == IFF_LINK20x4000 &&
1757 bridge_ipsec(ifp, eh, hassnap, &llc, dir, AF_INET624, hlen,
1758 m))
1759 return (NULL((void *)0));
1760#endif /* IPSEC */
1761
1762#if NPF1 > 0
1763 if (pf_test(AF_INET624, dir, ifp, &m) != PF_PASS)
1764 goto dropit;
1765 if (m == NULL((void *)0))
1766 return (NULL((void *)0));
1767#endif /* NPF > 0 */
1768 in6_proto_cksum_out(m, ifp);
1769
1770#if NPF1 > 0
1771 if (dir == BRIDGE_INPF_IN &&
1772 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_DIVERTED0x08) {
1773 m_resethdr(m);
1774 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
1775 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1776 ipv6_input(ifp, m);
1777 return (NULL((void *)0));
1778 }
1779#endif /* NPF > 0 */
1780
1781 break;
1782#endif /* INET6 */
1783
1784 default:
1785 goto dropit;
1786 break;
1787 }
1788
1789 /* Reattach SNAP header */
1790 if (hassnap) {
1791 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1792 if (m == NULL((void *)0))
1793 goto dropit;
1794 bcopy(&llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
1795 }
1796
1797 /* Reattach ethernet header */
1798 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
1799 if (m == NULL((void *)0))
1800 goto dropit;
1801 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
1802
1803 return (m);
1804
1805dropit:
1806 m_freem(m);
1807 return (NULL((void *)0));
1808}
1809
1810void
1811bridge_fragment(struct ifnet *brifp, struct ifnet *ifp, struct ether_header *eh,
1812 struct mbuf *m)
1813{
1814 struct llc llc;
1815 struct mbuf_list fml;
1816 int error = 0;
1817 int hassnap = 0;
1818 u_int16_t etype;
1819 struct ip *ip;
1820
1821 etype = ntohs(eh->ether_type)(__uint16_t)(__builtin_constant_p(eh->ether_type) ? (__uint16_t
)(((__uint16_t)(eh->ether_type) & 0xffU) << 8 | (
(__uint16_t)(eh->ether_type) & 0xff00U) >> 8) : __swap16md
(eh->ether_type))
;
1822#if NVLAN1 > 0
1823 if ((m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) || etype == ETHERTYPE_VLAN0x8100 ||
1824 etype == ETHERTYPE_QINQ0x88A8) {
1825 int len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1826
1827 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1828 len += ETHER_VLAN_ENCAP_LEN4;
1829 if ((ifp->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_MTU0x00000010) &&
1830 (len - sizeof(struct ether_vlan_header) <= ifp->if_mtuif_data.ifi_mtu)) {
1831 bridge_ifenqueue(brifp, ifp, m);
1832 return;
1833 }
1834 goto dropit;
1835 }
1836#endif
1837 if (etype != ETHERTYPE_IP0x0800) {
1838 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4) ||
1839 m->m_pkthdrM_dat.MH.MH_pkthdr.len < (LLC_SNAPFRAMELEN8 +
1840 ETHER_HDR_LEN((6 * 2) + 2)))
1841 goto dropit;
1842
1843 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1844
1845 if (llc.llc_dsap != LLC_SNAP_LSAP0xaa ||
1846 llc.llc_ssap != LLC_SNAP_LSAP0xaa ||
1847 llc.llc_controlllc_un.type_u.control != LLC_UI0x3 ||
1848 llc.llc_snapllc_un.type_snap.org_code[0] ||
1849 llc.llc_snapllc_un.type_snap.org_code[1] ||
1850 llc.llc_snapllc_un.type_snap.org_code[2] ||
1851 llc.llc_snapllc_un.type_snap.ether_type != htons(ETHERTYPE_IP)(__uint16_t)(__builtin_constant_p(0x0800) ? (__uint16_t)(((__uint16_t
)(0x0800) & 0xffU) << 8 | ((__uint16_t)(0x0800) &
0xff00U) >> 8) : __swap16md(0x0800))
)
1852 goto dropit;
1853
1854 hassnap = 1;
1855 }
1856
1857 m_adj(m, ETHER_HDR_LEN((6 * 2) + 2));
1858 if (hassnap)
1859 m_adj(m, LLC_SNAPFRAMELEN8);
1860
1861 if (m->m_lenm_hdr.mh_len < sizeof(struct ip) &&
1862 (m = m_pullup(m, sizeof(struct ip))) == NULL((void *)0))
1863 goto dropit;
1864 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1865
1866 /* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
1867 if (ip->ip_off & htons(IP_DF)(__uint16_t)(__builtin_constant_p(0x4000) ? (__uint16_t)(((__uint16_t
)(0x4000) & 0xffU) << 8 | ((__uint16_t)(0x4000) &
0xff00U) >> 8) : __swap16md(0x4000))
) {
1868 bridge_send_icmp_err(ifp, eh, m, hassnap, &llc,
1869 ifp->if_mtuif_data.ifi_mtu, ICMP_UNREACH3, ICMP_UNREACH_NEEDFRAG4);
1870 return;
1871 }
1872
1873 error = ip_fragment(m, &fml, ifp, ifp->if_mtuif_data.ifi_mtu);
1874 if (error)
1875 return;
1876
1877 while ((m = ml_dequeue(&fml)) != NULL((void *)0)) {
1878 if (hassnap) {
1879 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1880 if (m == NULL((void *)0)) {
1881 error = ENOBUFS55;
1882 break;
1883 }
1884 bcopy(&llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
1885 }
1886 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
1887 if (m == NULL((void *)0)) {
1888 error = ENOBUFS55;
1889 break;
1890 }
1891 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
1892 error = bridge_ifenqueue(brifp, ifp, m);
1893 if (error)
1894 break;
1895 }
1896 if (error)
1897 ml_purge(&fml);
1898 else
1899 ipstat_inc(ips_fragmented);
1900
1901 return;
1902 dropit:
1903 m_freem(m);
1904}
1905
1906int
1907bridge_ifenqueue(struct ifnet *brifp, struct ifnet *ifp, struct mbuf *m)
1908{
1909 int error, len;
1910
1911 /* Loop prevention. */
1912 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
1913
1914 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1915
1916 error = if_enqueue(ifp, m);
1917 if (error) {
1918 brifp->if_oerrorsif_data.ifi_oerrors++;
1919 return (error);
1920 }
1921
1922 brifp->if_opacketsif_data.ifi_opackets++;
1923 brifp->if_obytesif_data.ifi_obytes += len;
1924
1925 return (0);
1926}
1927
1928void
1929bridge_ifinput(struct ifnet *ifp, struct mbuf *m)
1930{
1931 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1932
1933 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
1934
1935 ml_enqueue(&ml, m);
1936 if_input(ifp, &ml);
1937}
1938
1939void
1940bridge_send_icmp_err(struct ifnet *ifp,
1941 struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
1942 int mtu, int type, int code)
1943{
1944 struct ip *ip;
1945 struct icmp *icp;
1946 struct in_addr t;
1947 struct mbuf *m, *n2;
1948 int hlen;
1949 u_int8_t ether_tmp[ETHER_ADDR_LEN6];
1950
1951 n2 = m_copym(n, 0, M_COPYALL1000000000, M_DONTWAIT0x0002);
1952 if (!n2) {
1953 m_freem(n);
1954 return;
1955 }
1956 m = icmp_do_error(n, type, code, 0, mtu);
1957 if (m == NULL((void *)0)) {
1958 m_freem(n2);
1959 return;
1960 }
1961
1962 n = n2;
1963
1964 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1965 hlen = ip->ip_hl << 2;
1966 t = ip->ip_dst;
1967 ip->ip_dst = ip->ip_src;
1968 ip->ip_src = t;
1969
1970 m->m_datam_hdr.mh_data += hlen;
1971 m->m_lenm_hdr.mh_len -= hlen;
1972 icp = mtod(m, struct icmp *)((struct icmp *)((m)->m_hdr.mh_data));
1973 icp->icmp_cksum = 0;
1974 icp->icmp_cksum = in_cksum(m, ntohs(ip->ip_len)(__uint16_t)(__builtin_constant_p(ip->ip_len) ? (__uint16_t
)(((__uint16_t)(ip->ip_len) & 0xffU) << 8 | ((__uint16_t
)(ip->ip_len) & 0xff00U) >> 8) : __swap16md(ip->
ip_len))
- hlen);
1975 m->m_datam_hdr.mh_data -= hlen;
1976 m->m_lenm_hdr.mh_len += hlen;
1977
1978 ip->ip_v = IPVERSION4;
1979 ip->ip_off &= htons(IP_DF)(__uint16_t)(__builtin_constant_p(0x4000) ? (__uint16_t)(((__uint16_t
)(0x4000) & 0xffU) << 8 | ((__uint16_t)(0x4000) &
0xff00U) >> 8) : __swap16md(0x4000))
;
1980 ip->ip_id = htons(ip_randomid())(__uint16_t)(__builtin_constant_p(ip_randomid()) ? (__uint16_t
)(((__uint16_t)(ip_randomid()) & 0xffU) << 8 | ((__uint16_t
)(ip_randomid()) & 0xff00U) >> 8) : __swap16md(ip_randomid
()))
;
1981 ip->ip_ttl = MAXTTL255;
1982 ip->ip_sum = 0;
1983 ip->ip_sum = in_cksum(m, hlen);
1984
1985 /* Swap ethernet addresses */
1986 bcopy(&eh->ether_dhost, &ether_tmp, sizeof(ether_tmp));
1987 bcopy(&eh->ether_shost, &eh->ether_dhost, sizeof(ether_tmp));
1988 bcopy(&ether_tmp, &eh->ether_shost, sizeof(ether_tmp));
1989
1990 /* Reattach SNAP header */
1991 if (hassnap) {
1992 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1993 if (m == NULL((void *)0))
1994 goto dropit;
1995 bcopy(llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
1996 }
1997
1998 /* Reattach ethernet header */
1999 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
2000 if (m == NULL((void *)0))
2001 goto dropit;
2002 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
2003
2004 bridge_enqueue(ifp, m);
2005 m_freem(n);
2006 return;
2007
2008 dropit:
2009 m_freem(n);
2010}
2011
2012void
2013bridge_take(void *unused)
2014{
2015 return;
2016}
2017
2018void
2019bridge_rele(void *unused)
2020{
2021 return;
2022}