Line data Source code
1 : /* $OpenBSD: if_bridge.c,v 1.308 2018/04/19 22:31:25 dlg 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 : #include "mpw.h"
40 :
41 : #include <sys/param.h>
42 : #include <sys/systm.h>
43 : #include <sys/mbuf.h>
44 : #include <sys/socket.h>
45 : #include <sys/ioctl.h>
46 : #include <sys/kernel.h>
47 :
48 : #include <net/if.h>
49 : #include <net/if_types.h>
50 : #include <net/if_llc.h>
51 : #include <net/netisr.h>
52 :
53 : #include <netinet/in.h>
54 : #include <netinet/ip.h>
55 : #include <netinet/ip_var.h>
56 : #include <netinet/if_ether.h>
57 : #include <netinet/ip_icmp.h>
58 :
59 : #ifdef IPSEC
60 : #include <netinet/ip_ipsp.h>
61 : #include <net/if_enc.h>
62 : #endif
63 :
64 : #ifdef INET6
65 : #include <netinet6/in6_var.h>
66 : #include <netinet/ip6.h>
67 : #include <netinet6/ip6_var.h>
68 : #endif
69 :
70 : #if NPF > 0
71 : #include <net/pfvar.h>
72 : #define BRIDGE_IN PF_IN
73 : #define BRIDGE_OUT PF_OUT
74 : #else
75 : #define BRIDGE_IN 0
76 : #define BRIDGE_OUT 1
77 : #endif
78 :
79 : #if NBPFILTER > 0
80 : #include <net/bpf.h>
81 : #endif
82 :
83 : #if NCARP > 0
84 : #include <netinet/ip_carp.h>
85 : #endif
86 :
87 : #if NVLAN > 0
88 : #include <net/if_vlan_var.h>
89 : #endif
90 :
91 : #include <net/if_bridge.h>
92 :
93 : /*
94 : * Maximum number of addresses to cache
95 : */
96 : #ifndef BRIDGE_RTABLE_MAX
97 : #define BRIDGE_RTABLE_MAX 100
98 : #endif
99 :
100 : /*
101 : * Timeout (in seconds) for entries learned dynamically
102 : */
103 : #ifndef BRIDGE_RTABLE_TIMEOUT
104 : #define BRIDGE_RTABLE_TIMEOUT 240
105 : #endif
106 :
107 : void bridgeattach(int);
108 : int bridge_ioctl(struct ifnet *, u_long, caddr_t);
109 : void bridge_ifdetach(void *);
110 : void bridge_spandetach(void *);
111 : int bridge_input(struct ifnet *, struct mbuf *, void *);
112 : void bridge_process(struct ifnet *, struct mbuf *);
113 : void bridgeintr_frame(struct bridge_softc *, struct ifnet *, struct mbuf *);
114 : void bridge_broadcast(struct bridge_softc *, struct ifnet *,
115 : struct ether_header *, struct mbuf *);
116 : void bridge_localbroadcast(struct bridge_softc *, struct ifnet *,
117 : struct ether_header *, struct mbuf *);
118 : void bridge_span(struct bridge_softc *, struct mbuf *);
119 : void bridge_stop(struct bridge_softc *);
120 : void bridge_init(struct bridge_softc *);
121 : int bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
122 : int bridge_blocknonip(struct ether_header *, struct mbuf *);
123 : void bridge_ifinput(struct ifnet *, struct mbuf *);
124 : int bridge_dummy_output(struct ifnet *, struct mbuf *, struct sockaddr *,
125 : struct rtentry *);
126 : #ifdef IPSEC
127 : int bridge_ipsec(struct bridge_softc *, struct ifnet *,
128 : struct ether_header *, int, struct llc *,
129 : int, int, int, struct mbuf *);
130 : #endif
131 : int bridge_clone_create(struct if_clone *, int);
132 : int bridge_clone_destroy(struct ifnet *ifp);
133 : int bridge_delete(struct bridge_softc *, struct bridge_iflist *);
134 :
135 : #define ETHERADDR_IS_IP_MCAST(a) \
136 : /* struct etheraddr *a; */ \
137 : ((a)->ether_addr_octet[0] == 0x01 && \
138 : (a)->ether_addr_octet[1] == 0x00 && \
139 : (a)->ether_addr_octet[2] == 0x5e)
140 :
141 : struct niqueue bridgeintrq = NIQUEUE_INITIALIZER(1024, NETISR_BRIDGE);
142 :
143 : struct if_clone bridge_cloner =
144 : IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
145 :
146 : void
147 0 : bridgeattach(int n)
148 : {
149 0 : if_clone_attach(&bridge_cloner);
150 0 : }
151 :
152 : int
153 0 : bridge_clone_create(struct if_clone *ifc, int unit)
154 : {
155 : struct bridge_softc *sc;
156 : struct ifnet *ifp;
157 : int i;
158 :
159 0 : sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
160 0 : sc->sc_stp = bstp_create(&sc->sc_if);
161 0 : if (!sc->sc_stp) {
162 0 : free(sc, M_DEVBUF, sizeof *sc);
163 0 : return (ENOMEM);
164 : }
165 :
166 0 : sc->sc_brtmax = BRIDGE_RTABLE_MAX;
167 0 : sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
168 0 : timeout_set(&sc->sc_brtimeout, bridge_rtage, sc);
169 0 : TAILQ_INIT(&sc->sc_iflist);
170 0 : TAILQ_INIT(&sc->sc_spanlist);
171 0 : for (i = 0; i < BRIDGE_RTABLE_SIZE; i++)
172 0 : LIST_INIT(&sc->sc_rts[i]);
173 0 : arc4random_buf(&sc->sc_hashkey, sizeof(sc->sc_hashkey));
174 : ifp = &sc->sc_if;
175 0 : snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
176 : unit);
177 0 : ifp->if_softc = sc;
178 0 : ifp->if_mtu = ETHERMTU;
179 0 : ifp->if_ioctl = bridge_ioctl;
180 0 : ifp->if_output = bridge_dummy_output;
181 0 : ifp->if_xflags = IFXF_CLONED;
182 0 : ifp->if_start = NULL;
183 0 : ifp->if_type = IFT_BRIDGE;
184 0 : ifp->if_hdrlen = ETHER_HDR_LEN;
185 :
186 0 : if_attach(ifp);
187 0 : if_alloc_sadl(ifp);
188 :
189 : #if NBPFILTER > 0
190 0 : bpfattach(&sc->sc_if.if_bpf, ifp,
191 : DLT_EN10MB, ETHER_HDR_LEN);
192 : #endif
193 :
194 0 : if_ih_insert(ifp, ether_input, NULL);
195 :
196 0 : return (0);
197 0 : }
198 :
199 : int
200 0 : bridge_dummy_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
201 : struct rtentry *rt)
202 : {
203 0 : m_freem(m);
204 0 : return (EAFNOSUPPORT);
205 : }
206 :
207 : int
208 0 : bridge_clone_destroy(struct ifnet *ifp)
209 : {
210 0 : struct bridge_softc *sc = ifp->if_softc;
211 : struct bridge_iflist *bif;
212 :
213 0 : bridge_stop(sc);
214 0 : bridge_rtflush(sc, IFBF_FLUSHALL);
215 0 : while ((bif = TAILQ_FIRST(&sc->sc_iflist)) != NULL)
216 0 : bridge_delete(sc, bif);
217 0 : while ((bif = TAILQ_FIRST(&sc->sc_spanlist)) != NULL)
218 0 : bridge_spandetach(bif);
219 :
220 0 : bstp_destroy(sc->sc_stp);
221 :
222 : /* Undo pseudo-driver changes. */
223 0 : if_deactivate(ifp);
224 :
225 0 : if_ih_remove(ifp, ether_input, NULL);
226 :
227 0 : KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs));
228 :
229 0 : if_detach(ifp);
230 :
231 0 : free(sc, M_DEVBUF, sizeof *sc);
232 0 : return (0);
233 : }
234 :
235 : int
236 0 : bridge_delete(struct bridge_softc *sc, struct bridge_iflist *p)
237 : {
238 : int error;
239 :
240 0 : if (p->bif_flags & IFBIF_STP)
241 0 : bstp_delete(p->bif_stp);
242 :
243 0 : p->ifp->if_bridgeport = NULL;
244 0 : error = ifpromisc(p->ifp, 0);
245 0 : hook_disestablish(p->ifp->if_detachhooks, p->bif_dhcookie);
246 :
247 0 : if_ih_remove(p->ifp, bridge_input, NULL);
248 0 : TAILQ_REMOVE(&sc->sc_iflist, p, next);
249 0 : bridge_rtdelete(sc, p->ifp, 0);
250 0 : bridge_flushrule(p);
251 0 : free(p, M_DEVBUF, sizeof *p);
252 :
253 0 : return (error);
254 : }
255 :
256 : int
257 0 : bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
258 : {
259 0 : struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
260 0 : struct ifbreq *req = (struct ifbreq *)data;
261 0 : struct ifbropreq *brop = (struct ifbropreq *)data;
262 : struct ifnet *ifs;
263 : struct bridge_iflist *p;
264 : struct bstp_port *bp;
265 0 : struct bstp_state *bs = sc->sc_stp;
266 : int error = 0;
267 :
268 0 : switch (cmd) {
269 : case SIOCBRDGADD:
270 : /* bridge(4) does not distinguish between routing/forwarding ports */
271 : case SIOCBRDGADDL:
272 0 : if ((error = suser(curproc)) != 0)
273 : break;
274 :
275 0 : ifs = ifunit(req->ifbr_ifsname);
276 :
277 : /* try to create the interface if it does't exist */
278 0 : if (ifs == NULL && if_clone_create(req->ifbr_ifsname, 0) == 0)
279 0 : ifs = ifunit(req->ifbr_ifsname);
280 :
281 0 : if (ifs == NULL) { /* no such interface */
282 : error = ENOENT;
283 0 : break;
284 : }
285 :
286 0 : if (ifs->if_bridgeport != NULL) {
287 0 : p = (struct bridge_iflist *)ifs->if_bridgeport;
288 0 : if (p->bridge_sc == sc)
289 0 : error = EEXIST;
290 : else
291 : error = EBUSY;
292 : break;
293 : }
294 :
295 : /* If it's in the span list, it can't be a member. */
296 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next)
297 0 : if (p->ifp == ifs)
298 : break;
299 0 : if (p != NULL) {
300 : error = EBUSY;
301 0 : break;
302 : }
303 :
304 0 : if (ifs->if_type == IFT_ETHER) {
305 0 : error = ifpromisc(ifs, 1);
306 0 : if (error != 0)
307 : break;
308 : }
309 : #if NMPW > 0
310 0 : else if (ifs->if_type == IFT_MPLSTUNNEL) {
311 : /* Nothing needed */
312 : }
313 : #endif /* NMPW */
314 : else {
315 : error = EINVAL;
316 0 : break;
317 : }
318 :
319 0 : p = malloc(sizeof(*p), M_DEVBUF, M_NOWAIT|M_ZERO);
320 0 : if (p == NULL) {
321 0 : if (ifs->if_type == IFT_ETHER)
322 0 : ifpromisc(ifs, 0);
323 : error = ENOMEM;
324 0 : break;
325 : }
326 :
327 0 : p->bridge_sc = sc;
328 0 : p->ifp = ifs;
329 0 : p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
330 0 : SIMPLEQ_INIT(&p->bif_brlin);
331 0 : SIMPLEQ_INIT(&p->bif_brlout);
332 0 : ifs->if_bridgeport = (caddr_t)p;
333 0 : p->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
334 0 : bridge_ifdetach, ifs);
335 0 : if_ih_insert(p->ifp, bridge_input, NULL);
336 0 : TAILQ_INSERT_TAIL(&sc->sc_iflist, p, next);
337 0 : break;
338 : case SIOCBRDGDEL:
339 0 : if ((error = suser(curproc)) != 0)
340 : break;
341 0 : ifs = ifunit(req->ifbr_ifsname);
342 0 : if (ifs == NULL) {
343 : error = ENOENT;
344 0 : break;
345 : }
346 0 : p = (struct bridge_iflist *)ifs->if_bridgeport;
347 0 : if (p == NULL || p->bridge_sc != sc) {
348 : error = ESRCH;
349 0 : break;
350 : }
351 0 : error = bridge_delete(sc, p);
352 0 : break;
353 : case SIOCBRDGIFS:
354 0 : error = bridge_bifconf(sc, (struct ifbifconf *)data);
355 0 : break;
356 : case SIOCBRDGADDS:
357 0 : if ((error = suser(curproc)) != 0)
358 : break;
359 0 : ifs = ifunit(req->ifbr_ifsname);
360 0 : if (ifs == NULL) { /* no such interface */
361 : error = ENOENT;
362 0 : break;
363 : }
364 0 : if (ifs->if_type != IFT_ETHER &&
365 0 : ifs->if_type != IFT_MPLSTUNNEL) {
366 : error = EINVAL;
367 0 : break;
368 : }
369 0 : if (ifs->if_bridgeport != NULL) {
370 : error = EBUSY;
371 0 : break;
372 : }
373 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
374 0 : if (p->ifp == ifs)
375 : break;
376 : }
377 0 : if (p != NULL) {
378 : error = EEXIST;
379 0 : break;
380 : }
381 0 : p = malloc(sizeof(*p), M_DEVBUF, M_NOWAIT|M_ZERO);
382 0 : if (p == NULL) {
383 : error = ENOMEM;
384 0 : break;
385 : }
386 0 : p->ifp = ifs;
387 0 : p->bif_flags = IFBIF_SPAN;
388 0 : p->bridge_sc = sc;
389 0 : p->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
390 : bridge_spandetach, p);
391 0 : SIMPLEQ_INIT(&p->bif_brlin);
392 0 : SIMPLEQ_INIT(&p->bif_brlout);
393 0 : TAILQ_INSERT_TAIL(&sc->sc_spanlist, p, next);
394 0 : break;
395 : case SIOCBRDGDELS:
396 0 : if ((error = suser(curproc)) != 0)
397 : break;
398 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
399 0 : if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
400 0 : sizeof(p->ifp->if_xname)) == 0) {
401 0 : bridge_spandetach(p);
402 0 : break;
403 : }
404 : }
405 0 : if (p == NULL) {
406 : error = ENOENT;
407 0 : break;
408 : }
409 : break;
410 : case SIOCBRDGGIFFLGS:
411 0 : ifs = ifunit(req->ifbr_ifsname);
412 0 : if (ifs == NULL) {
413 : error = ENOENT;
414 0 : break;
415 : }
416 0 : p = (struct bridge_iflist *)ifs->if_bridgeport;
417 0 : if (p == NULL || p->bridge_sc != sc) {
418 : error = ESRCH;
419 0 : break;
420 : }
421 0 : req->ifbr_ifsflags = p->bif_flags;
422 0 : req->ifbr_portno = p->ifp->if_index & 0xfff;
423 0 : req->ifbr_protected = p->bif_protected;
424 0 : if (p->bif_flags & IFBIF_STP) {
425 0 : bp = p->bif_stp;
426 0 : req->ifbr_state = bstp_getstate(bs, bp);
427 0 : req->ifbr_priority = bp->bp_priority;
428 0 : req->ifbr_path_cost = bp->bp_path_cost;
429 0 : req->ifbr_proto = bp->bp_protover;
430 0 : req->ifbr_role = bp->bp_role;
431 0 : req->ifbr_stpflags = bp->bp_flags;
432 0 : req->ifbr_fwd_trans = bp->bp_forward_transitions;
433 0 : req->ifbr_desg_bridge = bp->bp_desg_pv.pv_dbridge_id;
434 0 : req->ifbr_desg_port = bp->bp_desg_pv.pv_dport_id;
435 0 : req->ifbr_root_bridge = bp->bp_desg_pv.pv_root_id;
436 0 : req->ifbr_root_cost = bp->bp_desg_pv.pv_cost;
437 0 : req->ifbr_root_port = bp->bp_desg_pv.pv_port_id;
438 :
439 : /* Copy STP state options as flags */
440 0 : if (bp->bp_operedge)
441 0 : req->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
442 0 : if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
443 0 : req->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
444 0 : if (bp->bp_ptp_link)
445 0 : req->ifbr_ifsflags |= IFBIF_BSTP_PTP;
446 0 : if (bp->bp_flags & BSTP_PORT_AUTOPTP)
447 0 : req->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
448 : }
449 : break;
450 : case SIOCBRDGSIFFLGS:
451 0 : if ((error = suser(curproc)) != 0)
452 : break;
453 0 : ifs = ifunit(req->ifbr_ifsname);
454 0 : if (ifs == NULL) {
455 : error = ENOENT;
456 0 : break;
457 : }
458 0 : p = (struct bridge_iflist *)ifs->if_bridgeport;
459 0 : if (p == NULL || p->bridge_sc != sc) {
460 : error = ESRCH;
461 0 : break;
462 : }
463 0 : if (req->ifbr_ifsflags & IFBIF_RO_MASK) {
464 : error = EINVAL;
465 0 : break;
466 : }
467 0 : if (req->ifbr_ifsflags & IFBIF_STP) {
468 0 : if ((p->bif_flags & IFBIF_STP) == 0) {
469 : /* Enable STP */
470 0 : if ((p->bif_stp = bstp_add(sc->sc_stp,
471 0 : p->ifp)) == NULL) {
472 : error = ENOMEM;
473 0 : break;
474 : }
475 : } else {
476 : /* Update STP flags */
477 0 : bstp_ifsflags(p->bif_stp, req->ifbr_ifsflags);
478 : }
479 0 : } else if (p->bif_flags & IFBIF_STP) {
480 0 : bstp_delete(p->bif_stp);
481 0 : p->bif_stp = NULL;
482 0 : }
483 0 : p->bif_flags = req->ifbr_ifsflags;
484 0 : break;
485 : case SIOCSIFFLAGS:
486 0 : if ((ifp->if_flags & IFF_UP) == IFF_UP)
487 0 : bridge_init(sc);
488 :
489 0 : if ((ifp->if_flags & IFF_UP) == 0)
490 0 : bridge_stop(sc);
491 :
492 : break;
493 : case SIOCBRDGGPARAM:
494 0 : if ((bp = bs->bs_root_port) == NULL)
495 0 : brop->ifbop_root_port = 0;
496 : else
497 0 : brop->ifbop_root_port = bp->bp_ifp->if_index;
498 0 : brop->ifbop_maxage = bs->bs_bridge_max_age >> 8;
499 0 : brop->ifbop_hellotime = bs->bs_bridge_htime >> 8;
500 0 : brop->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8;
501 0 : brop->ifbop_holdcount = bs->bs_txholdcount;
502 0 : brop->ifbop_priority = bs->bs_bridge_priority;
503 0 : brop->ifbop_protocol = bs->bs_protover;
504 0 : brop->ifbop_root_bridge = bs->bs_root_pv.pv_root_id;
505 0 : brop->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
506 0 : brop->ifbop_root_port = bs->bs_root_pv.pv_port_id;
507 0 : brop->ifbop_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
508 0 : brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
509 0 : brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
510 0 : break;
511 : case SIOCBRDGSIFPROT:
512 0 : ifs = ifunit(req->ifbr_ifsname);
513 0 : if (ifs == NULL) {
514 : error = ENOENT;
515 0 : break;
516 : }
517 0 : p = (struct bridge_iflist *)ifs->if_bridgeport;
518 0 : if (p == NULL || p->bridge_sc != sc) {
519 : error = ESRCH;
520 0 : break;
521 : }
522 0 : p->bif_protected = req->ifbr_protected;
523 0 : break;
524 : case SIOCBRDGRTS:
525 : case SIOCBRDGGCACHE:
526 : case SIOCBRDGGPRI:
527 : case SIOCBRDGGMA:
528 : case SIOCBRDGGHT:
529 : case SIOCBRDGGFD:
530 : case SIOCBRDGGTO:
531 : case SIOCBRDGGRL:
532 : break;
533 : case SIOCBRDGFLUSH:
534 : case SIOCBRDGSADDR:
535 : case SIOCBRDGDADDR:
536 : case SIOCBRDGSCACHE:
537 : case SIOCBRDGSTO:
538 : case SIOCBRDGARL:
539 : case SIOCBRDGFRL:
540 : case SIOCBRDGSPRI:
541 : case SIOCBRDGSFD:
542 : case SIOCBRDGSMA:
543 : case SIOCBRDGSHT:
544 : case SIOCBRDGSTXHC:
545 : case SIOCBRDGSPROTO:
546 : case SIOCBRDGSIFPRIO:
547 : case SIOCBRDGSIFCOST:
548 0 : error = suser(curproc);
549 0 : break;
550 : default:
551 : error = ENOTTY;
552 0 : break;
553 : }
554 :
555 0 : if (!error)
556 0 : error = bridgectl_ioctl(ifp, cmd, data);
557 :
558 0 : if (!error)
559 0 : error = bstp_ioctl(ifp, cmd, data);
560 :
561 0 : return (error);
562 : }
563 :
564 : /* Detach an interface from a bridge. */
565 : void
566 0 : bridge_ifdetach(void *arg)
567 : {
568 0 : struct ifnet *ifp = (struct ifnet *)arg;
569 : struct bridge_softc *sc;
570 : struct bridge_iflist *bif;
571 :
572 0 : bif = (struct bridge_iflist *)ifp->if_bridgeport;
573 0 : sc = bif->bridge_sc;
574 :
575 0 : bridge_delete(sc, bif);
576 0 : }
577 :
578 : void
579 0 : bridge_spandetach(void *arg)
580 : {
581 0 : struct bridge_iflist *p = (struct bridge_iflist *)arg;
582 0 : struct bridge_softc *sc = p->bridge_sc;
583 :
584 0 : hook_disestablish(p->ifp->if_detachhooks, p->bif_dhcookie);
585 0 : TAILQ_REMOVE(&sc->sc_spanlist, p, next);
586 0 : free(p, M_DEVBUF, sizeof(*p));
587 0 : }
588 :
589 : int
590 0 : bridge_bifconf(struct bridge_softc *sc, struct ifbifconf *bifc)
591 : {
592 : struct bridge_iflist *p;
593 : struct bstp_port *bp;
594 0 : struct bstp_state *bs = sc->sc_stp;
595 : u_int32_t total = 0, i = 0;
596 : int error = 0;
597 : struct ifbreq *breq = NULL;
598 :
599 0 : TAILQ_FOREACH(p, &sc->sc_iflist, next)
600 0 : total++;
601 :
602 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next)
603 0 : total++;
604 :
605 0 : if (bifc->ifbic_len == 0) {
606 : i = total;
607 0 : goto done;
608 : }
609 :
610 0 : if ((breq = (struct ifbreq *)
611 0 : malloc(sizeof(*breq), M_DEVBUF, M_NOWAIT)) == NULL)
612 : goto done;
613 :
614 0 : TAILQ_FOREACH(p, &sc->sc_iflist, next) {
615 0 : bzero(breq, sizeof(*breq));
616 0 : if (bifc->ifbic_len < sizeof(*breq))
617 : break;
618 0 : strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
619 0 : strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
620 0 : breq->ifbr_ifsflags = p->bif_flags;
621 0 : breq->ifbr_portno = p->ifp->if_index & 0xfff;
622 0 : breq->ifbr_protected = p->bif_protected;
623 0 : if (p->bif_flags & IFBIF_STP) {
624 0 : bp = p->bif_stp;
625 0 : breq->ifbr_state = bstp_getstate(sc->sc_stp, bp);
626 0 : breq->ifbr_priority = bp->bp_priority;
627 0 : breq->ifbr_path_cost = bp->bp_path_cost;
628 0 : breq->ifbr_proto = bp->bp_protover;
629 0 : breq->ifbr_role = bp->bp_role;
630 0 : breq->ifbr_stpflags = bp->bp_flags;
631 0 : breq->ifbr_fwd_trans = bp->bp_forward_transitions;
632 0 : breq->ifbr_root_bridge = bs->bs_root_pv.pv_root_id;
633 0 : breq->ifbr_root_cost = bs->bs_root_pv.pv_cost;
634 0 : breq->ifbr_root_port = bs->bs_root_pv.pv_port_id;
635 0 : breq->ifbr_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
636 0 : breq->ifbr_desg_port = bs->bs_root_pv.pv_dport_id;
637 :
638 : /* Copy STP state options as flags */
639 0 : if (bp->bp_operedge)
640 0 : breq->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
641 0 : if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
642 0 : breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
643 0 : if (bp->bp_ptp_link)
644 0 : breq->ifbr_ifsflags |= IFBIF_BSTP_PTP;
645 0 : if (bp->bp_flags & BSTP_PORT_AUTOPTP)
646 0 : breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
647 : }
648 0 : error = copyout((caddr_t)breq,
649 0 : (caddr_t)(bifc->ifbic_req + i), sizeof(*breq));
650 0 : if (error)
651 : goto done;
652 0 : i++;
653 0 : bifc->ifbic_len -= sizeof(*breq);
654 : }
655 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
656 0 : bzero(breq, sizeof(*breq));
657 0 : if (bifc->ifbic_len < sizeof(*breq))
658 : break;
659 0 : strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
660 0 : strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
661 0 : breq->ifbr_ifsflags = p->bif_flags | IFBIF_SPAN;
662 0 : breq->ifbr_portno = p->ifp->if_index & 0xfff;
663 0 : error = copyout((caddr_t)breq,
664 0 : (caddr_t)(bifc->ifbic_req + i), sizeof(*breq));
665 0 : if (error)
666 : goto done;
667 0 : i++;
668 0 : bifc->ifbic_len -= sizeof(*breq);
669 : }
670 :
671 : done:
672 0 : if (breq != NULL)
673 0 : free(breq, M_DEVBUF, sizeof *breq);
674 0 : bifc->ifbic_len = i * sizeof(*breq);
675 0 : return (error);
676 : }
677 :
678 : void
679 0 : bridge_init(struct bridge_softc *sc)
680 : {
681 0 : struct ifnet *ifp = &sc->sc_if;
682 :
683 0 : if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
684 0 : return;
685 :
686 0 : ifp->if_flags |= IFF_RUNNING;
687 0 : bstp_initialization(sc->sc_stp);
688 :
689 0 : if (sc->sc_brttimeout != 0)
690 0 : timeout_add_sec(&sc->sc_brtimeout, sc->sc_brttimeout);
691 0 : }
692 :
693 : /*
694 : * Stop the bridge and deallocate the routing table.
695 : */
696 : void
697 0 : bridge_stop(struct bridge_softc *sc)
698 : {
699 0 : struct ifnet *ifp = &sc->sc_if;
700 :
701 : /*
702 : * If we're not running, there's nothing to do.
703 : */
704 0 : if ((ifp->if_flags & IFF_RUNNING) == 0)
705 0 : return;
706 :
707 0 : timeout_del(&sc->sc_brtimeout);
708 :
709 0 : bridge_rtflush(sc, IFBF_FLUSHDYN);
710 :
711 0 : ifp->if_flags &= ~IFF_RUNNING;
712 0 : }
713 :
714 : /*
715 : * Send output from the bridge. The mbuf has the ethernet header
716 : * already attached. We must enqueue or free the mbuf before exiting.
717 : */
718 : int
719 0 : bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
720 : struct rtentry *rt)
721 : {
722 : struct ether_header *eh;
723 : struct ifnet *dst_if = NULL;
724 : struct bridge_rtnode *dst_p = NULL;
725 : struct ether_addr *dst;
726 : struct bridge_softc *sc;
727 : struct bridge_tunneltag *brtag;
728 : struct bridge_iflist *ifl;
729 : int error;
730 :
731 : /* ifp must be a member interface of the bridge. */
732 0 : if (ifp->if_bridgeport == NULL) {
733 0 : m_freem(m);
734 0 : return (EINVAL);
735 : }
736 0 : sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc;
737 :
738 0 : if (m->m_len < sizeof(*eh)) {
739 0 : m = m_pullup(m, sizeof(*eh));
740 0 : if (m == NULL)
741 0 : return (ENOBUFS);
742 : }
743 0 : eh = mtod(m, struct ether_header *);
744 0 : dst = (struct ether_addr *)&eh->ether_dhost[0];
745 :
746 : /*
747 : * If bridge is down, but original output interface is up,
748 : * go ahead and send out that interface. Otherwise the packet
749 : * is dropped below.
750 : */
751 0 : if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
752 : dst_if = ifp;
753 0 : goto sendunicast;
754 : }
755 :
756 : #if NBPFILTER > 0
757 0 : if (sc->sc_if.if_bpf)
758 0 : bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT);
759 : #endif
760 0 : ifp->if_opackets++;
761 0 : ifp->if_obytes += m->m_pkthdr.len;
762 :
763 : /*
764 : * If the packet is a broadcast or we don't know a better way to
765 : * get there, send to all interfaces.
766 : */
767 0 : if ((dst_p = bridge_rtlookup(sc, dst)) != NULL)
768 0 : dst_if = dst_p->brt_if;
769 0 : if (dst_if == NULL || ETHER_IS_MULTICAST(eh->ether_dhost)) {
770 : struct bridge_iflist *p;
771 : struct mbuf *mc;
772 : int used = 0;
773 :
774 0 : bridge_span(sc, m);
775 :
776 0 : TAILQ_FOREACH(p, &sc->sc_iflist, next) {
777 0 : dst_if = p->ifp;
778 0 : if ((dst_if->if_flags & IFF_RUNNING) == 0)
779 : continue;
780 :
781 : /*
782 : * If this is not the original output interface,
783 : * and the interface is participating in spanning
784 : * tree, make sure the port is in a state that
785 : * allows forwarding.
786 : */
787 0 : if (dst_if != ifp &&
788 0 : (p->bif_flags & IFBIF_STP) &&
789 0 : (p->bif_state == BSTP_IFSTATE_DISCARDING))
790 : continue;
791 : #if NMPW > 0
792 : /*
793 : * Split horizon: avoid broadcasting messages from
794 : * wire to another wire.
795 : */
796 0 : if (ifp->if_type == IFT_MPLSTUNNEL &&
797 0 : dst_if->if_type == IFT_MPLSTUNNEL)
798 : continue;
799 : #endif /* NMPW */
800 0 : if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
801 0 : (m->m_flags & (M_BCAST | M_MCAST)) == 0)
802 : continue;
803 :
804 0 : if (TAILQ_NEXT(p, next) == NULL) {
805 : used = 1;
806 : mc = m;
807 0 : } else {
808 0 : mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
809 0 : if (mc == NULL) {
810 0 : sc->sc_if.if_oerrors++;
811 0 : continue;
812 : }
813 : }
814 :
815 0 : ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
816 0 : KASSERT(ifl != NULL);
817 0 : if (bridge_filterrule(&ifl->bif_brlout, eh, mc) ==
818 : BRL_ACTION_BLOCK)
819 : continue;
820 :
821 0 : error = bridge_ifenqueue(sc, dst_if, mc);
822 : if (error)
823 0 : continue;
824 : }
825 0 : if (!used)
826 0 : m_freem(m);
827 : return (0);
828 : }
829 :
830 : sendunicast:
831 0 : if ((dst_p != NULL) &&
832 0 : (dst_p->brt_tunnel.brtag_peer.sa.sa_family != AF_UNSPEC) &&
833 0 : ((brtag = bridge_tunneltag(m)) != NULL))
834 0 : bridge_copytag(&dst_p->brt_tunnel, brtag);
835 :
836 0 : bridge_span(sc, m);
837 0 : if ((dst_if->if_flags & IFF_RUNNING) == 0) {
838 0 : m_freem(m);
839 0 : return (ENETDOWN);
840 : }
841 0 : bridge_ifenqueue(sc, dst_if, m);
842 0 : return (0);
843 0 : }
844 :
845 : /*
846 : * Loop through each bridge interface and process their input queues.
847 : */
848 : void
849 0 : bridgeintr(void)
850 : {
851 0 : struct mbuf_list ml;
852 : struct mbuf *m;
853 : struct ifnet *ifp;
854 :
855 0 : niq_delist(&bridgeintrq, &ml);
856 0 : if (ml_empty(&ml))
857 0 : return;
858 :
859 0 : while ((m = ml_dequeue(&ml)) != NULL) {
860 :
861 0 : ifp = if_get(m->m_pkthdr.ph_ifidx);
862 0 : if (ifp == NULL) {
863 0 : m_freem(m);
864 0 : continue;
865 : }
866 :
867 0 : bridge_process(ifp, m);
868 :
869 0 : if_put(ifp);
870 : }
871 0 : }
872 :
873 : /*
874 : * Process a single frame. Frame must be freed or queued before returning.
875 : */
876 : void
877 0 : bridgeintr_frame(struct bridge_softc *sc, struct ifnet *src_if, struct mbuf *m)
878 : {
879 : struct ifnet *dst_if;
880 : struct bridge_iflist *ifl;
881 : struct bridge_rtnode *dst_p;
882 : struct ether_addr *dst, *src;
883 0 : struct ether_header eh;
884 : u_int32_t protected;
885 : int len;
886 :
887 :
888 0 : sc->sc_if.if_ipackets++;
889 0 : sc->sc_if.if_ibytes += m->m_pkthdr.len;
890 :
891 0 : ifl = (struct bridge_iflist *)src_if->if_bridgeport;
892 0 : KASSERT(ifl != NULL);
893 :
894 0 : if (m->m_pkthdr.len < sizeof(eh)) {
895 0 : m_freem(m);
896 0 : return;
897 : }
898 0 : m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&eh);
899 0 : dst = (struct ether_addr *)&eh.ether_dhost[0];
900 0 : src = (struct ether_addr *)&eh.ether_shost[0];
901 :
902 : /*
903 : * If interface is learning, and if source address
904 : * is not broadcast or multicast, record its address.
905 : */
906 0 : if ((ifl->bif_flags & IFBIF_LEARNING) &&
907 0 : (eh.ether_shost[0] & 1) == 0 &&
908 0 : !(eh.ether_shost[0] == 0 && eh.ether_shost[1] == 0 &&
909 0 : eh.ether_shost[2] == 0 && eh.ether_shost[3] == 0 &&
910 0 : eh.ether_shost[4] == 0 && eh.ether_shost[5] == 0))
911 0 : bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC, m);
912 :
913 0 : if ((ifl->bif_flags & IFBIF_STP) &&
914 0 : (ifl->bif_state == BSTP_IFSTATE_LEARNING)) {
915 0 : m_freem(m);
916 0 : return;
917 : }
918 :
919 : /*
920 : * At this point, the port either doesn't participate in stp or
921 : * it's in the forwarding state
922 : */
923 :
924 : /*
925 : * If packet is unicast, destined for someone on "this"
926 : * side of the bridge, drop it.
927 : */
928 0 : if (!ETHER_IS_MULTICAST(eh.ether_dhost)) {
929 0 : if ((dst_p = bridge_rtlookup(sc, dst)) != NULL)
930 0 : dst_if = dst_p->brt_if;
931 : else
932 : dst_if = NULL;
933 0 : if (dst_if == src_if) {
934 0 : m_freem(m);
935 0 : return;
936 : }
937 : } else {
938 0 : if (memcmp(etherbroadcastaddr, eh.ether_dhost,
939 0 : sizeof(etherbroadcastaddr)) == 0)
940 0 : m->m_flags |= M_BCAST;
941 : else
942 0 : m->m_flags |= M_MCAST;
943 : dst_if = NULL;
944 : }
945 :
946 : /*
947 : * Multicast packets get handled a little differently:
948 : * If interface is:
949 : * -link0,-link1 (default) Forward all multicast
950 : * as broadcast.
951 : * -link0,link1 Drop non-IP multicast, forward
952 : * as broadcast IP multicast.
953 : * link0,-link1 Drop IP multicast, forward as
954 : * broadcast non-IP multicast.
955 : * link0,link1 Drop all multicast.
956 : */
957 0 : if (m->m_flags & M_MCAST) {
958 0 : if ((sc->sc_if.if_flags &
959 0 : (IFF_LINK0 | IFF_LINK1)) ==
960 : (IFF_LINK0 | IFF_LINK1)) {
961 0 : m_freem(m);
962 0 : return;
963 : }
964 0 : if (sc->sc_if.if_flags & IFF_LINK0 &&
965 0 : ETHERADDR_IS_IP_MCAST(dst)) {
966 0 : m_freem(m);
967 0 : return;
968 : }
969 0 : if (sc->sc_if.if_flags & IFF_LINK1 &&
970 0 : !ETHERADDR_IS_IP_MCAST(dst)) {
971 0 : m_freem(m);
972 0 : return;
973 : }
974 : }
975 :
976 0 : if (ifl->bif_flags & IFBIF_BLOCKNONIP && bridge_blocknonip(&eh, m)) {
977 0 : m_freem(m);
978 0 : return;
979 : }
980 :
981 0 : if (bridge_filterrule(&ifl->bif_brlin, &eh, m) == BRL_ACTION_BLOCK) {
982 0 : m_freem(m);
983 0 : return;
984 : }
985 0 : m = bridge_ip(sc, BRIDGE_IN, src_if, &eh, m);
986 0 : if (m == NULL)
987 0 : return;
988 : /*
989 : * If the packet is a multicast or broadcast OR if we don't
990 : * know any better, forward it to all interfaces.
991 : */
992 0 : if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) {
993 0 : sc->sc_if.if_imcasts++;
994 0 : bridge_broadcast(sc, src_if, &eh, m);
995 0 : return;
996 : }
997 0 : protected = ifl->bif_protected;
998 :
999 : /*
1000 : * At this point, we're dealing with a unicast frame going to a
1001 : * different interface
1002 : */
1003 0 : if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1004 0 : m_freem(m);
1005 0 : return;
1006 : }
1007 0 : ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
1008 0 : if ((ifl->bif_flags & IFBIF_STP) &&
1009 0 : (ifl->bif_state == BSTP_IFSTATE_DISCARDING)) {
1010 0 : m_freem(m);
1011 0 : return;
1012 : }
1013 : /*
1014 : * Do not transmit if both ports are part of the same protected
1015 : * domain.
1016 : */
1017 0 : if (protected != 0 && (protected & ifl->bif_protected)) {
1018 0 : m_freem(m);
1019 0 : return;
1020 : }
1021 0 : if (bridge_filterrule(&ifl->bif_brlout, &eh, m) == BRL_ACTION_BLOCK) {
1022 0 : m_freem(m);
1023 0 : return;
1024 : }
1025 0 : m = bridge_ip(sc, BRIDGE_OUT, dst_if, &eh, m);
1026 0 : if (m == NULL)
1027 0 : return;
1028 :
1029 0 : len = m->m_pkthdr.len;
1030 : #if NVLAN > 0
1031 0 : if ((m->m_flags & M_VLANTAG) &&
1032 0 : (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
1033 0 : len += ETHER_VLAN_ENCAP_LEN;
1034 : #endif
1035 0 : if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
1036 0 : bridge_fragment(sc, dst_if, &eh, m);
1037 : else {
1038 0 : bridge_ifenqueue(sc, dst_if, m);
1039 : }
1040 0 : }
1041 :
1042 : /*
1043 : * Return 1 if `ena' belongs to `ifl', 0 otherwise.
1044 : */
1045 : int
1046 0 : bridge_ourether(struct bridge_iflist *ifl, uint8_t *ena)
1047 : {
1048 0 : struct arpcom *ac = (struct arpcom *)ifl->ifp;
1049 :
1050 0 : if (memcmp(ac->ac_enaddr, ena, ETHER_ADDR_LEN) == 0)
1051 0 : return (1);
1052 :
1053 : #if NCARP > 0
1054 0 : if (carp_ourether(ifl->ifp, ena))
1055 0 : return (1);
1056 : #endif
1057 :
1058 0 : return (0);
1059 0 : }
1060 :
1061 : /*
1062 : * Receive input from an interface. Queue the packet for bridging if its
1063 : * not for us, and schedule an interrupt.
1064 : */
1065 : int
1066 0 : bridge_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
1067 : {
1068 0 : KASSERT(m->m_flags & M_PKTHDR);
1069 :
1070 0 : if (m->m_flags & M_PROTO1) {
1071 0 : m->m_flags &= ~M_PROTO1;
1072 0 : return (0);
1073 : }
1074 :
1075 0 : niq_enqueue(&bridgeintrq, m);
1076 :
1077 0 : return (1);
1078 0 : }
1079 :
1080 : void
1081 0 : bridge_process(struct ifnet *ifp, struct mbuf *m)
1082 : {
1083 : struct bridge_softc *sc;
1084 : struct bridge_iflist *ifl;
1085 : struct bridge_iflist *srcifl;
1086 : struct ether_header *eh;
1087 : struct mbuf *mc;
1088 :
1089 0 : ifl = (struct bridge_iflist *)ifp->if_bridgeport;
1090 0 : if (ifl == NULL)
1091 : goto reenqueue;
1092 :
1093 0 : sc = ifl->bridge_sc;
1094 0 : if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1095 : goto reenqueue;
1096 :
1097 : #if NVLAN > 0
1098 : /*
1099 : * If the underlying interface removed the VLAN header itself,
1100 : * add it back.
1101 : */
1102 0 : if (ISSET(m->m_flags, M_VLANTAG)) {
1103 0 : m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag);
1104 0 : if (m == NULL)
1105 0 : return;
1106 : }
1107 : #endif
1108 :
1109 : #if NBPFILTER > 0
1110 0 : if (sc->sc_if.if_bpf)
1111 0 : bpf_mtap_ether(sc->sc_if.if_bpf, m, BPF_DIRECTION_IN);
1112 : #endif
1113 :
1114 0 : bridge_span(sc, m);
1115 :
1116 0 : eh = mtod(m, struct ether_header *);
1117 0 : if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
1118 : /*
1119 : * Reserved destination MAC addresses (01:80:C2:00:00:0x)
1120 : * should not be forwarded to bridge members according to
1121 : * section 7.12.6 of the 802.1D-2004 specification. The
1122 : * STP destination address (as stored in bstp_etheraddr)
1123 : * is the first of these.
1124 : */
1125 0 : if (memcmp(eh->ether_dhost, bstp_etheraddr,
1126 0 : ETHER_ADDR_LEN - 1) == 0) {
1127 0 : if (eh->ether_dhost[ETHER_ADDR_LEN - 1] == 0) {
1128 : /* STP traffic */
1129 0 : if ((m = bstp_input(sc->sc_stp, ifl->bif_stp,
1130 0 : eh, m)) == NULL)
1131 0 : return;
1132 0 : } else if (eh->ether_dhost[ETHER_ADDR_LEN - 1] <= 0xf) {
1133 0 : m_freem(m);
1134 0 : return;
1135 : }
1136 : }
1137 :
1138 : /*
1139 : * No need to process frames for ifs in the discarding state
1140 : */
1141 0 : if ((ifl->bif_flags & IFBIF_STP) &&
1142 0 : (ifl->bif_state == BSTP_IFSTATE_DISCARDING))
1143 : goto reenqueue;
1144 :
1145 0 : mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
1146 0 : if (mc == NULL)
1147 : goto reenqueue;
1148 :
1149 0 : bridge_ifinput(ifp, mc);
1150 :
1151 0 : bridgeintr_frame(sc, ifp, m);
1152 0 : return;
1153 : }
1154 :
1155 : /*
1156 : * No need to queue frames for ifs in the discarding state
1157 : */
1158 0 : if ((ifl->bif_flags & IFBIF_STP) &&
1159 0 : (ifl->bif_state == BSTP_IFSTATE_DISCARDING))
1160 : goto reenqueue;
1161 :
1162 : /*
1163 : * Unicast, make sure it's not for us.
1164 : */
1165 : srcifl = ifl;
1166 0 : TAILQ_FOREACH(ifl, &sc->sc_iflist, next) {
1167 0 : if (ifl->ifp->if_type != IFT_ETHER)
1168 : continue;
1169 0 : if (bridge_ourether(ifl, eh->ether_dhost)) {
1170 0 : if (srcifl->bif_flags & IFBIF_LEARNING)
1171 0 : bridge_rtupdate(sc,
1172 0 : (struct ether_addr *)&eh->ether_shost,
1173 : ifp, 0, IFBAF_DYNAMIC, m);
1174 0 : if (bridge_filterrule(&srcifl->bif_brlin, eh, m) ==
1175 : BRL_ACTION_BLOCK) {
1176 0 : m_freem(m);
1177 0 : return;
1178 : }
1179 :
1180 : /* Count for the bridge */
1181 0 : sc->sc_if.if_ipackets++;
1182 0 : sc->sc_if.if_ibytes += m->m_pkthdr.len;
1183 :
1184 0 : bridge_ifinput(ifl->ifp, m);
1185 0 : return;
1186 : }
1187 0 : if (bridge_ourether(ifl, eh->ether_shost)) {
1188 0 : m_freem(m);
1189 0 : return;
1190 : }
1191 : }
1192 :
1193 0 : bridgeintr_frame(sc, ifp, m);
1194 0 : return;
1195 :
1196 : reenqueue:
1197 0 : bridge_ifinput(ifp, m);
1198 0 : }
1199 :
1200 : /*
1201 : * Send a frame to all interfaces that are members of the bridge
1202 : * (except the one it came in on).
1203 : */
1204 : void
1205 0 : bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
1206 : struct ether_header *eh, struct mbuf *m)
1207 : {
1208 : struct bridge_iflist *p;
1209 : struct mbuf *mc;
1210 : struct ifnet *dst_if;
1211 : int len, used = 0;
1212 : u_int32_t protected;
1213 :
1214 0 : p = (struct bridge_iflist *)ifp->if_bridgeport;
1215 0 : protected = p->bif_protected;
1216 :
1217 0 : TAILQ_FOREACH(p, &sc->sc_iflist, next) {
1218 0 : dst_if = p->ifp;
1219 :
1220 0 : if ((dst_if->if_flags & IFF_RUNNING) == 0)
1221 : continue;
1222 :
1223 0 : if ((p->bif_flags & IFBIF_STP) &&
1224 0 : (p->bif_state == BSTP_IFSTATE_DISCARDING))
1225 : continue;
1226 :
1227 0 : if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
1228 0 : (m->m_flags & (M_BCAST | M_MCAST)) == 0)
1229 : continue;
1230 :
1231 : /* Drop non-IP frames if the appropriate flag is set. */
1232 0 : if (p->bif_flags & IFBIF_BLOCKNONIP &&
1233 0 : bridge_blocknonip(eh, m))
1234 : continue;
1235 :
1236 : /*
1237 : * Do not transmit if both ports are part of the same
1238 : * protected domain.
1239 : */
1240 0 : if (protected != 0 && (protected & p->bif_protected))
1241 : continue;
1242 :
1243 0 : if (bridge_filterrule(&p->bif_brlout, eh, m) == BRL_ACTION_BLOCK)
1244 : continue;
1245 :
1246 : /*
1247 : * Don't retransmit out of the same interface where
1248 : * the packet was received from.
1249 : */
1250 0 : if (dst_if->if_index == ifp->if_index)
1251 : continue;
1252 :
1253 0 : bridge_localbroadcast(sc, dst_if, eh, m);
1254 :
1255 : #if NMPW > 0
1256 : /*
1257 : * Split horizon: avoid broadcasting messages from wire to
1258 : * another wire.
1259 : */
1260 0 : if (ifp->if_type == IFT_MPLSTUNNEL &&
1261 0 : dst_if->if_type == IFT_MPLSTUNNEL)
1262 : continue;
1263 : #endif /* NMPW */
1264 :
1265 : /* If last one, reuse the passed-in mbuf */
1266 0 : if (TAILQ_NEXT(p, next) == NULL) {
1267 : mc = m;
1268 : used = 1;
1269 0 : } else {
1270 0 : mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
1271 0 : if (mc == NULL) {
1272 0 : sc->sc_if.if_oerrors++;
1273 0 : continue;
1274 : }
1275 : }
1276 :
1277 0 : mc = bridge_ip(sc, BRIDGE_OUT, dst_if, eh, mc);
1278 0 : if (mc == NULL)
1279 : continue;
1280 :
1281 0 : len = mc->m_pkthdr.len;
1282 : #if NVLAN > 0
1283 0 : if ((mc->m_flags & M_VLANTAG) &&
1284 0 : (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
1285 0 : len += ETHER_VLAN_ENCAP_LEN;
1286 : #endif
1287 0 : if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
1288 0 : bridge_fragment(sc, dst_if, eh, mc);
1289 : else {
1290 0 : bridge_ifenqueue(sc, dst_if, mc);
1291 : }
1292 : }
1293 :
1294 0 : if (!used)
1295 0 : m_freem(m);
1296 0 : }
1297 :
1298 : void
1299 0 : bridge_localbroadcast(struct bridge_softc *sc, struct ifnet *ifp,
1300 : struct ether_header *eh, struct mbuf *m)
1301 : {
1302 : struct mbuf *m1;
1303 : u_int16_t etype;
1304 :
1305 : /*
1306 : * quick optimisation, don't send packets up the stack if no
1307 : * corresponding address has been specified.
1308 : */
1309 0 : etype = ntohs(eh->ether_type);
1310 0 : if (!(m->m_flags & M_VLANTAG) && etype == ETHERTYPE_IP) {
1311 : struct ifaddr *ifa;
1312 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1313 0 : if (ifa->ifa_addr->sa_family == AF_INET)
1314 : break;
1315 : }
1316 0 : if (ifa == NULL)
1317 0 : return;
1318 0 : }
1319 :
1320 0 : m1 = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
1321 0 : if (m1 == NULL) {
1322 0 : sc->sc_if.if_oerrors++;
1323 0 : return;
1324 : }
1325 :
1326 : #if NPF > 0
1327 0 : pf_pkt_addr_changed(m1);
1328 : #endif /* NPF */
1329 :
1330 0 : bridge_ifinput(ifp, m1);
1331 0 : }
1332 :
1333 : void
1334 0 : bridge_span(struct bridge_softc *sc, struct mbuf *m)
1335 : {
1336 : struct bridge_iflist *p;
1337 : struct ifnet *ifp;
1338 : struct mbuf *mc;
1339 : int error;
1340 :
1341 0 : TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
1342 0 : ifp = p->ifp;
1343 :
1344 0 : if ((ifp->if_flags & IFF_RUNNING) == 0)
1345 : continue;
1346 :
1347 0 : mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1348 0 : if (mc == NULL) {
1349 0 : sc->sc_if.if_oerrors++;
1350 0 : continue;
1351 : }
1352 :
1353 0 : error = bridge_ifenqueue(sc, ifp, mc);
1354 : if (error)
1355 0 : continue;
1356 : }
1357 0 : }
1358 :
1359 : /*
1360 : * Block non-ip frames:
1361 : * Returns 0 if frame is ip, and 1 if it should be dropped.
1362 : */
1363 : int
1364 0 : bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
1365 : {
1366 0 : struct llc llc;
1367 : u_int16_t etype;
1368 :
1369 0 : if (m->m_pkthdr.len < ETHER_HDR_LEN)
1370 0 : return (1);
1371 :
1372 : #if NVLAN > 0
1373 0 : if (m->m_flags & M_VLANTAG)
1374 0 : return (1);
1375 : #endif
1376 :
1377 0 : etype = ntohs(eh->ether_type);
1378 0 : switch (etype) {
1379 : case ETHERTYPE_ARP:
1380 : case ETHERTYPE_REVARP:
1381 : case ETHERTYPE_IP:
1382 : case ETHERTYPE_IPV6:
1383 0 : return (0);
1384 : }
1385 :
1386 0 : if (etype > ETHERMTU)
1387 0 : return (1);
1388 :
1389 0 : if (m->m_pkthdr.len <
1390 : (ETHER_HDR_LEN + LLC_SNAPFRAMELEN))
1391 0 : return (1);
1392 :
1393 0 : m_copydata(m, ETHER_HDR_LEN, LLC_SNAPFRAMELEN,
1394 : (caddr_t)&llc);
1395 :
1396 0 : etype = ntohs(llc.llc_snap.ether_type);
1397 0 : if (llc.llc_dsap == LLC_SNAP_LSAP &&
1398 0 : llc.llc_ssap == LLC_SNAP_LSAP &&
1399 0 : llc.llc_control == LLC_UI &&
1400 0 : llc.llc_snap.org_code[0] == 0 &&
1401 0 : llc.llc_snap.org_code[1] == 0 &&
1402 0 : llc.llc_snap.org_code[2] == 0 &&
1403 0 : (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
1404 0 : etype == ETHERTYPE_IP || etype == ETHERTYPE_IPV6)) {
1405 0 : return (0);
1406 : }
1407 :
1408 0 : return (1);
1409 0 : }
1410 :
1411 : #ifdef IPSEC
1412 : int
1413 0 : bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
1414 : struct ether_header *eh, int hassnap, struct llc *llc,
1415 : int dir, int af, int hlen, struct mbuf *m)
1416 : {
1417 0 : union sockaddr_union dst;
1418 : struct tdb *tdb;
1419 0 : u_int32_t spi;
1420 0 : u_int16_t cpi;
1421 0 : int error, off;
1422 : u_int8_t proto = 0;
1423 : struct ip *ip;
1424 : #ifdef INET6
1425 : struct ip6_hdr *ip6;
1426 : #endif /* INET6 */
1427 : #if NPF > 0
1428 : struct ifnet *encif;
1429 : #endif
1430 :
1431 0 : if (dir == BRIDGE_IN) {
1432 0 : switch (af) {
1433 : case AF_INET:
1434 0 : if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1435 : goto skiplookup;
1436 :
1437 0 : ip = mtod(m, struct ip *);
1438 0 : proto = ip->ip_p;
1439 : off = offsetof(struct ip, ip_p);
1440 :
1441 0 : if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
1442 0 : proto != IPPROTO_IPCOMP)
1443 : goto skiplookup;
1444 :
1445 0 : bzero(&dst, sizeof(union sockaddr_union));
1446 0 : dst.sa.sa_family = AF_INET;
1447 0 : dst.sin.sin_len = sizeof(struct sockaddr_in);
1448 0 : m_copydata(m, offsetof(struct ip, ip_dst),
1449 : sizeof(struct in_addr),
1450 0 : (caddr_t)&dst.sin.sin_addr);
1451 :
1452 0 : break;
1453 : #ifdef INET6
1454 : case AF_INET6:
1455 0 : if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
1456 : goto skiplookup;
1457 :
1458 0 : ip6 = mtod(m, struct ip6_hdr *);
1459 :
1460 : /* XXX We should chase down the header chain */
1461 0 : proto = ip6->ip6_nxt;
1462 : off = offsetof(struct ip6_hdr, ip6_nxt);
1463 :
1464 0 : if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
1465 0 : proto != IPPROTO_IPCOMP)
1466 : goto skiplookup;
1467 :
1468 0 : bzero(&dst, sizeof(union sockaddr_union));
1469 0 : dst.sa.sa_family = AF_INET6;
1470 0 : dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
1471 0 : m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
1472 : sizeof(struct in6_addr),
1473 0 : (caddr_t)&dst.sin6.sin6_addr);
1474 :
1475 0 : break;
1476 : #endif /* INET6 */
1477 : default:
1478 0 : return (0);
1479 : }
1480 :
1481 0 : switch (proto) {
1482 : case IPPROTO_ESP:
1483 0 : m_copydata(m, hlen, sizeof(u_int32_t), (caddr_t)&spi);
1484 0 : break;
1485 : case IPPROTO_AH:
1486 0 : m_copydata(m, hlen + sizeof(u_int32_t),
1487 : sizeof(u_int32_t), (caddr_t)&spi);
1488 0 : break;
1489 : case IPPROTO_IPCOMP:
1490 0 : m_copydata(m, hlen + sizeof(u_int16_t),
1491 : sizeof(u_int16_t), (caddr_t)&cpi);
1492 0 : spi = ntohl(htons(cpi));
1493 0 : break;
1494 : }
1495 :
1496 0 : NET_ASSERT_LOCKED();
1497 :
1498 0 : tdb = gettdb(ifp->if_rdomain, spi, &dst, proto);
1499 0 : if (tdb != NULL && (tdb->tdb_flags & TDBF_INVALID) == 0 &&
1500 0 : tdb->tdb_xform != NULL) {
1501 0 : if (tdb->tdb_first_use == 0) {
1502 0 : tdb->tdb_first_use = time_second;
1503 0 : if (tdb->tdb_flags & TDBF_FIRSTUSE)
1504 0 : timeout_add_sec(&tdb->tdb_first_tmo,
1505 0 : tdb->tdb_exp_first_use);
1506 0 : if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
1507 0 : timeout_add_sec(&tdb->tdb_sfirst_tmo,
1508 0 : tdb->tdb_soft_first_use);
1509 : }
1510 :
1511 0 : (*(tdb->tdb_xform->xf_input))(m, tdb, hlen, off);
1512 0 : return (1);
1513 : } else {
1514 : skiplookup:
1515 : /* XXX do an input policy lookup */
1516 0 : return (0);
1517 : }
1518 : } else { /* Outgoing from the bridge. */
1519 0 : tdb = ipsp_spd_lookup(m, af, hlen, &error,
1520 : IPSP_DIRECTION_OUT, NULL, NULL, 0);
1521 0 : if (tdb != NULL) {
1522 : /*
1523 : * We don't need to do loop detection, the
1524 : * bridge will do that for us.
1525 : */
1526 : #if NPF > 0
1527 0 : if ((encif = enc_getif(tdb->tdb_rdomain,
1528 0 : tdb->tdb_tap)) == NULL ||
1529 0 : pf_test(af, dir, encif, &m) != PF_PASS) {
1530 0 : m_freem(m);
1531 0 : return (1);
1532 : }
1533 0 : if (m == NULL)
1534 0 : return (1);
1535 0 : else if (af == AF_INET)
1536 0 : in_proto_cksum_out(m, encif);
1537 : #ifdef INET6
1538 0 : else if (af == AF_INET6)
1539 0 : in6_proto_cksum_out(m, encif);
1540 : #endif /* INET6 */
1541 : #endif /* NPF */
1542 :
1543 0 : ip = mtod(m, struct ip *);
1544 0 : if ((af == AF_INET) &&
1545 0 : ip_mtudisc && (ip->ip_off & htons(IP_DF)) &&
1546 0 : tdb->tdb_mtu && ntohs(ip->ip_len) > tdb->tdb_mtu &&
1547 0 : tdb->tdb_mtutimeout > time_second)
1548 0 : bridge_send_icmp_err(sc, ifp, eh, m,
1549 0 : hassnap, llc, tdb->tdb_mtu,
1550 : ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
1551 : else
1552 0 : error = ipsp_process_packet(m, tdb, af, 0);
1553 0 : return (1);
1554 : } else
1555 0 : return (0);
1556 : }
1557 :
1558 : return (0);
1559 0 : }
1560 : #endif /* IPSEC */
1561 :
1562 : /*
1563 : * Filter IP packets by peeking into the ethernet frame. This violates
1564 : * the ISO model, but allows us to act as a IP filter at the data link
1565 : * layer. As a result, most of this code will look familiar to those
1566 : * who've read net/if_ethersubr.c and netinet/ip_input.c
1567 : */
1568 : struct mbuf *
1569 0 : bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
1570 : struct ether_header *eh, struct mbuf *m)
1571 : {
1572 0 : struct llc llc;
1573 : int hassnap = 0;
1574 : struct ip *ip;
1575 : int hlen;
1576 : u_int16_t etype;
1577 :
1578 : #if NVLAN > 0
1579 0 : if (m->m_flags & M_VLANTAG)
1580 0 : return (m);
1581 : #endif
1582 :
1583 0 : etype = ntohs(eh->ether_type);
1584 :
1585 0 : if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
1586 0 : if (etype > ETHERMTU ||
1587 0 : m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
1588 : ETHER_HDR_LEN))
1589 0 : return (m);
1590 :
1591 0 : m_copydata(m, ETHER_HDR_LEN,
1592 : LLC_SNAPFRAMELEN, (caddr_t)&llc);
1593 :
1594 0 : if (llc.llc_dsap != LLC_SNAP_LSAP ||
1595 0 : llc.llc_ssap != LLC_SNAP_LSAP ||
1596 0 : llc.llc_control != LLC_UI ||
1597 0 : llc.llc_snap.org_code[0] ||
1598 0 : llc.llc_snap.org_code[1] ||
1599 0 : llc.llc_snap.org_code[2])
1600 0 : return (m);
1601 :
1602 0 : etype = ntohs(llc.llc_snap.ether_type);
1603 0 : if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
1604 0 : return (m);
1605 : hassnap = 1;
1606 0 : }
1607 :
1608 0 : m_adj(m, ETHER_HDR_LEN);
1609 0 : if (hassnap)
1610 0 : m_adj(m, LLC_SNAPFRAMELEN);
1611 :
1612 0 : switch (etype) {
1613 :
1614 : case ETHERTYPE_IP:
1615 0 : if (m->m_pkthdr.len < sizeof(struct ip))
1616 : goto dropit;
1617 :
1618 : /* Copy minimal header, and drop invalids */
1619 0 : if (m->m_len < sizeof(struct ip) &&
1620 0 : (m = m_pullup(m, sizeof(struct ip))) == NULL) {
1621 0 : ipstat_inc(ips_toosmall);
1622 0 : return (NULL);
1623 : }
1624 0 : ip = mtod(m, struct ip *);
1625 :
1626 0 : if (ip->ip_v != IPVERSION) {
1627 0 : ipstat_inc(ips_badvers);
1628 0 : goto dropit;
1629 : }
1630 :
1631 0 : hlen = ip->ip_hl << 2; /* get whole header length */
1632 0 : if (hlen < sizeof(struct ip)) {
1633 0 : ipstat_inc(ips_badhlen);
1634 0 : goto dropit;
1635 : }
1636 :
1637 0 : if (hlen > m->m_len) {
1638 0 : if ((m = m_pullup(m, hlen)) == NULL) {
1639 0 : ipstat_inc(ips_badhlen);
1640 0 : return (NULL);
1641 : }
1642 0 : ip = mtod(m, struct ip *);
1643 0 : }
1644 :
1645 0 : if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
1646 0 : if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
1647 0 : ipstat_inc(ips_badsum);
1648 0 : goto dropit;
1649 : }
1650 :
1651 0 : ipstat_inc(ips_inswcsum);
1652 0 : if (in_cksum(m, hlen) != 0) {
1653 0 : ipstat_inc(ips_badsum);
1654 0 : goto dropit;
1655 : }
1656 : }
1657 :
1658 0 : if (ntohs(ip->ip_len) < hlen)
1659 : goto dropit;
1660 :
1661 0 : if (m->m_pkthdr.len < ntohs(ip->ip_len))
1662 : goto dropit;
1663 0 : if (m->m_pkthdr.len > ntohs(ip->ip_len)) {
1664 0 : if (m->m_len == m->m_pkthdr.len) {
1665 0 : m->m_len = ntohs(ip->ip_len);
1666 0 : m->m_pkthdr.len = ntohs(ip->ip_len);
1667 0 : } else
1668 0 : m_adj(m, ntohs(ip->ip_len) - m->m_pkthdr.len);
1669 : }
1670 :
1671 : #ifdef IPSEC
1672 0 : if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
1673 0 : bridge_ipsec(sc, ifp, eh, hassnap, &llc,
1674 0 : dir, AF_INET, hlen, m))
1675 0 : return (NULL);
1676 : #endif /* IPSEC */
1677 : #if NPF > 0
1678 : /* Finally, we get to filter the packet! */
1679 0 : if (pf_test(AF_INET, dir, ifp, &m) != PF_PASS)
1680 : goto dropit;
1681 0 : if (m == NULL)
1682 : goto dropit;
1683 : #endif /* NPF > 0 */
1684 :
1685 : /* Rebuild the IP header */
1686 0 : if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
1687 0 : return (NULL);
1688 0 : if (m->m_len < sizeof(struct ip))
1689 : goto dropit;
1690 0 : in_proto_cksum_out(m, ifp);
1691 0 : ip = mtod(m, struct ip *);
1692 0 : ip->ip_sum = 0;
1693 : if (0 && (ifp->if_capabilities & IFCAP_CSUM_IPv4))
1694 : m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
1695 : else {
1696 0 : ipstat_inc(ips_outswcsum);
1697 0 : ip->ip_sum = in_cksum(m, hlen);
1698 : }
1699 :
1700 0 : break;
1701 :
1702 : #ifdef INET6
1703 : case ETHERTYPE_IPV6: {
1704 : struct ip6_hdr *ip6;
1705 :
1706 0 : if (m->m_len < sizeof(struct ip6_hdr)) {
1707 0 : if ((m = m_pullup(m, sizeof(struct ip6_hdr)))
1708 0 : == NULL) {
1709 0 : ip6stat_inc(ip6s_toosmall);
1710 0 : return (NULL);
1711 : }
1712 : }
1713 :
1714 0 : ip6 = mtod(m, struct ip6_hdr *);
1715 :
1716 0 : if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1717 0 : ip6stat_inc(ip6s_badvers);
1718 0 : goto dropit;
1719 : }
1720 :
1721 : #ifdef IPSEC
1722 : hlen = sizeof(struct ip6_hdr);
1723 :
1724 0 : if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
1725 0 : bridge_ipsec(sc, ifp, eh, hassnap, &llc,
1726 : dir, AF_INET6, hlen, m))
1727 0 : return (NULL);
1728 : #endif /* IPSEC */
1729 :
1730 : #if NPF > 0
1731 0 : if (pf_test(AF_INET6, dir, ifp, &m) != PF_PASS)
1732 0 : goto dropit;
1733 0 : if (m == NULL)
1734 0 : return (NULL);
1735 : #endif /* NPF > 0 */
1736 0 : in6_proto_cksum_out(m, ifp);
1737 :
1738 0 : break;
1739 : }
1740 : #endif /* INET6 */
1741 :
1742 : default:
1743 : goto dropit;
1744 : break;
1745 : }
1746 :
1747 : /* Reattach SNAP header */
1748 0 : if (hassnap) {
1749 0 : M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
1750 0 : if (m == NULL)
1751 : goto dropit;
1752 0 : bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
1753 0 : }
1754 :
1755 : /* Reattach ethernet header */
1756 0 : M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
1757 0 : if (m == NULL)
1758 : goto dropit;
1759 0 : bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
1760 :
1761 0 : return (m);
1762 :
1763 : dropit:
1764 0 : m_freem(m);
1765 0 : return (NULL);
1766 0 : }
1767 :
1768 : void
1769 0 : bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
1770 : struct ether_header *eh, struct mbuf *m)
1771 : {
1772 0 : struct llc llc;
1773 : struct mbuf *m0;
1774 : int error = 0;
1775 : int hassnap = 0;
1776 : u_int16_t etype;
1777 : struct ip *ip;
1778 :
1779 0 : etype = ntohs(eh->ether_type);
1780 : #if NVLAN > 0
1781 0 : if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN ||
1782 0 : etype == ETHERTYPE_QINQ) {
1783 0 : int len = m->m_pkthdr.len;
1784 :
1785 0 : if (m->m_flags & M_VLANTAG)
1786 0 : len += ETHER_VLAN_ENCAP_LEN;
1787 0 : if ((ifp->if_capabilities & IFCAP_VLAN_MTU) &&
1788 0 : (len - sizeof(struct ether_vlan_header) <= ifp->if_mtu)) {
1789 0 : bridge_ifenqueue(sc, ifp, m);
1790 0 : return;
1791 : }
1792 0 : goto dropit;
1793 : }
1794 : #endif
1795 0 : if (etype != ETHERTYPE_IP) {
1796 0 : if (etype > ETHERMTU ||
1797 0 : m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
1798 : ETHER_HDR_LEN))
1799 : goto dropit;
1800 :
1801 0 : m_copydata(m, ETHER_HDR_LEN,
1802 : LLC_SNAPFRAMELEN, (caddr_t)&llc);
1803 :
1804 0 : if (llc.llc_dsap != LLC_SNAP_LSAP ||
1805 0 : llc.llc_ssap != LLC_SNAP_LSAP ||
1806 0 : llc.llc_control != LLC_UI ||
1807 0 : llc.llc_snap.org_code[0] ||
1808 0 : llc.llc_snap.org_code[1] ||
1809 0 : llc.llc_snap.org_code[2] ||
1810 0 : llc.llc_snap.ether_type != htons(ETHERTYPE_IP))
1811 : goto dropit;
1812 :
1813 : hassnap = 1;
1814 0 : }
1815 :
1816 0 : m_adj(m, ETHER_HDR_LEN);
1817 0 : if (hassnap)
1818 0 : m_adj(m, LLC_SNAPFRAMELEN);
1819 :
1820 0 : if (m->m_len < sizeof(struct ip) &&
1821 0 : (m = m_pullup(m, sizeof(struct ip))) == NULL)
1822 : goto dropit;
1823 0 : ip = mtod(m, struct ip *);
1824 :
1825 : /* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
1826 0 : if (ip->ip_off & htons(IP_DF)) {
1827 0 : bridge_send_icmp_err(sc, ifp, eh, m, hassnap, &llc,
1828 0 : ifp->if_mtu, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
1829 0 : return;
1830 : }
1831 :
1832 0 : error = ip_fragment(m, ifp, ifp->if_mtu);
1833 0 : if (error) {
1834 : m = NULL;
1835 0 : goto dropit;
1836 : }
1837 :
1838 0 : for (; m; m = m0) {
1839 0 : m0 = m->m_nextpkt;
1840 0 : m->m_nextpkt = NULL;
1841 0 : if (error == 0) {
1842 0 : if (hassnap) {
1843 0 : M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
1844 0 : if (m == NULL) {
1845 : error = ENOBUFS;
1846 0 : continue;
1847 : }
1848 0 : bcopy(&llc, mtod(m, caddr_t),
1849 : LLC_SNAPFRAMELEN);
1850 0 : }
1851 0 : M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
1852 0 : if (m == NULL) {
1853 : error = ENOBUFS;
1854 0 : continue;
1855 : }
1856 0 : bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
1857 0 : error = bridge_ifenqueue(sc, ifp, m);
1858 0 : if (error) {
1859 : continue;
1860 : }
1861 : } else
1862 0 : m_freem(m);
1863 : }
1864 :
1865 0 : if (error == 0)
1866 0 : ipstat_inc(ips_fragmented);
1867 :
1868 0 : return;
1869 : dropit:
1870 0 : m_freem(m);
1871 0 : }
1872 :
1873 : int
1874 0 : bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
1875 : {
1876 : int error, len;
1877 :
1878 : /* Loop prevention. */
1879 0 : m->m_flags |= M_PROTO1;
1880 :
1881 0 : len = m->m_pkthdr.len;
1882 :
1883 0 : error = if_enqueue(ifp, m);
1884 0 : if (error) {
1885 0 : sc->sc_if.if_oerrors++;
1886 0 : return (error);
1887 : }
1888 :
1889 0 : sc->sc_if.if_opackets++;
1890 0 : sc->sc_if.if_obytes += len;
1891 :
1892 0 : return (0);
1893 0 : }
1894 :
1895 : void
1896 0 : bridge_ifinput(struct ifnet *ifp, struct mbuf *m)
1897 : {
1898 0 : struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1899 :
1900 0 : m->m_flags |= M_PROTO1;
1901 :
1902 0 : ml_enqueue(&ml, m);
1903 0 : if_input(ifp, &ml);
1904 0 : }
1905 :
1906 : void
1907 0 : bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
1908 : struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
1909 : int mtu, int type, int code)
1910 : {
1911 : struct ip *ip;
1912 : struct icmp *icp;
1913 : struct in_addr t;
1914 : struct mbuf *m, *n2;
1915 : int hlen;
1916 0 : u_int8_t ether_tmp[ETHER_ADDR_LEN];
1917 :
1918 0 : n2 = m_copym(n, 0, M_COPYALL, M_DONTWAIT);
1919 0 : if (!n2) {
1920 0 : m_freem(n);
1921 0 : return;
1922 : }
1923 0 : m = icmp_do_error(n, type, code, 0, mtu);
1924 0 : if (m == NULL) {
1925 0 : m_freem(n2);
1926 0 : return;
1927 : }
1928 :
1929 : n = n2;
1930 :
1931 0 : ip = mtod(m, struct ip *);
1932 0 : hlen = ip->ip_hl << 2;
1933 0 : t = ip->ip_dst;
1934 0 : ip->ip_dst = ip->ip_src;
1935 0 : ip->ip_src = t;
1936 :
1937 0 : m->m_data += hlen;
1938 0 : m->m_len -= hlen;
1939 0 : icp = mtod(m, struct icmp *);
1940 0 : icp->icmp_cksum = 0;
1941 0 : icp->icmp_cksum = in_cksum(m, ntohs(ip->ip_len) - hlen);
1942 0 : m->m_data -= hlen;
1943 0 : m->m_len += hlen;
1944 :
1945 0 : ip->ip_v = IPVERSION;
1946 0 : ip->ip_off &= htons(IP_DF);
1947 0 : ip->ip_id = htons(ip_randomid());
1948 0 : ip->ip_ttl = MAXTTL;
1949 0 : ip->ip_sum = 0;
1950 0 : ip->ip_sum = in_cksum(m, hlen);
1951 :
1952 : /* Swap ethernet addresses */
1953 0 : bcopy(&eh->ether_dhost, ðer_tmp, sizeof(ether_tmp));
1954 0 : bcopy(&eh->ether_shost, &eh->ether_dhost, sizeof(ether_tmp));
1955 0 : bcopy(ðer_tmp, &eh->ether_shost, sizeof(ether_tmp));
1956 :
1957 : /* Reattach SNAP header */
1958 0 : if (hassnap) {
1959 0 : M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
1960 0 : if (m == NULL)
1961 : goto dropit;
1962 0 : bcopy(llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
1963 0 : }
1964 :
1965 : /* Reattach ethernet header */
1966 0 : M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
1967 0 : if (m == NULL)
1968 : goto dropit;
1969 0 : bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
1970 :
1971 0 : bridge_output(ifp, m, NULL, NULL);
1972 0 : m_freem(n);
1973 0 : return;
1974 :
1975 : dropit:
1976 0 : m_freem(n);
1977 0 : }
1978 :
1979 : struct bridge_tunneltag *
1980 0 : bridge_tunnel(struct mbuf *m)
1981 : {
1982 : struct m_tag *mtag;
1983 :
1984 0 : if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL)
1985 0 : return (NULL);
1986 :
1987 0 : return ((struct bridge_tunneltag *)(mtag + 1));
1988 0 : }
1989 :
1990 : struct bridge_tunneltag *
1991 0 : bridge_tunneltag(struct mbuf *m)
1992 : {
1993 : struct m_tag *mtag;
1994 :
1995 0 : if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL) {
1996 0 : mtag = m_tag_get(PACKET_TAG_TUNNEL,
1997 : sizeof(struct bridge_tunneltag), M_NOWAIT);
1998 0 : if (mtag == NULL)
1999 0 : return (NULL);
2000 0 : bzero(mtag + 1, sizeof(struct bridge_tunneltag));
2001 0 : m_tag_prepend(m, mtag);
2002 0 : }
2003 :
2004 0 : return ((struct bridge_tunneltag *)(mtag + 1));
2005 0 : }
2006 :
2007 : void
2008 0 : bridge_tunneluntag(struct mbuf *m)
2009 : {
2010 : struct m_tag *mtag;
2011 0 : if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) != NULL)
2012 0 : m_tag_delete(m, mtag);
2013 0 : }
2014 :
2015 : void
2016 0 : bridge_copyaddr(struct sockaddr *src, struct sockaddr *dst)
2017 : {
2018 0 : if (src != NULL && src->sa_family != AF_UNSPEC)
2019 0 : memcpy(dst, src, src->sa_len);
2020 : else {
2021 0 : dst->sa_family = AF_UNSPEC;
2022 0 : dst->sa_len = 0;
2023 : }
2024 0 : }
2025 :
2026 : void
2027 0 : bridge_copytag(struct bridge_tunneltag *src, struct bridge_tunneltag *dst)
2028 : {
2029 0 : if (src == NULL) {
2030 0 : memset(dst, 0, sizeof(*dst));
2031 0 : } else {
2032 0 : bridge_copyaddr(&src->brtag_peer.sa, &dst->brtag_peer.sa);
2033 0 : bridge_copyaddr(&src->brtag_local.sa, &dst->brtag_local.sa);
2034 0 : dst->brtag_id = src->brtag_id;
2035 : }
2036 0 : }
|