Bug Summary

File:net/if_bridge.c
Warning:line 1052, column 54
The left operand of '==' is a garbage value

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))
1
Assuming field 'ml_len' is not equal to 0
2
Taking false branch
925 return;
926
927 KERNEL_LOCK()_kernel_lock();
928 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
929
930 ifp = if_get(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx);
931 if (ifp == NULL((void *)0)) {
5
Assuming 'ifp' is not equal to NULL
6
Taking false branch
932 m_freem(m);
933 continue;
934 }
935
936 bridge_process(ifp, m);
7
Calling 'bridge_process'
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;
36
'dst_ifidx' declared without an initial value
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"))
;
37
Assuming 'bif' is not equal to null
38
'?' condition is true
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) &&
39
Assuming the condition is false
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) &&
40
Assuming the condition is false
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)) {
41
Assuming the condition is false
42
Taking false branch
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)
)
43
Assuming the condition is false
44
Taking false branch
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) {
45
Assuming the condition is false
46
Taking false branch
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)) {
47
Assuming the condition is false
1037 m_freem(m);
1038 return;
1039 }
1040
1041 if (bridge_filterrule(&bif->bif_brlin, &eh, m) == BRL_ACTION_BLOCK0x01) {
48
Assuming the condition is false
49
Taking false branch
1042 m_freem(m);
1043 return;
1044 }
1045 m = bridge_ip(&sc->sc_if, BRIDGE_INPF_IN, src_if, &eh, m);
1046 if (m
49.1
'm' is not equal to NULL
== NULL((void *)0))
50
Taking false branch
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) {
51
Assuming the condition is false
52
The left operand of '==' is a garbage value
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()"))
;
8
Assuming the condition is true
9
'?' condition is true
1153
1154 brifp = if_get(ifp->if_bridgeidx);
1155 if ((brifp == NULL((void *)0)) || !ISSET(brifp->if_flags, IFF_RUNNING)((brifp->if_flags) & (0x40)))
10
Assuming 'brifp' is not equal to NULL
11
Assuming the condition is false
12
Taking false branch
1156 goto reenqueue;
1157
1158 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < sizeof(*eh))
13
Assuming the condition is false
14
Taking false branch
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))) {
15
Assuming the condition is false
16
Taking false branch
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)
17
Assuming 'if_bpf' is null
18
Taking false branch
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)))
{
19
Assuming 'bif' is not equal to null
20
Loop condition is true. Entering loop body
25
Assuming 'bif' is equal to null
26
Loop condition is false. Execution continues on line 1189
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
)
21
Assuming the condition is false
22
Taking false branch
1185 goto bad;
1186 if (bif->ifp == ifp)
23
Assuming 'ifp' is equal to field 'ifp'
24
Taking true branch
1187 bif0 = bif;
1188 }
1189 if (bif0
26.1
'bif0' is not equal to NULL
== NULL((void *)0))
27
Taking false branch
1190 goto reenqueue;
1191
1192 bridge_span(brifp, m);
1193
1194 if (ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
28
Assuming the condition is true
29
Taking true branch
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))
30
Assuming the condition is false
31
Taking false branch
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) &&
32
Assuming the condition is false
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))
33
Assuming 'mc' is not equal to NULL
34
Taking false branch
1223 goto reenqueue;
1224
1225 bridge_ifinput(ifp, mc);
1226
1227 bridgeintr_frame(brifp, ifp, m);
35
Calling 'bridgeintr_frame'
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);
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}