Bug Summary

File:net/if_bridge.c
Warning:line 1066, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name if_bridge.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/net/if_bridge.c
1/* $OpenBSD: if_bridge.c,v 1.368 2023/05/16 14:32:54 jan 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), ((((0x4)) > 0x0 && ((0x4)) <
0x9) ? 0x9 : ((0x4))), 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. Media ioctl run without netlock.
266 */
267 switch (cmd) {
268 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
269 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
270 return (ENOTTY25);
271 }
272 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
273
274 switch (cmd) {
275 case SIOCBRDGADD((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((60)))
:
276 /* bridge(4) does not distinguish between routing/forwarding ports */
277 case SIOCBRDGADDL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((73)))
:
278 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)
279 break;
280
281 ifs = if_unit(req->ifbr_ifsname);
282 if (ifs == NULL((void *)0)) { /* no such interface */
283 error = ENOENT2;
284 break;
285 }
286 if (ifs->if_typeif_data.ifi_type != IFT_ETHER0x06) {
287 if_put(ifs);
288 error = EINVAL22;
289 break;
290 }
291 if (ifs->if_bridgeidx != 0) {
292 if (ifs->if_bridgeidx == ifp->if_index)
293 error = EEXIST17;
294 else
295 error = EBUSY16;
296 if_put(ifs);
297 break;
298 }
299
300 error = ether_brport_isset(ifs);
301 if (error != 0) {
302 if_put(ifs);
303 break;
304 }
305
306 /* If it's in the span list, it can't be a member. */
307 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)))
{
308 if (bif->ifp == ifs)
309 break;
310 }
311 if (bif != NULL((void *)0)) {
312 if_put(ifs);
313 error = EBUSY16;
314 break;
315 }
316
317 bif = malloc(sizeof(*bif), M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
318 if (bif == NULL((void *)0)) {
319 if_put(ifs);
320 error = ENOMEM12;
321 break;
322 }
323
324 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
325 error = ifpromisc(ifs, 1);
326 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
327 if (error != 0) {
328 if_put(ifs);
329 free(bif, M_DEVBUF2, sizeof(*bif));
330 break;
331 }
332
333 /*
334 * XXX If the NET_LOCK() or ifpromisc() calls above
335 * had to sleep, then something else could have come
336 * along and taken over ifs while the kernel lock was
337 * released.
338 */
339
340 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
341 ifsetlro(ifs, 0);
342 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
343
344 bif->bridge_sc = sc;
345 bif->ifp = ifs;
346 bif->bif_flags = IFBIF_LEARNING0x0001 | IFBIF_DISCOVER0x0002;
347 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)
;
348 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)
;
349 ifs->if_bridgeidx = ifp->if_index;
350 task_set(&bif->bif_dtask, bridge_ifdetach, bif);
351 if_detachhook_add(ifs, &bif->bif_dtask);
352 ether_brport_set(bif->ifp, &bridge_brport);
353 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)
;
354 break;
355 case SIOCBRDGDEL((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((61)))
:
356 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)
357 break;
358 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
359 if (error != 0)
360 break;
361 bridge_ifremove(bif);
362 break;
363 case SIOCBRDGIFS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((66)))
:
364 error = bridge_bifconf(sc, (struct ifbifconf *)data);
365 break;
366 case SIOCBRDGADDS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((65)))
:
367 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)
368 break;
369 ifs = if_unit(req->ifbr_ifsname);
370 if (ifs == NULL((void *)0)) { /* no such interface */
371 error = ENOENT2;
372 break;
373 }
374 if (ifs->if_typeif_data.ifi_type != IFT_ETHER0x06) {
375 if_put(ifs);
376 error = EINVAL22;
377 break;
378 }
379 if (ifs->if_bridgeidx != 0) {
380 if (ifs->if_bridgeidx == ifp->if_index)
381 error = EEXIST17;
382 else
383 error = EBUSY16;
384 if_put(ifs);
385 break;
386 }
387 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)))
{
388 if (bif->ifp == ifs)
389 break;
390 }
391 if (bif != NULL((void *)0)) {
392 if_put(ifs);
393 error = EEXIST17;
394 break;
395 }
396 bif = malloc(sizeof(*bif), M_DEVBUF2, M_NOWAIT0x0002|M_ZERO0x0008);
397 if (bif == NULL((void *)0)) {
398 if_put(ifs);
399 error = ENOMEM12;
400 break;
401 }
402
403 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
404 ifsetlro(ifs, 0);
405 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
406
407 bif->bridge_sc = sc;
408 bif->ifp = ifs;
409 bif->bif_flags = IFBIF_SPAN0x0100;
410 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)
;
411 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)
;
412 task_set(&bif->bif_dtask, bridge_spandetach, bif);
413 if_detachhook_add(ifs, &bif->bif_dtask);
414 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)
;
415 break;
416 case SIOCBRDGDELS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((66)))
:
417 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)
418 break;
419 ifs = if_unit(req->ifbr_ifsname);
420 if (ifs == NULL((void *)0)) {
421 error = ENOENT2;
422 break;
423 }
424 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)))
{
425 if (bif->ifp == ifs)
426 break;
427 }
428 if_put(ifs);
429 if (bif == NULL((void *)0)) {
430 error = ESRCH3;
431 break;
432 }
433 bridge_spanremove(bif);
434 break;
435 case SIOCBRDGGIFFLGS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((62)))
:
436 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
437 if (error != 0)
438 break;
439 req->ifbr_ifsflags = bif->bif_flags;
440 req->ifbr_portno = bif->ifp->if_index & 0xfff;
441 req->ifbr_protected = bif->bif_protected;
442 if (bif->bif_flags & IFBIF_STP0x0008)
443 bridge_bifgetstp(sc, bif, req);
444 break;
445 case SIOCBRDGSIFFLGS((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((63)))
:
446 if (req->ifbr_ifsflags & IFBIF_RO_MASK0x0f00) {
447 error = EINVAL22;
448 break;
449 }
450 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)
451 break;
452 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
453 if (error != 0)
454 break;
455 if (req->ifbr_ifsflags & IFBIF_STP0x0008) {
456 if ((bif->bif_flags & IFBIF_STP0x0008) == 0) {
457 /* Enable STP */
458 if ((bif->bif_stp = bstp_add(sc->sc_stp,
459 bif->ifp)) == NULL((void *)0)) {
460 error = ENOMEM12;
461 break;
462 }
463 } else {
464 /* Update STP flags */
465 bstp_ifsflags(bif->bif_stp, req->ifbr_ifsflags);
466 }
467 } else if (bif->bif_flags & IFBIF_STP0x0008) {
468 bstp_delete(bif->bif_stp);
469 bif->bif_stp = NULL((void *)0);
470 }
471 bif->bif_flags = req->ifbr_ifsflags;
472 break;
473 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
474 if ((ifp->if_flags & IFF_UP0x1) == IFF_UP0x1)
475 bridge_init(sc);
476
477 if ((ifp->if_flags & IFF_UP0x1) == 0)
478 bridge_stop(sc);
479
480 break;
481 case SIOCBRDGGPARAM(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbropreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((88)))
:
482 if ((bp = bs->bs_root_port) == NULL((void *)0))
483 brop->ifbop_root_port = 0;
484 else
485 brop->ifbop_root_port = bp->bp_ifindex;
486 brop->ifbop_maxage = bs->bs_bridge_max_age >> 8;
487 brop->ifbop_hellotime = bs->bs_bridge_htime >> 8;
488 brop->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8;
489 brop->ifbop_holdcount = bs->bs_txholdcount;
490 brop->ifbop_priority = bs->bs_bridge_priority;
491 brop->ifbop_protocol = bs->bs_protover;
492 brop->ifbop_root_bridge = bs->bs_root_pv.pv_root_id;
493 brop->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
494 brop->ifbop_root_port = bs->bs_root_pv.pv_port_id;
495 brop->ifbop_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
496 brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
497 brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
498 break;
499 case SIOCBRDGSIFPROT((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((74)))
:
500 error = bridge_findbif(sc, req->ifbr_ifsname, &bif);
501 if (error != 0)
502 break;
503 bif->bif_protected = req->ifbr_protected;
504 break;
505 case SIOCBRDGRTS(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbaconf) & 0x1fff) << 16) | ((('i')) <<
8) | ((67)))
:
506 case SIOCBRDGGCACHE(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((65)))
:
507 case SIOCBRDGGPRI(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((80)))
:
508 case SIOCBRDGGMA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((83)))
:
509 case SIOCBRDGGHT(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((81)))
:
510 case SIOCBRDGGFD(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((82)))
:
511 case SIOCBRDGGTO(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrparam) & 0x1fff) << 16) | ((('i')) <<
8) | ((70)))
:
512 case SIOCBRDGGRL(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbrlconf) & 0x1fff) << 16) | ((('i')) <<
8) | ((79)))
:
513 break;
514 case SIOCBRDGFLUSH((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((72)))
:
515 case SIOCBRDGSADDR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifbareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((68)))
:
516 case SIOCBRDGDADDR((unsigned long)0x80000000 | ((sizeof(struct ifbareq) & 0x1fff
) << 16) | ((('i')) << 8) | ((71)))
:
517 case SIOCBRDGSCACHE((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((64)))
:
518 case SIOCBRDGSTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((69)))
:
519 case SIOCBRDGARL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((77)))
:
520 case SIOCBRDGFRL((unsigned long)0x80000000 | ((sizeof(struct ifbrlreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((78)))
:
521 case SIOCBRDGSPRI((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((80)))
:
522 case SIOCBRDGSFD((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((82)))
:
523 case SIOCBRDGSMA((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((83)))
:
524 case SIOCBRDGSHT((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((81)))
:
525 case SIOCBRDGSTXHC((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((89)))
:
526 case SIOCBRDGSPROTO((unsigned long)0x80000000 | ((sizeof(struct ifbrparam) &
0x1fff) << 16) | ((('i')) << 8) | ((90)))
:
527 case SIOCBRDGSIFPRIO((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((84)))
:
528 case SIOCBRDGSIFCOST((unsigned long)0x80000000 | ((sizeof(struct ifbreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((85)))
:
529 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
);
530 break;
531 default:
532 error = ENOTTY25;
533 break;
534 }
535
536 if (!error)
537 error = bridgectl_ioctl(ifp, cmd, data);
538
539 if (!error)
540 error = bstp_ioctl(ifp, cmd, data);
541
542 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
543 return (error);
544}
545
546/* Detach an interface from a bridge. */
547int
548bridge_ifremove(struct bridge_iflist *bif)
549{
550 struct bridge_softc *sc = bif->bridge_sc;
551 int error;
552
553 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)
;
554 if_detachhook_del(bif->ifp, &bif->bif_dtask);
555 ether_brport_clr(bif->ifp);
556
557 smr_barrier()smr_barrier_impl(0);
558
559 if (bif->bif_flags & IFBIF_STP0x0008) {
560 bstp_delete(bif->bif_stp);
561 bif->bif_stp = NULL((void *)0);
562 }
563
564 bif->ifp->if_bridgeidx = 0;
565 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
566 error = ifpromisc(bif->ifp, 0);
567 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
568
569 bridge_rtdelete(sc, bif->ifp, 0);
570 bridge_flushrule(bif);
571
572 if_put(bif->ifp);
573 bif->ifp = NULL((void *)0);
574 free(bif, M_DEVBUF2, sizeof(*bif));
575
576 return (error);
577}
578
579void
580bridge_spanremove(struct bridge_iflist *bif)
581{
582 struct bridge_softc *sc = bif->bridge_sc;
583
584 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)
;
585 if_detachhook_del(bif->ifp, &bif->bif_dtask);
586
587 smr_barrier()smr_barrier_impl(0);
588
589 if_put(bif->ifp);
590 bif->ifp = NULL((void *)0);
591 free(bif, M_DEVBUF2, sizeof(*bif));
592}
593
594void
595bridge_ifdetach(void *xbif)
596{
597 struct bridge_iflist *bif = xbif;
598
599 /*
600 * bridge(4) detach hook doesn't need the NET_LOCK(), worst the
601 * use of smr_barrier() while holding the lock might lead to a
602 * deadlock situation.
603 */
604 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
605 bridge_ifremove(bif);
606 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
607}
608
609void
610bridge_spandetach(void *xbif)
611{
612 struct bridge_iflist *bif = xbif;
613
614 /*
615 * bridge(4) detach hook doesn't need the NET_LOCK(), worst the
616 * use of smr_barrier() while holding the lock might lead to a
617 * deadlock situation.
618 */
619 NET_UNLOCK()do { rw_exit_write(&netlock); } while (0);
620 bridge_spanremove(bif);
621 NET_LOCK()do { rw_enter_write(&netlock); } while (0);
622}
623
624void
625bridge_bifgetstp(struct bridge_softc *sc, struct bridge_iflist *bif,
626 struct ifbreq *breq)
627{
628 struct bstp_state *bs = sc->sc_stp;
629 struct bstp_port *bp = bif->bif_stp;
630
631 breq->ifbr_state = bstp_getstate(bs, bp);
632 breq->ifbr_priority = bp->bp_priority;
633 breq->ifbr_path_cost = bp->bp_path_cost;
634 breq->ifbr_proto = bp->bp_protover;
635 breq->ifbr_role = bp->bp_role;
636 breq->ifbr_stpflags = bp->bp_flags;
637 breq->ifbr_fwd_trans = bp->bp_forward_transitions;
638 breq->ifbr_root_bridge = bs->bs_root_pv.pv_root_id;
639 breq->ifbr_root_cost = bs->bs_root_pv.pv_cost;
640 breq->ifbr_root_port = bs->bs_root_pv.pv_port_id;
641 breq->ifbr_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
642 breq->ifbr_desg_port = bs->bs_root_pv.pv_dport_id;
643
644 /* Copy STP state options as flags */
645 if (bp->bp_operedge)
646 breq->ifbr_ifsflags |= IFBIF_BSTP_EDGE0x0010;
647 if (bp->bp_flags & BSTP_PORT_AUTOEDGE0x0010)
648 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE0x0020;
649 if (bp->bp_ptp_link)
650 breq->ifbr_ifsflags |= IFBIF_BSTP_PTP0x0040;
651 if (bp->bp_flags & BSTP_PORT_AUTOPTP0x0020)
652 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP0x0080;
653}
654
655int
656bridge_bifconf(struct bridge_softc *sc, struct ifbifconf *bifc)
657{
658 struct bridge_iflist *bif;
659 u_int32_t total = 0, i = 0;
660 int error = 0;
661 struct ifbreq *breq, *breqs = NULL((void *)0);
662
663 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)))
664 total++;
665
666 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)))
667 total++;
668
669 if (bifc->ifbic_len == 0) {
670 i = total;
671 goto done;
672 }
673
674 breqs = mallocarray(total, sizeof(*breqs), M_TEMP127, M_NOWAIT0x0002|M_ZERO0x0008);
675 if (breqs == NULL((void *)0))
676 goto done;
677
678 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)))
{
679 if (bifc->ifbic_len < (i + 1) * sizeof(*breqs))
680 break;
681 breq = &breqs[i];
682 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ16);
683 strlcpy(breq->ifbr_ifsname, bif->ifp->if_xname, IFNAMSIZ16);
684 breq->ifbr_ifsflags = bif->bif_flags;
685 breq->ifbr_portno = bif->ifp->if_index & 0xfff;
686 breq->ifbr_protected = bif->bif_protected;
687 if (bif->bif_flags & IFBIF_STP0x0008)
688 bridge_bifgetstp(sc, bif, breq);
689 i++;
690 }
691 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)))
{
692 if (bifc->ifbic_len < (i + 1) * sizeof(*breqs))
693 break;
694 breq = &breqs[i];
695 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ16);
696 strlcpy(breq->ifbr_ifsname, bif->ifp->if_xname, IFNAMSIZ16);
697 breq->ifbr_ifsflags = bif->bif_flags | IFBIF_SPAN0x0100;
698 breq->ifbr_portno = bif->ifp->if_index & 0xfff;
699 i++;
700 }
701
702 error = copyout(breqs, bifc->ifbic_reqifbic_ifbicu.ifbicu_req, i * sizeof(*breqs));
703done:
704 free(breqs, M_TEMP127, total * sizeof(*breq));
705 bifc->ifbic_len = i * sizeof(*breq);
706 return (error);
707}
708
709int
710bridge_findbif(struct bridge_softc *sc, const char *name,
711 struct bridge_iflist **rbif)
712{
713 struct ifnet *ifp;
714 struct bridge_iflist *bif;
715 int error = 0;
716
717 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 717, "_kernel_lock_held()"))
;
718
719 if ((ifp = if_unit(name)) == NULL((void *)0))
720 return (ENOENT2);
721
722 if (ifp->if_bridgeidx != sc->sc_if.if_index) {
723 error = ESRCH3;
724 goto put;
725 }
726
727 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)))
{
728 if (bif->ifp == ifp)
729 break;
730 }
731
732 if (bif == NULL((void *)0)) {
733 error = ENOENT2;
734 goto put;
735 }
736
737 *rbif = bif;
738put:
739 if_put(ifp);
740
741 return (error);
742}
743
744struct bridge_iflist *
745bridge_getbif(struct ifnet *ifp)
746{
747 struct bridge_iflist *bif;
748 struct bridge_softc *sc;
749 struct ifnet *bifp;
750
751 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 751, "_kernel_lock_held()"))
;
752
753 bifp = if_get(ifp->if_bridgeidx);
754 if (bifp == NULL((void *)0))
755 return (NULL((void *)0));
756
757 sc = bifp->if_softc;
758 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)))
{
759 if (bif->ifp == ifp)
760 break;
761 }
762
763 if_put(bifp);
764
765 return (bif);
766}
767
768void
769bridge_init(struct bridge_softc *sc)
770{
771 struct ifnet *ifp = &sc->sc_if;
772
773 if (ISSET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) & (0x40)))
774 return;
775
776 bstp_enable(sc->sc_stp, ifp->if_index);
777
778 if (sc->sc_brttimeout != 0)
779 timeout_add_sec(&sc->sc_brtimeout, sc->sc_brttimeout);
780
781 SET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) |= (0x40));
782}
783
784/*
785 * Stop the bridge and deallocate the routing table.
786 */
787void
788bridge_stop(struct bridge_softc *sc)
789{
790 struct ifnet *ifp = &sc->sc_if;
791
792 if (!ISSET(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) & (0x40)))
793 return;
794
795 CLR(ifp->if_flags, IFF_RUNNING)((ifp->if_flags) &= ~(0x40));
796
797 bstp_disable(sc->sc_stp);
798
799 timeout_del_barrier(&sc->sc_brtimeout);
800
801 bridge_rtflush(sc, IFBF_FLUSHDYN0x0);
802}
803
804/*
805 * Send output from the bridge. The mbuf has the ethernet header
806 * already attached. We must enqueue or free the mbuf before exiting.
807 */
808int
809bridge_enqueue(struct ifnet *ifp, struct mbuf *m)
810{
811 struct ifnet *brifp;
812 struct ether_header *eh;
813 struct ifnet *dst_if = NULL((void *)0);
814 unsigned int dst_ifidx = 0;
815#if NBPFILTER1 > 0
816 caddr_t if_bpf;
817#endif
818 int error = 0;
819
820 if (m->m_lenm_hdr.mh_len < sizeof(*eh)) {
821 m = m_pullup(m, sizeof(*eh));
822 if (m == NULL((void *)0))
823 return (ENOBUFS55);
824 }
825
826 /* ifp must be a member interface of the bridge. */
827 brifp = if_get(ifp->if_bridgeidx);
828 if (brifp == NULL((void *)0)) {
829 m_freem(m);
830 return (EINVAL22);
831 }
832
833 /*
834 * If bridge is down, but original output interface is up,
835 * go ahead and send out that interface. Otherwise the packet
836 * is dropped below.
837 */
838 if (!ISSET(brifp->if_flags, IFF_RUNNING)((brifp->if_flags) & (0x40))) {
839 /* Loop prevention. */
840 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
841 error = if_enqueue(ifp, m);
842 if_put(brifp);
843 return (error);
844 }
845
846#if NBPFILTER1 > 0
847 if_bpf = brifp->if_bpf;
848 if (if_bpf)
849 bpf_mtap(if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
850#endif
851 ifp->if_opacketsif_data.ifi_opackets++;
852 ifp->if_obytesif_data.ifi_obytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
853
854 bridge_span(brifp, m);
855
856 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
857 if (!ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
858 struct ether_addr *dst;
859
860 dst = (struct ether_addr *)&eh->ether_dhost[0];
861 dst_ifidx = bridge_rtlookup(brifp, dst, m);
862 }
863
864 /*
865 * If the packet is a broadcast or we don't know a better way to
866 * get there, send to all interfaces.
867 */
868 if (dst_ifidx == 0) {
869 struct bridge_softc *sc = brifp->if_softc;
870 struct bridge_iflist *bif;
871 struct mbuf *mc;
872
873 smr_read_enter();
874 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; }))
{
875 dst_if = bif->ifp;
876 if ((dst_if->if_flags & IFF_RUNNING0x40) == 0)
877 continue;
878
879 /*
880 * If this is not the original output interface,
881 * and the interface is participating in spanning
882 * tree, make sure the port is in a state that
883 * allows forwarding.
884 */
885 if (dst_if != ifp &&
886 (bif->bif_flags & IFBIF_STP0x0008) &&
887 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
888 continue;
889 if ((bif->bif_flags & IFBIF_DISCOVER0x0002) == 0 &&
890 (m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) == 0)
891 continue;
892
893 if (bridge_filterrule(&bif->bif_brlout, eh, m) ==
894 BRL_ACTION_BLOCK0x01)
895 continue;
896
897 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
898 if (mc == NULL((void *)0)) {
899 brifp->if_oerrorsif_data.ifi_oerrors++;
900 continue;
901 }
902
903 error = bridge_ifenqueue(brifp, dst_if, mc);
904 if (error)
905 continue;
906 }
907 smr_read_leave();
908 m_freem(m);
909 goto out;
910 }
911
912 dst_if = if_get(dst_ifidx);
913 if ((dst_if == NULL((void *)0)) || !ISSET(dst_if->if_flags, IFF_RUNNING)((dst_if->if_flags) & (0x40))) {
914 m_freem(m);
915 if_put(dst_if);
916 error = ENETDOWN50;
917 goto out;
918 }
919
920 bridge_ifenqueue(brifp, dst_if, m);
921 if_put(dst_if);
922out:
923 if_put(brifp);
924 return (error);
925}
926
927/*
928 * Loop through each bridge interface and process their input queues.
929 */
930void
931bridgeintr(void)
932{
933 struct mbuf_list ml;
934 struct mbuf *m;
935 struct ifnet *ifp;
936
937 niq_delist(&bridgeintrq, &ml)mq_delist(&(&bridgeintrq)->ni_q, (&ml));
938 if (ml_empty(&ml)((&ml)->ml_len == 0))
1
Assuming field 'ml_len' is not equal to 0
2
Taking false branch
939 return;
940
941 KERNEL_LOCK()_kernel_lock();
942 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
943
944 ifp = if_get(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx);
945 if (ifp == NULL((void *)0)) {
5
Assuming 'ifp' is not equal to NULL
6
Taking false branch
946 m_freem(m);
947 continue;
948 }
949
950 bridge_process(ifp, m);
7
Calling 'bridge_process'
951
952 if_put(ifp);
953 }
954 KERNEL_UNLOCK()_kernel_unlock();
955}
956
957/*
958 * Process a single frame. Frame must be freed or queued before returning.
959 */
960void
961bridgeintr_frame(struct ifnet *brifp, struct ifnet *src_if, struct mbuf *m)
962{
963 struct bridge_softc *sc = brifp->if_softc;
964 struct ifnet *dst_if = NULL((void *)0);
965 struct bridge_iflist *bif;
966 struct ether_addr *dst, *src;
967 struct ether_header eh;
968 unsigned int dst_ifidx;
35
'dst_ifidx' declared without an initial value
969 u_int32_t protected;
970 int len;
971
972
973 sc->sc_if.if_ipacketsif_data.ifi_ipackets++;
974 sc->sc_if.if_ibytesif_data.ifi_ibytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
975
976 bif = bridge_getbif(src_if);
977 KASSERT(bif != NULL)((bif != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 977, "bif != NULL"))
;
36
Assuming 'bif' is not equal to null
37
'?' condition is true
978
979 m_copydata(m, 0, ETHER_HDR_LEN((6 * 2) + 2), &eh);
980 dst = (struct ether_addr *)&eh.ether_dhost[0];
981 src = (struct ether_addr *)&eh.ether_shost[0];
982
983 /*
984 * If interface is learning, and if source address
985 * is not broadcast or multicast, record its address.
986 */
987 if ((bif->bif_flags & IFBIF_LEARNING0x0001) &&
38
Assuming the condition is false
988 !ETHER_IS_MULTICAST(eh.ether_shost)(*(eh.ether_shost) & 0x01) &&
989 !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)
)
990 bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC0x00, m);
991
992 if ((bif->bif_flags & IFBIF_STP0x0008) &&
39
Assuming the condition is false
993 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_LEARNING2)) {
994 m_freem(m);
995 return;
996 }
997
998 /*
999 * At this point, the port either doesn't participate in stp or
1000 * it's in the forwarding state
1001 */
1002
1003 /*
1004 * If packet is unicast, destined for someone on "this"
1005 * side of the bridge, drop it.
1006 */
1007 if (!ETHER_IS_MULTICAST(eh.ether_dhost)(*(eh.ether_dhost) & 0x01)) {
40
Assuming the condition is false
41
Taking false branch
1008 dst_ifidx = bridge_rtlookup(brifp, dst, NULL((void *)0));
1009 if (dst_ifidx == src_if->if_index) {
1010 m_freem(m);
1011 return;
1012 }
1013 } else {
1014 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)
)
42
Assuming the condition is false
43
Taking false branch
1015 m->m_flagsm_hdr.mh_flags |= M_BCAST0x0100;
1016 else
1017 m->m_flagsm_hdr.mh_flags |= M_MCAST0x0200;
1018 }
1019
1020 /*
1021 * Multicast packets get handled a little differently:
1022 * If interface is:
1023 * -link0,-link1 (default) Forward all multicast
1024 * as broadcast.
1025 * -link0,link1 Drop non-IP multicast, forward
1026 * as broadcast IP multicast.
1027 * link0,-link1 Drop IP multicast, forward as
1028 * broadcast non-IP multicast.
1029 * link0,link1 Drop all multicast.
1030 */
1031 if (m->m_flagsm_hdr.mh_flags & M_MCAST0x0200) {
44
Assuming the condition is false
1032 if ((sc->sc_if.if_flags &
1033 (IFF_LINK00x1000 | IFF_LINK10x2000)) ==
1034 (IFF_LINK00x1000 | IFF_LINK10x2000)) {
1035 m_freem(m);
1036 return;
1037 }
1038 if (sc->sc_if.if_flags & IFF_LINK00x1000 &&
1039 ETHERADDR_IS_IP_MCAST(dst)((dst)->ether_addr_octet[0] == 0x01 && (dst)->ether_addr_octet
[1] == 0x00 && (dst)->ether_addr_octet[2] == 0x5e)
) {
1040 m_freem(m);
1041 return;
1042 }
1043 if (sc->sc_if.if_flags & IFF_LINK10x2000 &&
1044 !ETHERADDR_IS_IP_MCAST(dst)((dst)->ether_addr_octet[0] == 0x01 && (dst)->ether_addr_octet
[1] == 0x00 && (dst)->ether_addr_octet[2] == 0x5e)
) {
1045 m_freem(m);
1046 return;
1047 }
1048 }
1049
1050 if (bif->bif_flags & IFBIF_BLOCKNONIP0x0004 && bridge_blocknonip(&eh, m)) {
45
Assuming the condition is false
1051 m_freem(m);
1052 return;
1053 }
1054
1055 if (bridge_filterrule(&bif->bif_brlin, &eh, m) == BRL_ACTION_BLOCK0x01) {
46
Assuming the condition is false
47
Taking false branch
1056 m_freem(m);
1057 return;
1058 }
1059 m = bridge_ip(&sc->sc_if, BRIDGE_INPF_IN, src_if, &eh, m);
1060 if (m
47.1
'm' is not equal to NULL
== NULL((void *)0))
1061 return;
1062 /*
1063 * If the packet is a multicast or broadcast OR if we don't
1064 * know any better, forward it to all interfaces.
1065 */
1066 if ((m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) || dst_ifidx == 0) {
48
Assuming the condition is false
49
The left operand of '==' is a garbage value
1067 sc->sc_if.if_imcastsif_data.ifi_imcasts++;
1068 bridge_broadcast(sc, src_if, &eh, m);
1069 return;
1070 }
1071 protected = bif->bif_protected;
1072
1073 dst_if = if_get(dst_ifidx);
1074 if (dst_if == NULL((void *)0))
1075 goto bad;
1076
1077 /*
1078 * At this point, we're dealing with a unicast frame going to a
1079 * different interface
1080 */
1081 if (!ISSET(dst_if->if_flags, IFF_RUNNING)((dst_if->if_flags) & (0x40)))
1082 goto bad;
1083 bif = bridge_getbif(dst_if);
1084 if ((bif == NULL((void *)0)) || ((bif->bif_flags & IFBIF_STP0x0008) &&
1085 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5)))
1086 goto bad;
1087 /*
1088 * Do not transmit if both ports are part of the same protected
1089 * domain.
1090 */
1091 if (protected != 0 && (protected & bif->bif_protected))
1092 goto bad;
1093 if (bridge_filterrule(&bif->bif_brlout, &eh, m) == BRL_ACTION_BLOCK0x01)
1094 goto bad;
1095 m = bridge_ip(&sc->sc_if, BRIDGE_OUTPF_OUT, dst_if, &eh, m);
1096 if (m == NULL((void *)0))
1097 goto bad;
1098
1099 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1100#if NVLAN1 > 0
1101 if ((m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) &&
1102 (dst_if->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_HWTAGGING0x00000020) == 0)
1103 len += ETHER_VLAN_ENCAP_LEN4;
1104#endif
1105 if ((len - ETHER_HDR_LEN((6 * 2) + 2)) > dst_if->if_mtuif_data.ifi_mtu)
1106 bridge_fragment(&sc->sc_if, dst_if, &eh, m);
1107 else {
1108 bridge_ifenqueue(&sc->sc_if, dst_if, m);
1109 }
1110 m = NULL((void *)0);
1111bad:
1112 if_put(dst_if);
1113 m_freem(m);
1114}
1115
1116/*
1117 * Return 1 if `ena' belongs to `bif', 0 otherwise.
1118 */
1119int
1120bridge_ourether(struct ifnet *ifp, uint8_t *ena)
1121{
1122 struct arpcom *ac = (struct arpcom *)ifp;
1123
1124 if (memcmp(ac->ac_enaddr, ena, ETHER_ADDR_LEN)__builtin_memcmp((ac->ac_enaddr), (ena), (6)) == 0)
1125 return (1);
1126
1127#if NCARP1 > 0
1128 if (carp_ourether(ifp, ena))
1129 return (1);
1130#endif
1131
1132 return (0);
1133}
1134
1135/*
1136 * Receive input from an interface. Queue the packet for bridging if its
1137 * not for us, and schedule an interrupt.
1138 */
1139struct mbuf *
1140bridge_input(struct ifnet *ifp, struct mbuf *m, uint64_t dst, void *null)
1141{
1142 KASSERT(m->m_flags & M_PKTHDR)((m->m_hdr.mh_flags & 0x0002) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/net/if_bridge.c", 1142, "m->m_flags & M_PKTHDR"
))
;
1143
1144 if (m->m_flagsm_hdr.mh_flags & M_PROTO10x0010) {
1145 m->m_flagsm_hdr.mh_flags &= ~M_PROTO10x0010;
1146 return (m);
1147 }
1148
1149 niq_enqueue(&bridgeintrq, m);
1150
1151 return (NULL((void *)0));
1152}
1153
1154void
1155bridge_process(struct ifnet *ifp, struct mbuf *m)
1156{
1157 struct ifnet *brifp;
1158 struct bridge_softc *sc;
1159 struct bridge_iflist *bif = NULL((void *)0), *bif0 = NULL((void *)0);
1160 struct ether_header *eh;
1161 struct mbuf *mc;
1162#if NBPFILTER1 > 0
1163 caddr_t if_bpf;
1164#endif
1165
1166 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 1166, "_kernel_lock_held()"))
;
8
Assuming the condition is true
9
'?' condition is true
1167
1168 brifp = if_get(ifp->if_bridgeidx);
1169 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
1170 goto reenqueue;
1171
1172 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < sizeof(*eh))
13
Assuming the condition is false
14
Taking false branch
1173 goto bad;
1174
1175#if NVLAN1 > 0
1176 /*
1177 * If the underlying interface removed the VLAN header itself,
1178 * add it back.
1179 */
1180 if (ISSET(m->m_flags, M_VLANTAG)((m->m_hdr.mh_flags) & (0x0020))) {
15
Assuming the condition is false
16
Taking false branch
1181 m = vlan_inject(m, ETHERTYPE_VLAN0x8100, m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag);
1182 if (m == NULL((void *)0))
1183 goto bad;
1184 }
1185#endif
1186
1187#if NBPFILTER1 > 0
1188 if_bpf = brifp->if_bpf;
1189 if (if_bpf)
17
Assuming 'if_bpf' is null
18
Taking false branch
1190 bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_IN(1 << 0));
1191#endif
1192
1193 eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data));
1194
1195 sc = brifp->if_softc;
1196 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 1203
1197 struct arpcom *ac = (struct arpcom *)bif->ifp;
1198 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
1199 goto bad;
1200 if (bif->ifp == ifp)
23
Assuming 'ifp' is equal to field 'ifp'
24
Taking true branch
1201 bif0 = bif;
1202 }
1203 if (bif0
26.1
'bif0' is not equal to NULL
== NULL((void *)0))
27
Taking false branch
1204 goto reenqueue;
1205
1206 bridge_span(brifp, m);
1207
1208 if (ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
28
Assuming the condition is true
29
Taking true branch
1209 /*
1210 * Reserved destination MAC addresses (01:80:C2:00:00:0x)
1211 * should not be forwarded to bridge members according to
1212 * section 7.12.6 of the 802.1D-2004 specification. The
1213 * STP destination address (as stored in bstp_etheraddr)
1214 * is the first of these.
1215 */
1216 if (memcmp(eh->ether_dhost, bstp_etheraddr,__builtin_memcmp((eh->ether_dhost), (bstp_etheraddr), (6 -
1))
30
Assuming the condition is false
1217 ETHER_ADDR_LEN - 1)__builtin_memcmp((eh->ether_dhost), (bstp_etheraddr), (6 -
1))
== 0
) {
1218 if (eh->ether_dhost[ETHER_ADDR_LEN6 - 1] == 0) {
1219 /* STP traffic */
1220 m = bstp_input(sc->sc_stp, bif0->bif_stp, eh,
1221 m);
1222 if (m == NULL((void *)0))
1223 goto bad;
1224 } else if (eh->ether_dhost[ETHER_ADDR_LEN6 - 1] <= 0xf)
1225 goto bad;
1226 }
1227
1228 /*
1229 * No need to process frames for ifs in the discarding state
1230 */
1231 if ((bif0->bif_flags & IFBIF_STP0x0008) &&
31
Assuming the condition is false
1232 (bif0->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
1233 goto reenqueue;
1234
1235 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1236 if (mc == NULL((void *)0))
32
Assuming 'mc' is not equal to NULL
33
Taking false branch
1237 goto reenqueue;
1238
1239 bridge_ifinput(ifp, mc);
1240
1241 bridgeintr_frame(brifp, ifp, m);
34
Calling 'bridgeintr_frame'
1242 if_put(brifp);
1243 return;
1244 }
1245
1246 /*
1247 * Unicast, make sure it's not for us.
1248 */
1249 if (bridge_ourether(bif0->ifp, eh->ether_dhost)) {
1250 bif = bif0;
1251 } else {
1252 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)))
{
1253 if (bif->ifp == ifp)
1254 continue;
1255 if (bridge_ourether(bif->ifp, eh->ether_dhost))
1256 break;
1257 }
1258 }
1259 if (bif != NULL((void *)0)) {
1260 if (bif0->bif_flags & IFBIF_LEARNING0x0001)
1261 bridge_rtupdate(sc,
1262 (struct ether_addr *)&eh->ether_shost,
1263 ifp, 0, IFBAF_DYNAMIC0x00, m);
1264 if (bridge_filterrule(&bif0->bif_brlin, eh, m) ==
1265 BRL_ACTION_BLOCK0x01) {
1266 goto bad;
1267 }
1268
1269 /* Count for the bridge */
1270 brifp->if_ipacketsif_data.ifi_ipackets++;
1271 brifp->if_ibytesif_data.ifi_ibytes += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1272
1273 ifp = bif->ifp;
1274 goto reenqueue;
1275 }
1276
1277 bridgeintr_frame(brifp, ifp, m);
1278 if_put(brifp);
1279 return;
1280
1281reenqueue:
1282 bridge_ifinput(ifp, m);
1283 m = NULL((void *)0);
1284bad:
1285 m_freem(m);
1286 if_put(brifp);
1287}
1288
1289/*
1290 * Send a frame to all interfaces that are members of the bridge
1291 * (except the one it came in on).
1292 */
1293void
1294bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
1295 struct ether_header *eh, struct mbuf *m)
1296{
1297 struct bridge_iflist *bif;
1298 struct mbuf *mc;
1299 struct ifnet *dst_if;
1300 int len, used = 0;
1301 u_int32_t protected;
1302
1303 bif = bridge_getbif(ifp);
1304 KASSERT(bif != NULL)((bif != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/net/if_bridge.c"
, 1304, "bif != NULL"))
;
1305 protected = bif->bif_protected;
1306
1307 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)))
{
1308 dst_if = bif->ifp;
1309
1310 if ((dst_if->if_flags & IFF_RUNNING0x40) == 0)
1311 continue;
1312
1313 if ((bif->bif_flags & IFBIF_STP0x0008) &&
1314 (bif->bif_statebif_stp->bp_state == BSTP_IFSTATE_DISCARDING5))
1315 continue;
1316
1317 if ((bif->bif_flags & IFBIF_DISCOVER0x0002) == 0 &&
1318 (m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100 | M_MCAST0x0200)) == 0)
1319 continue;
1320
1321 /* Drop non-IP frames if the appropriate flag is set. */
1322 if (bif->bif_flags & IFBIF_BLOCKNONIP0x0004 &&
1323 bridge_blocknonip(eh, m))
1324 continue;
1325
1326 /*
1327 * Do not transmit if both ports are part of the same
1328 * protected domain.
1329 */
1330 if (protected != 0 && (protected & bif->bif_protected))
1331 continue;
1332
1333 if (bridge_filterrule(&bif->bif_brlout, eh, m) ==
1334 BRL_ACTION_BLOCK0x01)
1335 continue;
1336
1337 /*
1338 * Don't retransmit out of the same interface where
1339 * the packet was received from.
1340 */
1341 if (dst_if->if_index == ifp->if_index)
1342 continue;
1343
1344 if (bridge_localbroadcast(dst_if, eh, m))
1345 sc->sc_if.if_oerrorsif_data.ifi_oerrors++;
1346
1347 /* If last one, reuse the passed-in mbuf */
1348 if (SMR_SLIST_NEXT_LOCKED(bif, bif_next)(*(&(bif)->bif_next.smr_sle_next)) == NULL((void *)0)) {
1349 mc = m;
1350 used = 1;
1351 } else {
1352 mc = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1353 if (mc == NULL((void *)0)) {
1354 sc->sc_if.if_oerrorsif_data.ifi_oerrors++;
1355 continue;
1356 }
1357 }
1358
1359 mc = bridge_ip(&sc->sc_if, BRIDGE_OUTPF_OUT, dst_if, eh, mc);
1360 if (mc == NULL((void *)0))
1361 continue;
1362
1363 len = mc->m_pkthdrM_dat.MH.MH_pkthdr.len;
1364#if NVLAN1 > 0
1365 if ((mc->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) &&
1366 (dst_if->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_HWTAGGING0x00000020) == 0)
1367 len += ETHER_VLAN_ENCAP_LEN4;
1368#endif
1369 if ((len - ETHER_HDR_LEN((6 * 2) + 2)) > dst_if->if_mtuif_data.ifi_mtu)
1370 bridge_fragment(&sc->sc_if, dst_if, eh, mc);
1371 else {
1372 bridge_ifenqueue(&sc->sc_if, dst_if, mc);
1373 }
1374 }
1375
1376 if (!used)
1377 m_freem(m);
1378}
1379
1380int
1381bridge_localbroadcast(struct ifnet *ifp, struct ether_header *eh,
1382 struct mbuf *m)
1383{
1384 struct mbuf *m1;
1385 u_int16_t etype;
1386
1387 /*
1388 * quick optimisation, don't send packets up the stack if no
1389 * corresponding address has been specified.
1390 */
1391 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))
;
1392 if (!(m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) && etype == ETHERTYPE_IP0x0800) {
1393 struct ifaddr *ifa;
1394 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list)for((ifa) = ((&ifp->if_addrlist)->tqh_first); (ifa)
!= ((void *)0); (ifa) = ((ifa)->ifa_list.tqe_next))
{
1395 if (ifa->ifa_addr->sa_family == AF_INET2)
1396 break;
1397 }
1398 if (ifa == NULL((void *)0))
1399 return (0);
1400 }
1401
1402 m1 = m_dup_pkt(m, ETHER_ALIGN2, M_NOWAIT0x0002);
1403 if (m1 == NULL((void *)0))
1404 return (1);
1405
1406#if NPF1 > 0
1407 pf_pkt_addr_changed(m1);
1408#endif /* NPF */
1409
1410 bridge_ifinput(ifp, m1);
1411
1412 return (0);
1413}
1414
1415void
1416bridge_span(struct ifnet *brifp, struct mbuf *m)
1417{
1418 struct bridge_softc *sc = brifp->if_softc;
1419 struct bridge_iflist *bif;
1420 struct ifnet *ifp;
1421 struct mbuf *mc;
1422 int error;
1423
1424 smr_read_enter();
1425 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; }))
{
1426 ifp = bif->ifp;
1427
1428 if ((ifp->if_flags & IFF_RUNNING0x40) == 0)
1429 continue;
1430
1431 mc = m_copym(m, 0, M_COPYALL1000000000, M_DONTWAIT0x0002);
1432 if (mc == NULL((void *)0)) {
1433 brifp->if_oerrorsif_data.ifi_oerrors++;
1434 continue;
1435 }
1436
1437 error = bridge_ifenqueue(brifp, ifp, mc);
1438 if (error)
1439 continue;
1440 }
1441 smr_read_leave();
1442}
1443
1444/*
1445 * Block non-ip frames:
1446 * Returns 0 if frame is ip, and 1 if it should be dropped.
1447 */
1448int
1449bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
1450{
1451 struct llc llc;
1452 u_int16_t etype;
1453
1454 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < ETHER_HDR_LEN((6 * 2) + 2))
1455 return (1);
1456
1457#if NVLAN1 > 0
1458 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1459 return (1);
1460#endif
1461
1462 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))
;
1463 switch (etype) {
1464 case ETHERTYPE_ARP0x0806:
1465 case ETHERTYPE_REVARP0x8035:
1466 case ETHERTYPE_IP0x0800:
1467 case ETHERTYPE_IPV60x86DD:
1468 return (0);
1469 }
1470
1471 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4))
1472 return (1);
1473
1474 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len <
1475 (ETHER_HDR_LEN((6 * 2) + 2) + LLC_SNAPFRAMELEN8))
1476 return (1);
1477
1478 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1479
1480 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))
;
1481 if (llc.llc_dsap == LLC_SNAP_LSAP0xaa &&
1482 llc.llc_ssap == LLC_SNAP_LSAP0xaa &&
1483 llc.llc_controlllc_un.type_u.control == LLC_UI0x3 &&
1484 llc.llc_snapllc_un.type_snap.org_code[0] == 0 &&
1485 llc.llc_snapllc_un.type_snap.org_code[1] == 0 &&
1486 llc.llc_snapllc_un.type_snap.org_code[2] == 0 &&
1487 (etype == ETHERTYPE_ARP0x0806 || etype == ETHERTYPE_REVARP0x8035 ||
1488 etype == ETHERTYPE_IP0x0800 || etype == ETHERTYPE_IPV60x86DD)) {
1489 return (0);
1490 }
1491
1492 return (1);
1493}
1494
1495#ifdef IPSEC1
1496int
1497bridge_ipsec(struct ifnet *ifp, struct ether_header *eh, int hassnap,
1498 struct llc *llc, int dir, int af, int hlen, struct mbuf *m)
1499{
1500 union sockaddr_union dst;
1501 struct tdb *tdb;
1502 u_int32_t spi;
1503 u_int16_t cpi;
1504 int error, off, prot;
1505 u_int8_t proto = 0;
1506 struct ip *ip;
1507#ifdef INET61
1508 struct ip6_hdr *ip6;
1509#endif /* INET6 */
1510#if NPF1 > 0
1511 struct ifnet *encif;
1512#endif
1513
1514 if (dir == BRIDGE_INPF_IN) {
1515 switch (af) {
1516 case AF_INET2:
1517 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1518 goto skiplookup;
1519
1520 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1521 proto = ip->ip_p;
1522 off = offsetof(struct ip, ip_p)__builtin_offsetof(struct ip, ip_p);
1523
1524 if (proto != IPPROTO_ESP50 && proto != IPPROTO_AH51 &&
1525 proto != IPPROTO_IPCOMP108)
1526 goto skiplookup;
1527
1528 bzero(&dst, sizeof(union sockaddr_union))__builtin_bzero((&dst), (sizeof(union sockaddr_union)));
1529 dst.sa.sa_family = AF_INET2;
1530 dst.sin.sin_len = sizeof(struct sockaddr_in);
1531 m_copydata(m, offsetof(struct ip, ip_dst)__builtin_offsetof(struct ip, ip_dst),
1532 sizeof(struct in_addr), &dst.sin.sin_addr);
1533
1534 break;
1535#ifdef INET61
1536 case AF_INET624:
1537 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1538 goto skiplookup;
1539
1540 ip6 = mtod(m, struct ip6_hdr *)((struct ip6_hdr *)((m)->m_hdr.mh_data));
1541
1542 /* XXX We should chase down the header chain */
1543 proto = ip6->ip6_nxtip6_ctlun.ip6_un1.ip6_un1_nxt;
1544 off = offsetof(struct ip6_hdr, ip6_nxt)__builtin_offsetof(struct ip6_hdr, ip6_ctlun.ip6_un1.ip6_un1_nxt
)
;
1545
1546 if (proto != IPPROTO_ESP50 && proto != IPPROTO_AH51 &&
1547 proto != IPPROTO_IPCOMP108)
1548 goto skiplookup;
1549
1550 bzero(&dst, sizeof(union sockaddr_union))__builtin_bzero((&dst), (sizeof(union sockaddr_union)));
1551 dst.sa.sa_family = AF_INET624;
1552 dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
1553 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst)__builtin_offsetof(struct ip6_hdr, ip6_dst),
1554 sizeof(struct in6_addr), &dst.sin6.sin6_addr);
1555
1556 break;
1557#endif /* INET6 */
1558 default:
1559 return (0);
1560 }
1561
1562 switch (proto) {
1563 case IPPROTO_ESP50:
1564 m_copydata(m, hlen, sizeof(u_int32_t), &spi);
1565 break;
1566 case IPPROTO_AH51:
1567 m_copydata(m, hlen + sizeof(u_int32_t),
1568 sizeof(u_int32_t), &spi);
1569 break;
1570 case IPPROTO_IPCOMP108:
1571 m_copydata(m, hlen + sizeof(u_int16_t),
1572 sizeof(u_int16_t), &cpi);
1573 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))))
;
1574 break;
1575 }
1576
1577 NET_ASSERT_LOCKED()do { int _s = rw_status(&netlock); if ((splassert_ctl >
0) && (_s != 0x0001UL && _s != 0x0002UL)) splassert_fail
(0x0002UL, _s, __func__); } while (0)
;
1578
1579 tdb = gettdb(ifp->if_rdomain, spi, &dst, proto)gettdb_dir((ifp->if_data.ifi_rdomain),(spi),(&dst),(proto
),0)
;
1580 if (tdb != NULL((void *)0) && (tdb->tdb_flags & TDBF_INVALID0x00010) == 0 &&
1581 tdb->tdb_xform != NULL((void *)0)) {
1582 if (tdb->tdb_first_use == 0) {
1583 tdb->tdb_first_use = gettime();
1584 if (tdb->tdb_flags & TDBF_FIRSTUSE0x00020) {
1585 if (timeout_add_sec(
1586 &tdb->tdb_first_tmo,
1587 tdb->tdb_exp_first_use))
1588 tdb_ref(tdb);
1589 }
1590 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE0x00400) {
1591 if (timeout_add_sec(
1592 &tdb->tdb_sfirst_tmo,
1593 tdb->tdb_soft_first_use))
1594 tdb_ref(tdb);
1595 }
1596 }
1597
1598 prot = (*(tdb->tdb_xform->xf_input))(&m, tdb, hlen,
1599 off);
1600 tdb_unref(tdb);
1601 if (prot != IPPROTO_DONE257)
1602 ip_deliver(&m, &hlen, prot, af);
1603 return (1);
1604 } else {
1605 tdb_unref(tdb);
1606 skiplookup:
1607 /* XXX do an input policy lookup */
1608 return (0);
1609 }
1610 } else { /* Outgoing from the bridge. */
1611 error = ipsp_spd_lookup(m, af, hlen, IPSP_DIRECTION_OUT0x2,
1612 NULL((void *)0), NULL((void *)0), &tdb, NULL((void *)0));
1613 if (error == 0 && tdb != NULL((void *)0)) {
1614 /*
1615 * We don't need to do loop detection, the
1616 * bridge will do that for us.
1617 */
1618#if NPF1 > 0
1619 if ((encif = enc_getif(tdb->tdb_rdomain,
1620 tdb->tdb_tap)) == NULL((void *)0) ||
1621 pf_test(af, dir, encif, &m) != PF_PASS) {
1622 m_freem(m);
1623 tdb_unref(tdb);
1624 return (1);
1625 }
1626 if (m == NULL((void *)0)) {
1627 tdb_unref(tdb);
1628 return (1);
1629 }
1630 if (af == AF_INET2)
1631 in_proto_cksum_out(m, encif);
1632#ifdef INET61
1633 else if (af == AF_INET624)
1634 in6_proto_cksum_out(m, encif);
1635#endif /* INET6 */
1636#endif /* NPF */
1637
1638 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1639 if ((af == AF_INET2) &&
1640 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))
) &&
1641 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 &&
1642 tdb->tdb_mtutimeout > gettime()) {
1643 bridge_send_icmp_err(ifp, eh, m,
1644 hassnap, llc, tdb->tdb_mtu,
1645 ICMP_UNREACH3, ICMP_UNREACH_NEEDFRAG4);
1646 } else {
1647 KERNEL_LOCK()_kernel_lock();
1648 error = ipsp_process_packet(m, tdb, af, 0);
1649 KERNEL_UNLOCK()_kernel_unlock();
1650 }
1651 tdb_unref(tdb);
1652 return (1);
1653 } else
1654 return (0);
1655 }
1656
1657 return (0);
1658}
1659#endif /* IPSEC */
1660
1661/*
1662 * Filter IP packets by peeking into the ethernet frame. This violates
1663 * the ISO model, but allows us to act as a IP filter at the data link
1664 * layer. As a result, most of this code will look familiar to those
1665 * who've read net/if_ethersubr.c and netinet/ip_input.c
1666 */
1667struct mbuf *
1668bridge_ip(struct ifnet *brifp, int dir, struct ifnet *ifp,
1669 struct ether_header *eh, struct mbuf *m)
1670{
1671 struct llc llc;
1672 int hassnap = 0;
1673 struct ip *ip;
1674 int hlen;
1675 u_int16_t etype;
1676
1677#if NVLAN1 > 0
1678 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1679 return (m);
1680#endif
1681
1682 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))
;
1683
1684 if (etype != ETHERTYPE_IP0x0800 && etype != ETHERTYPE_IPV60x86DD) {
1685 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4) ||
1686 m->m_pkthdrM_dat.MH.MH_pkthdr.len < (LLC_SNAPFRAMELEN8 +
1687 ETHER_HDR_LEN((6 * 2) + 2)))
1688 return (m);
1689
1690 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1691
1692 if (llc.llc_dsap != LLC_SNAP_LSAP0xaa ||
1693 llc.llc_ssap != LLC_SNAP_LSAP0xaa ||
1694 llc.llc_controlllc_un.type_u.control != LLC_UI0x3 ||
1695 llc.llc_snapllc_un.type_snap.org_code[0] ||
1696 llc.llc_snapllc_un.type_snap.org_code[1] ||
1697 llc.llc_snapllc_un.type_snap.org_code[2])
1698 return (m);
1699
1700 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))
;
1701 if (etype != ETHERTYPE_IP0x0800 && etype != ETHERTYPE_IPV60x86DD)
1702 return (m);
1703 hassnap = 1;
1704 }
1705
1706 m_adj(m, ETHER_HDR_LEN((6 * 2) + 2));
1707 if (hassnap)
1708 m_adj(m, LLC_SNAPFRAMELEN8);
1709
1710 switch (etype) {
1711
1712 case ETHERTYPE_IP0x0800:
1713 m = ipv4_check(ifp, m);
1714 if (m == NULL((void *)0))
1715 return (NULL((void *)0));
1716
1717 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1718 hlen = ip->ip_hl << 2;
1719
1720#ifdef IPSEC1
1721 if ((brifp->if_flags & IFF_LINK20x4000) == IFF_LINK20x4000 &&
1722 bridge_ipsec(ifp, eh, hassnap, &llc, dir, AF_INET2, hlen, m))
1723 return (NULL((void *)0));
1724#endif /* IPSEC */
1725#if NPF1 > 0
1726 /* Finally, we get to filter the packet! */
1727 if (pf_test(AF_INET2, dir, ifp, &m) != PF_PASS)
1728 goto dropit;
1729 if (m == NULL((void *)0))
1730 goto dropit;
1731#endif /* NPF > 0 */
1732
1733 /* Rebuild the IP header */
1734 if (m->m_lenm_hdr.mh_len < hlen && ((m = m_pullup(m, hlen)) == NULL((void *)0)))
1735 return (NULL((void *)0));
1736 if (m->m_lenm_hdr.mh_len < sizeof(struct ip))
1737 goto dropit;
1738 in_hdr_cksum_out(m, ifp);
1739 in_proto_cksum_out(m, ifp);
1740
1741#if NPF1 > 0
1742 if (dir == BRIDGE_INPF_IN &&
1743 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_DIVERTED0x08) {
1744 m_resethdr(m);
1745 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
1746 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1747 ipv4_input(ifp, m);
1748 return (NULL((void *)0));
1749 }
1750#endif /* NPF > 0 */
1751
1752 break;
1753
1754#ifdef INET61
1755 case ETHERTYPE_IPV60x86DD:
1756 m = ipv6_check(ifp, m);
1757 if (m == NULL((void *)0))
1758 return (NULL((void *)0));
1759
1760#ifdef IPSEC1
1761 hlen = sizeof(struct ip6_hdr);
1762
1763 if ((brifp->if_flags & IFF_LINK20x4000) == IFF_LINK20x4000 &&
1764 bridge_ipsec(ifp, eh, hassnap, &llc, dir, AF_INET624, hlen,
1765 m))
1766 return (NULL((void *)0));
1767#endif /* IPSEC */
1768
1769#if NPF1 > 0
1770 if (pf_test(AF_INET624, dir, ifp, &m) != PF_PASS)
1771 goto dropit;
1772 if (m == NULL((void *)0))
1773 return (NULL((void *)0));
1774#endif /* NPF > 0 */
1775 in6_proto_cksum_out(m, ifp);
1776
1777#if NPF1 > 0
1778 if (dir == BRIDGE_INPF_IN &&
1779 m->m_pkthdrM_dat.MH.MH_pkthdr.pf.flags & PF_TAG_DIVERTED0x08) {
1780 m_resethdr(m);
1781 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = ifp->if_index;
1782 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_rtableid = ifp->if_rdomainif_data.ifi_rdomain;
1783 ipv6_input(ifp, m);
1784 return (NULL((void *)0));
1785 }
1786#endif /* NPF > 0 */
1787
1788 break;
1789#endif /* INET6 */
1790
1791 default:
1792 goto dropit;
1793 break;
1794 }
1795
1796 /* Reattach SNAP header */
1797 if (hassnap) {
1798 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1799 if (m == NULL((void *)0))
1800 goto dropit;
1801 bcopy(&llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
1802 }
1803
1804 /* Reattach ethernet header */
1805 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
1806 if (m == NULL((void *)0))
1807 goto dropit;
1808 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
1809
1810 return (m);
1811
1812dropit:
1813 m_freem(m);
1814 return (NULL((void *)0));
1815}
1816
1817void
1818bridge_fragment(struct ifnet *brifp, struct ifnet *ifp, struct ether_header *eh,
1819 struct mbuf *m)
1820{
1821 struct llc llc;
1822 struct mbuf_list ml;
1823 int error = 0;
1824 int hassnap = 0;
1825 u_int16_t etype;
1826 struct ip *ip;
1827
1828 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))
;
1829#if NVLAN1 > 0
1830 if ((m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020) || etype == ETHERTYPE_VLAN0x8100 ||
1831 etype == ETHERTYPE_QINQ0x88A8) {
1832 int len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1833
1834 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1835 len += ETHER_VLAN_ENCAP_LEN4;
1836 if ((ifp->if_capabilitiesif_data.ifi_capabilities & IFCAP_VLAN_MTU0x00000010) &&
1837 (len - sizeof(struct ether_vlan_header) <= ifp->if_mtuif_data.ifi_mtu)) {
1838 bridge_ifenqueue(brifp, ifp, m);
1839 return;
1840 }
1841 goto dropit;
1842 }
1843#endif
1844 if (etype != ETHERTYPE_IP0x0800) {
1845 if (etype > ETHERMTU(1518 - ((6 * 2) + 2) - 4) ||
1846 m->m_pkthdrM_dat.MH.MH_pkthdr.len < (LLC_SNAPFRAMELEN8 +
1847 ETHER_HDR_LEN((6 * 2) + 2)))
1848 goto dropit;
1849
1850 m_copydata(m, ETHER_HDR_LEN((6 * 2) + 2), LLC_SNAPFRAMELEN8, &llc);
1851
1852 if (llc.llc_dsap != LLC_SNAP_LSAP0xaa ||
1853 llc.llc_ssap != LLC_SNAP_LSAP0xaa ||
1854 llc.llc_controlllc_un.type_u.control != LLC_UI0x3 ||
1855 llc.llc_snapllc_un.type_snap.org_code[0] ||
1856 llc.llc_snapllc_un.type_snap.org_code[1] ||
1857 llc.llc_snapllc_un.type_snap.org_code[2] ||
1858 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))
)
1859 goto dropit;
1860
1861 hassnap = 1;
1862 }
1863
1864 m_adj(m, ETHER_HDR_LEN((6 * 2) + 2));
1865 if (hassnap)
1866 m_adj(m, LLC_SNAPFRAMELEN8);
1867
1868 if (m->m_lenm_hdr.mh_len < sizeof(struct ip) &&
1869 (m = m_pullup(m, sizeof(struct ip))) == NULL((void *)0))
1870 goto dropit;
1871 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1872
1873 /* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
1874 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))
) {
1875 bridge_send_icmp_err(ifp, eh, m, hassnap, &llc,
1876 ifp->if_mtuif_data.ifi_mtu, ICMP_UNREACH3, ICMP_UNREACH_NEEDFRAG4);
1877 return;
1878 }
1879
1880 error = ip_fragment(m, &ml, ifp, ifp->if_mtuif_data.ifi_mtu);
1881 if (error)
1882 return;
1883
1884 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
1885 if (hassnap) {
1886 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1887 if (m == NULL((void *)0)) {
1888 error = ENOBUFS55;
1889 break;
1890 }
1891 bcopy(&llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
1892 }
1893 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
1894 if (m == NULL((void *)0)) {
1895 error = ENOBUFS55;
1896 break;
1897 }
1898 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
1899 error = bridge_ifenqueue(brifp, ifp, m);
1900 if (error)
1901 break;
1902 }
1903 if (error)
1904 ml_purge(&ml);
1905 else
1906 ipstat_inc(ips_fragmented);
1907
1908 return;
1909 dropit:
1910 m_freem(m);
1911}
1912
1913int
1914bridge_ifenqueue(struct ifnet *brifp, struct ifnet *ifp, struct mbuf *m)
1915{
1916 int error, len;
1917
1918 /* Loop prevention. */
1919 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
1920
1921 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1922
1923 error = if_enqueue(ifp, m);
1924 if (error) {
1925 brifp->if_oerrorsif_data.ifi_oerrors++;
1926 return (error);
1927 }
1928
1929 brifp->if_opacketsif_data.ifi_opackets++;
1930 brifp->if_obytesif_data.ifi_obytes += len;
1931
1932 return (0);
1933}
1934
1935void
1936bridge_ifinput(struct ifnet *ifp, struct mbuf *m)
1937{
1938 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1939
1940 m->m_flagsm_hdr.mh_flags |= M_PROTO10x0010;
1941
1942 ml_enqueue(&ml, m);
1943 if_input(ifp, &ml);
1944}
1945
1946void
1947bridge_send_icmp_err(struct ifnet *ifp,
1948 struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
1949 int mtu, int type, int code)
1950{
1951 struct ip *ip;
1952 struct icmp *icp;
1953 struct in_addr t;
1954 struct mbuf *m, *n2;
1955 int hlen;
1956 u_int8_t ether_tmp[ETHER_ADDR_LEN6];
1957
1958 n2 = m_copym(n, 0, M_COPYALL1000000000, M_DONTWAIT0x0002);
1959 if (!n2) {
1960 m_freem(n);
1961 return;
1962 }
1963 m = icmp_do_error(n, type, code, 0, mtu);
1964 if (m == NULL((void *)0)) {
1965 m_freem(n2);
1966 return;
1967 }
1968
1969 n = n2;
1970
1971 ip = mtod(m, struct ip *)((struct ip *)((m)->m_hdr.mh_data));
1972 hlen = ip->ip_hl << 2;
1973 t = ip->ip_dst;
1974 ip->ip_dst = ip->ip_src;
1975 ip->ip_src = t;
1976
1977 m->m_datam_hdr.mh_data += hlen;
1978 m->m_lenm_hdr.mh_len -= hlen;
1979 icp = mtod(m, struct icmp *)((struct icmp *)((m)->m_hdr.mh_data));
1980 icp->icmp_cksum = 0;
1981 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);
1982 m->m_datam_hdr.mh_data -= hlen;
1983 m->m_lenm_hdr.mh_len += hlen;
1984
1985 ip->ip_v = IPVERSION4;
1986 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))
;
1987 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
()))
;
1988 ip->ip_ttl = MAXTTL255;
1989 in_hdr_cksum_out(m, NULL((void *)0));
1990
1991 /* Swap ethernet addresses */
1992 bcopy(&eh->ether_dhost, &ether_tmp, sizeof(ether_tmp));
1993 bcopy(&eh->ether_shost, &eh->ether_dhost, sizeof(ether_tmp));
1994 bcopy(&ether_tmp, &eh->ether_shost, sizeof(ether_tmp));
1995
1996 /* Reattach SNAP header */
1997 if (hassnap) {
1998 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT)(m) = m_prepend((m), (8), (0x0002));
1999 if (m == NULL((void *)0))
2000 goto dropit;
2001 bcopy(llc, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), LLC_SNAPFRAMELEN8);
2002 }
2003
2004 /* Reattach ethernet header */
2005 M_PREPEND(m, sizeof(*eh), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*eh)), (0x0002));
2006 if (m == NULL((void *)0))
2007 goto dropit;
2008 bcopy(eh, mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), sizeof(*eh));
2009
2010 bridge_enqueue(ifp, m);
2011 m_freem(n);
2012 return;
2013
2014 dropit:
2015 m_freem(n);
2016}
2017
2018void
2019bridge_take(void *unused)
2020{
2021 return;
2022}
2023
2024void
2025bridge_rele(void *unused)
2026{
2027 return;
2028}