Bug Summary

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

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))
939 return;
940
941 KERNEL_LOCK()_kernel_lock();
942 while ((m = ml_dequeue(&ml)) != NULL((void *)0)) {
943
944 ifp = if_get(m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx);
945 if (ifp == NULL((void *)0)) {
946 m_freem(m);
947 continue;
948 }
949
950 bridge_process(ifp, m);
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;
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"))
;
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) &&
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) &&
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)) {
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)
)
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) {
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)) {
1051 m_freem(m);
1052 return;
1053 }
1054
1055 if (bridge_filterrule(&bif->bif_brlin, &eh, m) == BRL_ACTION_BLOCK0x01) {
1056 m_freem(m);
1057 return;
1058 }
1059 m = bridge_ip(&sc->sc_if, BRIDGE_INPF_IN, src_if, &eh, m);
1060 if (m == 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) {
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()"))
;
1167
1168 brifp = if_get(ifp->if_bridgeidx);
1169 if ((brifp == NULL((void *)0)) || !ISSET(brifp->if_flags, IFF_RUNNING)((brifp->if_flags) & (0x40)))
1170 goto reenqueue;
1171
1172 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < sizeof(*eh))
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))) {
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)
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)))
{
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)
1199 goto bad;
1200 if (bif->ifp == ifp)
1201 bif0 = bif;
1202 }
1203 if (bif0 == NULL((void *)0))
1204 goto reenqueue;
1205
1206 bridge_span(brifp, m);
1207
1208 if (ETHER_IS_MULTICAST(eh->ether_dhost)(*(eh->ether_dhost) & 0x01)) {
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))
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) &&
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))
1237 goto reenqueue;
1238
1239 bridge_ifinput(ifp, mc);
1240
1241 bridgeintr_frame(brifp, ifp, m);
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);
Value stored to 'error' is never read
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}