1 /* $OpenBSD: if_bridge.c,v 1.134 2004/05/04 18:03:58 canacar 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 "vlan.h"
38
39 #include <sys/param.h>
40 #include <sys/proc.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <sys/errno.h>
46 #include <sys/kernel.h>
47 #include <machine/cpu.h>
48 #include <dev/rndvar.h>
49
50 #include <net/if.h>
51 #include <net/if_types.h>
52 #include <net/if_llc.h>
53 #include <net/route.h>
54 #include <net/netisr.h>
55
56 #ifdef INET
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip.h>
61 #include <netinet/ip_var.h>
62 #include <netinet/if_ether.h>
63 #include <netinet/ip_icmp.h>
64 #endif
65
66 #ifdef IPSEC
67 #include <netinet/ip_ipsp.h>
68
69 #include <net/if_enc.h>
70 #endif
71
72 #ifdef INET6
73 #include <netinet/ip6.h>
74 #include <netinet6/ip6_var.h>
75 #endif
76
77 #if NPF > 0
78 #include <net/pfvar.h>
79 #define BRIDGE_IN PF_IN
80 #define BRIDGE_OUT PF_OUT
81 #else
82 #define BRIDGE_IN 0
83 #define BRIDGE_OUT 1
84 #endif
85
86 #if NBPFILTER > 0
87 #include <net/bpf.h>
88 #endif
89
90 #if NVLAN > 0
91 #include <net/if_vlan_var.h>
92 #endif
93
94 #include <net/if_bridge.h>
95
96 #ifndef BRIDGE_RTABLE_SIZE
97 #define BRIDGE_RTABLE_SIZE 1024
98 #endif
99 #define BRIDGE_RTABLE_MASK (BRIDGE_RTABLE_SIZE - 1)
100
101 /*
102 * Maximum number of addresses to cache
103 */
104 #ifndef BRIDGE_RTABLE_MAX
105 #define BRIDGE_RTABLE_MAX 100
106 #endif
107
108 /* spanning tree defaults */
109 #define BSTP_DEFAULT_MAX_AGE (20 * 256)
110 #define BSTP_DEFAULT_HELLO_TIME (2 * 256)
111 #define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)
112 #define BSTP_DEFAULT_HOLD_TIME (1 * 256)
113 #define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000
114 #define BSTP_DEFAULT_PORT_PRIORITY 0x80
115 #define BSTP_DEFAULT_PATH_COST 55
116
117 /*
118 * Timeout (in seconds) for entries learned dynamically
119 */
120 #ifndef BRIDGE_RTABLE_TIMEOUT
121 #define BRIDGE_RTABLE_TIMEOUT 240
122 #endif
123
124 extern int ifqmaxlen;
125
126 void bridgeattach(int);
127 int bridge_ioctl(struct ifnet *, u_long, caddr_t);
128 void bridge_start(struct ifnet *);
129 void bridgeintr_frame(struct bridge_softc *, struct mbuf *);
130 void bridge_broadcast(struct bridge_softc *, struct ifnet *,
131 struct ether_header *, struct mbuf *);
132 void bridge_span(struct bridge_softc *, struct ether_header *,
133 struct mbuf *);
134 void bridge_stop(struct bridge_softc *);
135 void bridge_init(struct bridge_softc *);
136 int bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
137
138 void bridge_timer(void *);
139 int bridge_rtfind(struct bridge_softc *, struct ifbaconf *);
140 void bridge_rtage(struct bridge_softc *);
141 void bridge_rttrim(struct bridge_softc *);
142 int bridge_rtdaddr(struct bridge_softc *, struct ether_addr *);
143 int bridge_rtflush(struct bridge_softc *, int);
144 struct ifnet * bridge_rtupdate(struct bridge_softc *,
145 struct ether_addr *, struct ifnet *ifp, int, u_int8_t);
146 struct ifnet * bridge_rtlookup(struct bridge_softc *,
147 struct ether_addr *);
148 u_int32_t bridge_hash(struct bridge_softc *, struct ether_addr *);
149 int bridge_blocknonip(struct ether_header *, struct mbuf *);
150 int bridge_addrule(struct bridge_iflist *,
151 struct ifbrlreq *, int out);
152 int bridge_flushrule(struct bridge_iflist *);
153 int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *);
154 u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *,
155 struct mbuf *);
156 #if NPF > 0
157 struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *,
158 struct ether_header *, struct mbuf *m);
159 #endif
160 int bridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *);
161 void bridge_fragment(struct bridge_softc *, struct ifnet *,
162 struct ether_header *, struct mbuf *);
163 #ifdef INET
164 void bridge_send_icmp_err(struct bridge_softc *, struct ifnet *,
165 struct ether_header *, struct mbuf *, int, struct llc *, int, int);
166 #endif
167 #ifdef IPSEC
168 int bridge_ipsec(int, int, int, struct mbuf *);
169 #endif
170 int bridge_clone_create(struct if_clone *, int);
171 int bridge_clone_destroy(struct ifnet *ifp);
172
173 #define ETHERADDR_IS_IP_MCAST(a) \
174 /* struct etheraddr *a; */ \
175 ((a)->ether_addr_octet[0] == 0x01 && \
176 (a)->ether_addr_octet[1] == 0x00 && \
177 (a)->ether_addr_octet[2] == 0x5e)
178
179 LIST_HEAD(, bridge_softc) bridge_list;
180
181 struct if_clone bridge_cloner =
182 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
183
184 /* ARGSUSED */
185 void
bridgeattach(int n)186 bridgeattach(int n)
187 {
188 LIST_INIT(&bridge_list);
189 if_clone_attach(&bridge_cloner);
190 }
191
192 int
bridge_clone_create(struct if_clone * ifc,int unit)193 bridge_clone_create(struct if_clone *ifc, int unit)
194 {
195 struct bridge_softc *sc;
196 struct ifnet *ifp;
197 int s;
198
199 sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
200 if (!sc)
201 return (ENOMEM);
202 bzero(sc, sizeof(*sc));
203
204 sc->sc_brtmax = BRIDGE_RTABLE_MAX;
205 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
206 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE;
207 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME;
208 sc->sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY;
209 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY;
210 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME;
211 timeout_set(&sc->sc_brtimeout, bridge_timer, sc);
212 LIST_INIT(&sc->sc_iflist);
213 LIST_INIT(&sc->sc_spanlist);
214 ifp = &sc->sc_if;
215 snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
216 unit);
217 ifp->if_softc = sc;
218 ifp->if_mtu = ETHERMTU;
219 ifp->if_ioctl = bridge_ioctl;
220 ifp->if_output = bridge_output;
221 ifp->if_start = bridge_start;
222 ifp->if_type = IFT_BRIDGE;
223 ifp->if_snd.ifq_maxlen = ifqmaxlen;
224 ifp->if_hdrlen = sizeof(struct ether_header);
225 if_attach(ifp);
226 if_alloc_sadl(ifp);
227 #if NBPFILTER > 0
228 bpfattach(&sc->sc_if.if_bpf, ifp,
229 DLT_EN10MB, sizeof(struct ether_header));
230 #endif
231 s = splnet();
232 LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
233 splx(s);
234
235 return (0);
236 }
237
238 int
bridge_clone_destroy(struct ifnet * ifp)239 bridge_clone_destroy(struct ifnet *ifp)
240 {
241 struct bridge_softc *sc = ifp->if_softc;
242 struct bridge_iflist *bif;
243 int s;
244
245 bridge_stop(sc);
246 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) {
247 /* XXX shared with ioctl and detach */
248 /* XXX promisc disable? */
249 LIST_REMOVE(bif, next);
250 bridge_rtdelete(sc, bif->ifp, 0);
251 bridge_flushrule(bif);
252 bif->ifp->if_bridge = NULL;
253 free(bif, M_DEVBUF);
254 }
255 while ((bif = LIST_FIRST(&sc->sc_spanlist)) != NULL) {
256 LIST_REMOVE(bif, next);
257 free(bif, M_DEVBUF);
258 }
259
260 s = splnet();
261 LIST_REMOVE(sc, sc_list);
262 splx(s);
263
264 #if NBPFILTER > 0
265 bpfdetach(ifp);
266 #endif
267 if_detach(ifp);
268
269 free(sc, M_DEVBUF);
270 return (0);
271 }
272
273 int
bridge_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data)274 bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
275 {
276 struct proc *prc = curproc; /* XXX */
277 struct ifnet *ifs;
278 struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
279 struct ifbreq *req = (struct ifbreq *)data;
280 struct ifbaconf *baconf = (struct ifbaconf *)data;
281 struct ifbareq *bareq = (struct ifbareq *)data;
282 struct ifbrparam *bparam = (struct ifbrparam *)data;
283 struct ifbifconf *bifconf = (struct ifbifconf *)data;
284 struct ifbrlreq *brlreq = (struct ifbrlreq *)data;
285 struct ifbrlconf *brlconf = (struct ifbrlconf *)data;
286 struct ifreq ifreq;
287 int error = 0, s;
288 struct bridge_iflist *p;
289
290 s = splnet();
291 switch (cmd) {
292 case SIOCBRDGADD:
293 if ((error = suser(prc, 0)) != 0)
294 break;
295
296 ifs = ifunit(req->ifbr_ifsname);
297 if (ifs == NULL) { /* no such interface */
298 error = ENOENT;
299 break;
300 }
301 if (ifs->if_bridge == (caddr_t)sc) {
302 error = EEXIST;
303 break;
304 }
305 if (ifs->if_bridge != NULL) {
306 error = EBUSY;
307 break;
308 }
309
310 /* If it's in the span list, it can't be a member. */
311 LIST_FOREACH(p, &sc->sc_spanlist, next)
312 if (p->ifp == ifs)
313 break;
314
315 if (p != LIST_END(&sc->sc_spanlist)) {
316 error = EBUSY;
317 break;
318 }
319
320 if (ifs->if_type == IFT_ETHER) {
321 if ((ifs->if_flags & IFF_UP) == 0) {
322 /*
323 * Bring interface up long enough to set
324 * promiscuous flag, then shut it down again.
325 */
326 strlcpy(ifreq.ifr_name, req->ifbr_ifsname,
327 IFNAMSIZ);
328 ifs->if_flags |= IFF_UP;
329 ifreq.ifr_flags = ifs->if_flags;
330 error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
331 (caddr_t)&ifreq);
332 if (error != 0)
333 break;
334
335 error = ifpromisc(ifs, 1);
336 if (error != 0)
337 break;
338
339 strlcpy(ifreq.ifr_name, req->ifbr_ifsname,
340 IFNAMSIZ);
341 ifs->if_flags &= ~IFF_UP;
342 ifreq.ifr_flags = ifs->if_flags;
343 error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS,
344 (caddr_t)&ifreq);
345 if (error != 0) {
346 ifpromisc(ifs, 0);
347 break;
348 }
349 } else {
350 error = ifpromisc(ifs, 1);
351 if (error != 0)
352 break;
353 }
354 }
355 #if NGIF > 0
356 else if (ifs->if_type == IFT_GIF) {
357 /* Nothing needed */
358 }
359 #endif /* NGIF */
360 else {
361 error = EINVAL;
362 break;
363 }
364
365 p = (struct bridge_iflist *) malloc(
366 sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT);
367 if (p == NULL) {
368 if (ifs->if_type == IFT_ETHER)
369 ifpromisc(ifs, 0);
370 error = ENOMEM;
371 break;
372 }
373 bzero(p, sizeof(struct bridge_iflist));
374
375 p->ifp = ifs;
376 p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
377 p->bif_priority = BSTP_DEFAULT_PORT_PRIORITY;
378 p->bif_path_cost = BSTP_DEFAULT_PATH_COST;
379 SIMPLEQ_INIT(&p->bif_brlin);
380 SIMPLEQ_INIT(&p->bif_brlout);
381 LIST_INSERT_HEAD(&sc->sc_iflist, p, next);
382 ifs->if_bridge = (caddr_t)sc;
383 break;
384 case SIOCBRDGDEL:
385 if ((error = suser(prc, 0)) != 0)
386 break;
387
388 LIST_FOREACH(p, &sc->sc_iflist, next) {
389 if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
390 sizeof(p->ifp->if_xname)) == 0) {
391 p->ifp->if_bridge = NULL;
392
393 error = ifpromisc(p->ifp, 0);
394
395 LIST_REMOVE(p, next);
396 bridge_rtdelete(sc, p->ifp, 0);
397 bridge_flushrule(p);
398 free(p, M_DEVBUF);
399 break;
400 }
401 }
402 if (p == LIST_END(&sc->sc_iflist)) {
403 error = ENOENT;
404 break;
405 }
406 break;
407 case SIOCBRDGIFS:
408 error = bridge_bifconf(sc, bifconf);
409 break;
410 case SIOCBRDGADDS:
411 if ((error = suser(prc, 0)) != 0)
412 break;
413 ifs = ifunit(req->ifbr_ifsname);
414 if (ifs == NULL) { /* no such interface */
415 error = ENOENT;
416 break;
417 }
418 if (ifs->if_bridge == (caddr_t)sc) {
419 error = EEXIST;
420 break;
421 }
422 if (ifs->if_bridge != NULL) {
423 error = EBUSY;
424 break;
425 }
426 LIST_FOREACH(p, &sc->sc_spanlist, next) {
427 if (p->ifp == ifs)
428 break;
429 }
430 if (p != LIST_END(&sc->sc_spanlist)) {
431 error = EBUSY;
432 break;
433 }
434 p = (struct bridge_iflist *)malloc(
435 sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT);
436 if (p == NULL) {
437 error = ENOMEM;
438 break;
439 }
440 bzero(p, sizeof(struct bridge_iflist));
441 p->ifp = ifs;
442 SIMPLEQ_INIT(&p->bif_brlin);
443 SIMPLEQ_INIT(&p->bif_brlout);
444 LIST_INSERT_HEAD(&sc->sc_spanlist, p, next);
445 break;
446 case SIOCBRDGDELS:
447 if ((error = suser(prc, 0)) != 0)
448 break;
449 LIST_FOREACH(p, &sc->sc_spanlist, next) {
450 if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
451 sizeof(p->ifp->if_xname)) == 0) {
452 LIST_REMOVE(p, next);
453 free(p, M_DEVBUF);
454 break;
455 }
456 }
457 if (p == LIST_END(&sc->sc_spanlist)) {
458 error = ENOENT;
459 break;
460 }
461 break;
462 case SIOCBRDGGIFFLGS:
463 ifs = ifunit(req->ifbr_ifsname);
464 if (ifs == NULL) {
465 error = ENOENT;
466 break;
467 }
468 if ((caddr_t)sc != ifs->if_bridge) {
469 error = ESRCH;
470 break;
471 }
472 LIST_FOREACH(p, &sc->sc_iflist, next) {
473 if (p->ifp == ifs)
474 break;
475 }
476 if (p == LIST_END(&sc->sc_iflist)) {
477 error = ESRCH;
478 break;
479 }
480 req->ifbr_ifsflags = p->bif_flags;
481 req->ifbr_state = p->bif_state;
482 req->ifbr_priority = p->bif_priority;
483 req->ifbr_path_cost = p->bif_path_cost;
484 req->ifbr_portno = p->ifp->if_index & 0xff;
485 break;
486 case SIOCBRDGSIFFLGS:
487 if ((error = suser(prc, 0)) != 0)
488 break;
489 ifs = ifunit(req->ifbr_ifsname);
490 if (ifs == NULL) {
491 error = ENOENT;
492 break;
493 }
494 if ((caddr_t)sc != ifs->if_bridge) {
495 error = ESRCH;
496 break;
497 }
498 LIST_FOREACH(p, &sc->sc_iflist, next) {
499 if (p->ifp == ifs)
500 break;
501 }
502 if (p == LIST_END(&sc->sc_iflist)) {
503 error = ESRCH;
504 break;
505 }
506 if (req->ifbr_ifsflags & IFBIF_RO_MASK) {
507 error = EINVAL;
508 break;
509 }
510 if ((req->ifbr_ifsflags & IFBIF_STP) &&
511 (ifs->if_type != IFT_ETHER)) {
512 error = EINVAL;
513 break;
514 }
515 p->bif_flags = req->ifbr_ifsflags;
516 break;
517 case SIOCBRDGSIFPRIO:
518 case SIOCBRDGSIFCOST:
519 if ((error = suser(prc, 0)) != 0)
520 break;
521 ifs = ifunit(req->ifbr_ifsname);
522 if (ifs == NULL) {
523 error = ENOENT;
524 break;
525 }
526 if ((caddr_t)sc != ifs->if_bridge) {
527 error = ESRCH;
528 break;
529 }
530 LIST_FOREACH(p, &sc->sc_iflist, next) {
531 if (p->ifp == ifs)
532 break;
533 }
534 if (p == LIST_END(&sc->sc_iflist)) {
535 error = ESRCH;
536 break;
537 }
538 if (cmd == SIOCBRDGSIFPRIO)
539 p->bif_priority = req->ifbr_priority;
540 else {
541 if (req->ifbr_path_cost < 1)
542 error = EINVAL;
543 else
544 p->bif_path_cost = req->ifbr_path_cost;
545 }
546 break;
547 case SIOCBRDGRTS:
548 error = bridge_rtfind(sc, baconf);
549 break;
550 case SIOCBRDGFLUSH:
551 if ((error = suser(prc, 0)) != 0)
552 break;
553
554 error = bridge_rtflush(sc, req->ifbr_ifsflags);
555 break;
556 case SIOCBRDGSADDR:
557 if ((error = suser(prc, 0)) != 0)
558 break;
559
560 ifs = ifunit(bareq->ifba_ifsname);
561 if (ifs == NULL) { /* no such interface */
562 error = ENOENT;
563 break;
564 }
565
566 if (ifs->if_bridge == NULL ||
567 ifs->if_bridge != (caddr_t)sc) {
568 error = ESRCH;
569 break;
570 }
571
572 ifs = bridge_rtupdate(sc, &bareq->ifba_dst, ifs, 1,
573 bareq->ifba_flags);
574 if (ifs == NULL)
575 error = ENOMEM;
576 break;
577 case SIOCBRDGDADDR:
578 if ((error = suser(prc, 0)) != 0)
579 break;
580 error = bridge_rtdaddr(sc, &bareq->ifba_dst);
581 break;
582 case SIOCBRDGGCACHE:
583 bparam->ifbrp_csize = sc->sc_brtmax;
584 break;
585 case SIOCBRDGSCACHE:
586 if ((error = suser(prc, 0)) != 0)
587 break;
588 sc->sc_brtmax = bparam->ifbrp_csize;
589 bridge_rttrim(sc);
590 break;
591 case SIOCBRDGSTO:
592 if ((error = suser(prc, 0)) != 0)
593 break;
594 if (bparam->ifbrp_ctime < 0 ||
595 bparam->ifbrp_ctime > INT_MAX / hz) {
596 error = EINVAL;
597 break;
598 }
599 sc->sc_brttimeout = bparam->ifbrp_ctime;
600 timeout_del(&sc->sc_brtimeout);
601 if (bparam->ifbrp_ctime != 0)
602 timeout_add(&sc->sc_brtimeout, sc->sc_brttimeout * hz);
603 break;
604 case SIOCBRDGGTO:
605 bparam->ifbrp_ctime = sc->sc_brttimeout;
606 break;
607 case SIOCSIFFLAGS:
608 if ((ifp->if_flags & IFF_UP) == IFF_UP)
609 bridge_init(sc);
610
611 if ((ifp->if_flags & IFF_UP) == 0)
612 bridge_stop(sc);
613
614 break;
615 case SIOCBRDGARL:
616 if ((error = suser(prc, 0)) != 0)
617 break;
618 ifs = ifunit(brlreq->ifbr_ifsname);
619 if (ifs == NULL) {
620 error = ENOENT;
621 break;
622 }
623 if (ifs->if_bridge == NULL ||
624 ifs->if_bridge != (caddr_t)sc) {
625 error = ESRCH;
626 break;
627 }
628 LIST_FOREACH(p, &sc->sc_iflist, next) {
629 if (p->ifp == ifs)
630 break;
631 }
632 if (p == LIST_END(&sc->sc_iflist)) {
633 error = ESRCH;
634 break;
635 }
636 if ((brlreq->ifbr_action != BRL_ACTION_BLOCK &&
637 brlreq->ifbr_action != BRL_ACTION_PASS) ||
638 (brlreq->ifbr_flags & (BRL_FLAG_IN|BRL_FLAG_OUT)) == 0) {
639 error = EINVAL;
640 break;
641 }
642 if (brlreq->ifbr_flags & BRL_FLAG_IN) {
643 error = bridge_addrule(p, brlreq, 0);
644 if (error)
645 break;
646 }
647 if (brlreq->ifbr_flags & BRL_FLAG_OUT) {
648 error = bridge_addrule(p, brlreq, 1);
649 if (error)
650 break;
651 }
652 break;
653 case SIOCBRDGFRL:
654 if ((error = suser(prc, 0)) != 0)
655 break;
656 ifs = ifunit(brlreq->ifbr_ifsname);
657 if (ifs == NULL) {
658 error = ENOENT;
659 break;
660 }
661 if (ifs->if_bridge == NULL ||
662 ifs->if_bridge != (caddr_t)sc) {
663 error = ESRCH;
664 break;
665 }
666 LIST_FOREACH(p, &sc->sc_iflist, next) {
667 if (p->ifp == ifs)
668 break;
669 }
670 if (p == LIST_END(&sc->sc_iflist)) {
671 error = ESRCH;
672 break;
673 }
674 error = bridge_flushrule(p);
675 break;
676 case SIOCBRDGGRL:
677 error = bridge_brlconf(sc, brlconf);
678 break;
679 case SIOCBRDGGPRI:
680 case SIOCBRDGGMA:
681 case SIOCBRDGGHT:
682 case SIOCBRDGGFD:
683 break;
684 case SIOCBRDGSPRI:
685 case SIOCBRDGSFD:
686 case SIOCBRDGSMA:
687 case SIOCBRDGSHT:
688 error = suser(prc, 0);
689 break;
690 default:
691 error = EINVAL;
692 }
693
694 if (!error)
695 error = bstp_ioctl(ifp, cmd, data);
696
697 splx(s);
698 return (error);
699 }
700
701 /* Detach an interface from a bridge. */
702 void
bridge_ifdetach(struct ifnet * ifp)703 bridge_ifdetach(struct ifnet *ifp)
704 {
705 struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge;
706 struct bridge_iflist *bif;
707
708 LIST_FOREACH(bif, &sc->sc_iflist, next)
709 if (bif->ifp == ifp) {
710 LIST_REMOVE(bif, next);
711 bridge_rtdelete(sc, ifp, 0);
712 bridge_flushrule(bif);
713 free(bif, M_DEVBUF);
714 ifp->if_bridge = NULL;
715 break;
716 }
717 }
718
719 int
bridge_bifconf(struct bridge_softc * sc,struct ifbifconf * bifc)720 bridge_bifconf(struct bridge_softc *sc, struct ifbifconf *bifc)
721 {
722 struct bridge_iflist *p;
723 u_int32_t total = 0, i = 0;
724 int error = 0;
725 struct ifbreq breq;
726
727 LIST_FOREACH(p, &sc->sc_iflist, next)
728 total++;
729
730 LIST_FOREACH(p, &sc->sc_spanlist, next)
731 total++;
732
733 if (bifc->ifbic_len == 0) {
734 i = total;
735 goto done;
736 }
737
738 LIST_FOREACH(p, &sc->sc_iflist, next) {
739 if (bifc->ifbic_len < sizeof(breq))
740 break;
741 strlcpy(breq.ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
742 strlcpy(breq.ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
743 breq.ifbr_ifsflags = p->bif_flags;
744 breq.ifbr_state = p->bif_state;
745 breq.ifbr_priority = p->bif_priority;
746 breq.ifbr_path_cost = p->bif_path_cost;
747 breq.ifbr_portno = p->ifp->if_index & 0xff;
748 error = copyout((caddr_t)&breq,
749 (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
750 if (error)
751 goto done;
752 i++;
753 bifc->ifbic_len -= sizeof(breq);
754 }
755 LIST_FOREACH(p, &sc->sc_spanlist, next) {
756 if (bifc->ifbic_len < sizeof(breq))
757 break;
758 strlcpy(breq.ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
759 strlcpy(breq.ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
760 breq.ifbr_ifsflags = p->bif_flags | IFBIF_SPAN;
761 breq.ifbr_state = p->bif_state;
762 breq.ifbr_priority = p->bif_priority;
763 breq.ifbr_path_cost = p->bif_path_cost;
764 breq.ifbr_portno = p->ifp->if_index & 0xff;
765 error = copyout((caddr_t)&breq,
766 (caddr_t)(bifc->ifbic_req + i), sizeof(breq));
767 if (error)
768 goto done;
769 i++;
770 bifc->ifbic_len -= sizeof(breq);
771 }
772
773 done:
774 bifc->ifbic_len = i * sizeof(breq);
775 return (error);
776 }
777
778 int
bridge_brlconf(struct bridge_softc * sc,struct ifbrlconf * bc)779 bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc)
780 {
781 struct ifnet *ifp;
782 struct bridge_iflist *ifl;
783 struct brl_node *n;
784 struct ifbrlreq req;
785 int error = 0;
786 u_int32_t i = 0, total = 0;
787
788 ifp = ifunit(bc->ifbrl_ifsname);
789 if (ifp == NULL)
790 return (ENOENT);
791 if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc)
792 return (ESRCH);
793 LIST_FOREACH(ifl, &sc->sc_iflist, next) {
794 if (ifl->ifp == ifp)
795 break;
796 }
797 if (ifl == LIST_END(&sc->sc_iflist))
798 return (ESRCH);
799
800 SIMPLEQ_FOREACH(n, &ifl->bif_brlin, brl_next) {
801 total++;
802 }
803 SIMPLEQ_FOREACH(n, &ifl->bif_brlout, brl_next) {
804 total++;
805 }
806
807 if (bc->ifbrl_len == 0) {
808 i = total;
809 goto done;
810 }
811
812 SIMPLEQ_FOREACH(n, &ifl->bif_brlin, brl_next) {
813 if (bc->ifbrl_len < sizeof(req))
814 goto done;
815 strlcpy(req.ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
816 strlcpy(req.ifbr_ifsname, ifl->ifp->if_xname, IFNAMSIZ);
817 req.ifbr_action = n->brl_action;
818 req.ifbr_flags = n->brl_flags;
819 req.ifbr_src = n->brl_src;
820 req.ifbr_dst = n->brl_dst;
821 #if NPF > 0
822 req.ifbr_tagname[0] = '\0';
823 if (n->brl_tag)
824 pf_tag2tagname(n->brl_tag, req.ifbr_tagname);
825 #endif
826 error = copyout((caddr_t)&req,
827 (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
828 if (error)
829 goto done;
830 i++;
831 bc->ifbrl_len -= sizeof(req);
832 }
833
834 SIMPLEQ_FOREACH(n, &ifl->bif_brlout, brl_next) {
835 if (bc->ifbrl_len < sizeof(req))
836 goto done;
837 strlcpy(req.ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
838 strlcpy(req.ifbr_ifsname, ifl->ifp->if_xname, IFNAMSIZ);
839 req.ifbr_action = n->brl_action;
840 req.ifbr_flags = n->brl_flags;
841 req.ifbr_src = n->brl_src;
842 req.ifbr_dst = n->brl_dst;
843 #if NPF > 0
844 req.ifbr_tagname[0] = '\0';
845 if (n->brl_tag)
846 pf_tag2tagname(n->brl_tag, req.ifbr_tagname);
847 #endif
848 error = copyout((caddr_t)&req,
849 (caddr_t)(bc->ifbrl_buf + (i * sizeof(req))), sizeof(req));
850 if (error)
851 goto done;
852 i++;
853 bc->ifbrl_len -= sizeof(req);
854 }
855
856 done:
857 bc->ifbrl_len = i * sizeof(req);
858 return (error);
859 }
860
861 void
bridge_init(struct bridge_softc * sc)862 bridge_init(struct bridge_softc *sc)
863 {
864 struct ifnet *ifp = &sc->sc_if;
865 int i;
866
867 if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
868 return;
869
870 if (sc->sc_rts == NULL) {
871 sc->sc_rts = (struct bridge_rthead *)malloc(
872 BRIDGE_RTABLE_SIZE * (sizeof(struct bridge_rthead)),
873 M_DEVBUF, M_NOWAIT);
874 if (sc->sc_rts == NULL)
875 return;
876 for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
877 LIST_INIT(&sc->sc_rts[i]);
878 }
879 sc->sc_hashkey = arc4random();
880 }
881 ifp->if_flags |= IFF_RUNNING;
882 bstp_initialization(sc);
883
884 if (sc->sc_brttimeout != 0)
885 timeout_add(&sc->sc_brtimeout, sc->sc_brttimeout * hz);
886 }
887
888 /*
889 * Stop the bridge and deallocate the routing table.
890 */
891 void
bridge_stop(struct bridge_softc * sc)892 bridge_stop(struct bridge_softc *sc)
893 {
894 struct ifnet *ifp = &sc->sc_if;
895
896 /*
897 * If we're not running, there's nothing to do.
898 */
899 if ((ifp->if_flags & IFF_RUNNING) == 0)
900 return;
901
902 timeout_del(&sc->sc_brtimeout);
903
904 bridge_rtflush(sc, IFBF_FLUSHDYN);
905
906 ifp->if_flags &= ~IFF_RUNNING;
907 }
908
909 /*
910 * Send output from the bridge. The mbuf has the ethernet header
911 * already attached. We must enqueue or free the mbuf before exiting.
912 */
913 int
bridge_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * sa,struct rtentry * rt)914 bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
915 struct rtentry *rt)
916 {
917 struct ether_header *eh;
918 struct ifnet *dst_if;
919 struct ether_addr *src, *dst;
920 struct bridge_softc *sc;
921 int s, error, len;
922 #ifdef IPSEC
923 struct m_tag *mtag;
924 #endif /* IPSEC */
925
926 if (m->m_len < sizeof(*eh)) {
927 m = m_pullup(m, sizeof(*eh));
928 if (m == NULL)
929 return (0);
930 }
931 eh = mtod(m, struct ether_header *);
932 dst = (struct ether_addr *)&eh->ether_dhost[0];
933 src = (struct ether_addr *)&eh->ether_shost[0];
934 sc = (struct bridge_softc *)ifp->if_bridge;
935
936 s = splimp();
937
938 /*
939 * If bridge is down, but original output interface is up,
940 * go ahead and send out that interface. Otherwise the packet
941 * is dropped below.
942 */
943 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
944 dst_if = ifp;
945 goto sendunicast;
946 }
947
948 /*
949 * If the packet is a broadcast or we don't know a better way to
950 * get there, send to all interfaces.
951 */
952 dst_if = bridge_rtlookup(sc, dst);
953 if (dst_if == NULL || ETHER_IS_MULTICAST(eh->ether_dhost)) {
954 struct bridge_iflist *p;
955 struct mbuf *mc;
956 int used = 0;
957
958 #ifdef IPSEC
959 /*
960 * Don't send out the packet if IPsec is needed, and
961 * notify IPsec to do its own crypto for now.
962 */
963 if ((mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED,
964 NULL)) != NULL) {
965 ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
966 m_freem(m);
967 splx(s);
968 return (0);
969 }
970 #endif /* IPSEC */
971
972 /* Catch packets that need TCP/UDP/IP hardware checksumming */
973 if (m->m_pkthdr.csum & M_IPV4_CSUM_OUT ||
974 m->m_pkthdr.csum & M_TCPV4_CSUM_OUT ||
975 m->m_pkthdr.csum & M_UDPV4_CSUM_OUT) {
976 m_freem(m);
977 splx(s);
978 return (0);
979 }
980
981 bridge_span(sc, NULL, m);
982
983 LIST_FOREACH(p, &sc->sc_iflist, next) {
984 dst_if = p->ifp;
985 if ((dst_if->if_flags & IFF_RUNNING) == 0)
986 continue;
987
988 /*
989 * If this is not the original output interface,
990 * and the interface is participating in spanning
991 * tree, make sure the port is in a state that
992 * allows forwarding.
993 */
994 if (dst_if != ifp &&
995 (p->bif_flags & IFBIF_STP) &&
996 (p->bif_state != BSTP_IFSTATE_FORWARDING))
997 continue;
998
999 if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
1000 (m->m_flags & (M_BCAST | M_MCAST)) == 0)
1001 continue;
1002
1003 #ifdef ALTQ
1004 if (ALTQ_IS_ENABLED(&dst_if->if_snd) == 0)
1005 #endif
1006 if (IF_QFULL(&dst_if->if_snd)) {
1007 IF_DROP(&dst_if->if_snd);
1008 sc->sc_if.if_oerrors++;
1009 continue;
1010 }
1011 if (LIST_NEXT(p, next) == LIST_END(&sc->sc_iflist)) {
1012 used = 1;
1013 mc = m;
1014 } else {
1015 struct mbuf *m1, *m2, *mx;
1016
1017 m1 = m_copym2(m, 0, sizeof(struct ether_header),
1018 M_DONTWAIT);
1019 if (m1 == NULL) {
1020 sc->sc_if.if_oerrors++;
1021 continue;
1022 }
1023 m2 = m_copym2(m, sizeof(struct ether_header),
1024 M_COPYALL, M_DONTWAIT);
1025 if (m2 == NULL) {
1026 m_freem(m1);
1027 sc->sc_if.if_oerrors++;
1028 continue;
1029 }
1030
1031 for (mx = m1; mx->m_next != NULL; mx = mx->m_next)
1032 /*EMPTY*/;
1033 mx->m_next = m2;
1034
1035 if (m1->m_flags & M_PKTHDR) {
1036 len = 0;
1037 for (mx = m1; mx != NULL; mx = mx->m_next)
1038 len += mx->m_len;
1039 m1->m_pkthdr.len = len;
1040 }
1041 mc = m1;
1042 }
1043
1044 error = bridge_ifenqueue(sc, dst_if, mc);
1045 if (error)
1046 continue;
1047 }
1048 if (!used)
1049 m_freem(m);
1050 splx(s);
1051 return (0);
1052 }
1053
1054 sendunicast:
1055 bridge_span(sc, NULL, m);
1056 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1057 m_freem(m);
1058 splx(s);
1059 return (0);
1060 }
1061 bridge_ifenqueue(sc, dst_if, m);
1062 splx(s);
1063 return (0);
1064 }
1065
1066 /*
1067 * Start output on the bridge. This function should never be called.
1068 */
1069 void
bridge_start(struct ifnet * ifp)1070 bridge_start(struct ifnet *ifp)
1071 {
1072 }
1073
1074 /*
1075 * Loop through each bridge interface and process their input queues.
1076 */
1077 void
bridgeintr(void)1078 bridgeintr(void)
1079 {
1080 struct bridge_softc *sc;
1081 struct mbuf *m;
1082 int s;
1083
1084 LIST_FOREACH(sc, &bridge_list, sc_list) {
1085 for (;;) {
1086 s = splimp();
1087 IF_DEQUEUE(&sc->sc_if.if_snd, m);
1088 splx(s);
1089 if (m == NULL)
1090 break;
1091 bridgeintr_frame(sc, m);
1092 }
1093 }
1094 }
1095
1096 /*
1097 * Process a single frame. Frame must be freed or queued before returning.
1098 */
1099 void
bridgeintr_frame(struct bridge_softc * sc,struct mbuf * m)1100 bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
1101 {
1102 int s, len;
1103 struct ifnet *src_if, *dst_if;
1104 struct bridge_iflist *ifl;
1105 struct ether_addr *dst, *src;
1106 struct ether_header eh;
1107
1108 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
1109 m_freem(m);
1110 return;
1111 }
1112
1113 src_if = m->m_pkthdr.rcvif;
1114
1115 #if NBPFILTER > 0
1116 if (sc->sc_if.if_bpf)
1117 bpf_mtap(sc->sc_if.if_bpf, m);
1118 #endif
1119
1120 sc->sc_if.if_ipackets++;
1121 sc->sc_if.if_ibytes += m->m_pkthdr.len;
1122
1123 LIST_FOREACH(ifl, &sc->sc_iflist, next)
1124 if (ifl->ifp == src_if)
1125 break;
1126
1127 if (ifl == LIST_END(&sc->sc_iflist)) {
1128 m_freem(m);
1129 return;
1130 }
1131
1132 if ((ifl->bif_flags & IFBIF_STP) &&
1133 (ifl->bif_state == BSTP_IFSTATE_BLOCKING ||
1134 ifl->bif_state == BSTP_IFSTATE_LISTENING ||
1135 ifl->bif_state == BSTP_IFSTATE_DISABLED)) {
1136 m_freem(m);
1137 return;
1138 }
1139
1140 if (m->m_pkthdr.len < sizeof(eh)) {
1141 m_freem(m);
1142 return;
1143 }
1144 m_copydata(m, 0, sizeof(struct ether_header), (caddr_t)&eh);
1145 dst = (struct ether_addr *)&eh.ether_dhost[0];
1146 src = (struct ether_addr *)&eh.ether_shost[0];
1147
1148 /*
1149 * If interface is learning, and if source address
1150 * is not broadcast or multicast, record it's address.
1151 */
1152 if ((ifl->bif_flags & IFBIF_LEARNING) &&
1153 (eh.ether_shost[0] & 1) == 0 &&
1154 !(eh.ether_shost[0] == 0 && eh.ether_shost[1] == 0 &&
1155 eh.ether_shost[2] == 0 && eh.ether_shost[3] == 0 &&
1156 eh.ether_shost[4] == 0 && eh.ether_shost[5] == 0))
1157 bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC);
1158
1159 if ((ifl->bif_flags & IFBIF_STP) &&
1160 (ifl->bif_state == BSTP_IFSTATE_LEARNING)) {
1161 m_freem(m);
1162 return;
1163 }
1164
1165 /*
1166 * At this point, the port either doesn't participate in stp or
1167 * it's in the forwarding state
1168 */
1169
1170 /*
1171 * If packet is unicast, destined for someone on "this"
1172 * side of the bridge, drop it.
1173 */
1174 if ((m->m_flags & (M_BCAST | M_MCAST)) == 0) {
1175 dst_if = bridge_rtlookup(sc, dst);
1176 if (dst_if == src_if) {
1177 m_freem(m);
1178 return;
1179 }
1180 } else
1181 dst_if = NULL;
1182
1183 /*
1184 * Multicast packets get handled a little differently:
1185 * If interface is:
1186 * -link0,-link1 (default) Forward all multicast
1187 * as broadcast.
1188 * -link0,link1 Drop non-IP multicast, forward
1189 * as broadcast IP multicast.
1190 * link0,-link1 Drop IP multicast, forward as
1191 * broadcast non-IP multicast.
1192 * link0,link1 Drop all multicast.
1193 */
1194 if (m->m_flags & M_MCAST) {
1195 if ((sc->sc_if.if_flags &
1196 (IFF_LINK0 | IFF_LINK1)) ==
1197 (IFF_LINK0 | IFF_LINK1)) {
1198 m_freem(m);
1199 return;
1200 }
1201 if (sc->sc_if.if_flags & IFF_LINK0 &&
1202 ETHERADDR_IS_IP_MCAST(dst)) {
1203 m_freem(m);
1204 return;
1205 }
1206 if (sc->sc_if.if_flags & IFF_LINK1 &&
1207 !ETHERADDR_IS_IP_MCAST(dst)) {
1208 m_freem(m);
1209 return;
1210 }
1211 }
1212
1213 if (ifl->bif_flags & IFBIF_BLOCKNONIP && bridge_blocknonip(&eh, m)) {
1214 m_freem(m);
1215 return;
1216 }
1217
1218 if (bridge_filterrule(&ifl->bif_brlin, &eh, m) == BRL_ACTION_BLOCK) {
1219 m_freem(m);
1220 return;
1221 }
1222 #if NPF > 0
1223 m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m);
1224 if (m == NULL)
1225 return;
1226 #endif
1227 /*
1228 * If the packet is a multicast or broadcast OR if we don't
1229 * know any better, forward it to all interfaces.
1230 */
1231 if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) {
1232 sc->sc_if.if_imcasts++;
1233 s = splimp();
1234 bridge_broadcast(sc, src_if, &eh, m);
1235 splx(s);
1236 return;
1237 }
1238
1239 /*
1240 * At this point, we're dealing with a unicast frame going to a
1241 * different interface
1242 */
1243 if ((dst_if->if_flags & IFF_RUNNING) == 0) {
1244 m_freem(m);
1245 return;
1246 }
1247 LIST_FOREACH(ifl, &sc->sc_iflist, next) {
1248 if (ifl->ifp == dst_if)
1249 break;
1250 }
1251 if (ifl == LIST_END(&sc->sc_iflist)) {
1252 m_freem(m);
1253 return;
1254 }
1255 if ((ifl->bif_flags & IFBIF_STP) &&
1256 (ifl->bif_state == BSTP_IFSTATE_DISABLED ||
1257 ifl->bif_state == BSTP_IFSTATE_BLOCKING)) {
1258 m_freem(m);
1259 return;
1260 }
1261 if (bridge_filterrule(&ifl->bif_brlout, &eh, m) == BRL_ACTION_BLOCK) {
1262 m_freem(m);
1263 return;
1264 }
1265 #if NPF > 0
1266 m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m);
1267 if (m == NULL)
1268 return;
1269 #endif
1270
1271 len = m->m_pkthdr.len;
1272 if ((len - sizeof(struct ether_header)) > dst_if->if_mtu)
1273 bridge_fragment(sc, dst_if, &eh, m);
1274 else {
1275 s = splimp();
1276 bridge_ifenqueue(sc, dst_if, m);
1277 splx(s);
1278 }
1279 }
1280
1281 /*
1282 * Receive input from an interface. Queue the packet for bridging if its
1283 * not for us, and schedule an interrupt.
1284 */
1285 struct mbuf *
bridge_input(struct ifnet * ifp,struct ether_header * eh,struct mbuf * m)1286 bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
1287 {
1288 struct bridge_softc *sc;
1289 int s;
1290 struct bridge_iflist *ifl, *srcifl;
1291 struct arpcom *ac;
1292 struct mbuf *mc;
1293
1294 /*
1295 * Make sure this interface is a bridge member.
1296 */
1297 if (ifp == NULL || ifp->if_bridge == NULL || m == NULL)
1298 return (m);
1299
1300 if ((m->m_flags & M_PKTHDR) == 0)
1301 panic("bridge_input(): no HDR");
1302
1303 m->m_flags &= ~M_PROTO1; /* Loop prevention */
1304
1305 sc = (struct bridge_softc *)ifp->if_bridge;
1306 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
1307 return (m);
1308
1309 LIST_FOREACH(ifl, &sc->sc_iflist, next) {
1310 if (ifl->ifp == ifp)
1311 break;
1312 }
1313 if (ifl == LIST_END(&sc->sc_iflist))
1314 return (m);
1315
1316 bridge_span(sc, eh, m);
1317
1318 if (m->m_flags & (M_BCAST | M_MCAST)) {
1319 /* Tap off 802.1D packets, they do not get forwarded */
1320 if (bcmp(eh->ether_dhost, bstp_etheraddr, ETHER_ADDR_LEN) == 0) {
1321 m = bstp_input(sc, ifp, eh, m);
1322 if (m == NULL)
1323 return (NULL);
1324 }
1325
1326 /*
1327 * No need to queue frames for ifs in the blocking, disabled,
1328 * or listening state
1329 */
1330 if ((ifl->bif_flags & IFBIF_STP) &&
1331 ((ifl->bif_state == BSTP_IFSTATE_BLOCKING) ||
1332 (ifl->bif_state == BSTP_IFSTATE_LISTENING) ||
1333 (ifl->bif_state == BSTP_IFSTATE_DISABLED)))
1334 return (m);
1335
1336 /*
1337 * make a copy of 'm' with 'eh' tacked on to the
1338 * beginning. Return 'm' for local processing
1339 * and enqueue the copy. Schedule netisr.
1340 */
1341 mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT);
1342 if (mc == NULL)
1343 return (m);
1344 M_PREPEND(mc, sizeof(struct ether_header), M_DONTWAIT);
1345 if (mc == NULL)
1346 return (m);
1347 bcopy(eh, mtod(mc, caddr_t), sizeof(struct ether_header));
1348 s = splimp();
1349 if (IF_QFULL(&sc->sc_if.if_snd)) {
1350 m_freem(mc);
1351 splx(s);
1352 return (m);
1353 }
1354 IF_ENQUEUE(&sc->sc_if.if_snd, mc);
1355 splx(s);
1356 schednetisr(NETISR_BRIDGE);
1357 if (ifp->if_type == IFT_GIF) {
1358 LIST_FOREACH(ifl, &sc->sc_iflist, next) {
1359 if (ifl->ifp->if_type == IFT_ETHER)
1360 break;
1361 }
1362 if (ifl != LIST_END(&sc->sc_iflist)) {
1363 m->m_flags |= M_PROTO1;
1364 m->m_pkthdr.rcvif = ifl->ifp;
1365 ether_input(ifl->ifp, eh, m);
1366 m = NULL;
1367 }
1368 }
1369 return (m);
1370 }
1371
1372 /*
1373 * No need to queue frames for ifs in the blocking, disabled, or
1374 * listening state
1375 */
1376 if ((ifl->bif_flags & IFBIF_STP) &&
1377 ((ifl->bif_state == BSTP_IFSTATE_BLOCKING) ||
1378 (ifl->bif_state == BSTP_IFSTATE_LISTENING) ||
1379 (ifl->bif_state == BSTP_IFSTATE_DISABLED)))
1380 return (m);
1381
1382
1383 /*
1384 * Unicast, make sure it's not for us.
1385 */
1386 srcifl = ifl;
1387 LIST_FOREACH(ifl, &sc->sc_iflist, next) {
1388 if (ifl->ifp->if_type != IFT_ETHER)
1389 continue;
1390 ac = (struct arpcom *)ifl->ifp;
1391 if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) {
1392 if (srcifl->bif_flags & IFBIF_LEARNING)
1393 bridge_rtupdate(sc,
1394 (struct ether_addr *)&eh->ether_shost,
1395 ifp, 0, IFBAF_DYNAMIC);
1396 if (bridge_filterrule(&srcifl->bif_brlin, eh, m) ==
1397 BRL_ACTION_BLOCK) {
1398 m_freem(m);
1399 return (NULL);
1400 }
1401 m->m_pkthdr.rcvif = ifl->ifp;
1402 if (ifp->if_type == IFT_GIF) {
1403 m->m_flags |= M_PROTO1;
1404 ether_input(ifl->ifp, eh, m);
1405 m = NULL;
1406 }
1407 return (m);
1408 }
1409 if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1410 m_freem(m);
1411 return (NULL);
1412 }
1413 }
1414 M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
1415 if (m == NULL)
1416 return (NULL);
1417 bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header));
1418 s = splimp();
1419 if (IF_QFULL(&sc->sc_if.if_snd)) {
1420 m_freem(m);
1421 splx(s);
1422 return (NULL);
1423 }
1424 IF_ENQUEUE(&sc->sc_if.if_snd, m);
1425 splx(s);
1426 schednetisr(NETISR_BRIDGE);
1427 return (NULL);
1428 }
1429
1430 /*
1431 * Send a frame to all interfaces that are members of the bridge
1432 * (except the one it came in on). This code assumes that it is
1433 * running at splnet or higher.
1434 */
1435 void
bridge_broadcast(struct bridge_softc * sc,struct ifnet * ifp,struct ether_header * eh,struct mbuf * m)1436 bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
1437 struct ether_header *eh, struct mbuf *m)
1438 {
1439 struct bridge_iflist *p;
1440 struct mbuf *mc;
1441 struct ifnet *dst_if;
1442 int len = m->m_pkthdr.len, used = 0;
1443
1444 splassert(IPL_NET);
1445
1446 LIST_FOREACH(p, &sc->sc_iflist, next) {
1447 /*
1448 * Don't retransmit out of the same interface where
1449 * the packet was received from.
1450 */
1451 dst_if = p->ifp;
1452 if (dst_if->if_index == ifp->if_index)
1453 continue;
1454
1455 if ((p->bif_flags & IFBIF_STP) &&
1456 (p->bif_state != BSTP_IFSTATE_FORWARDING))
1457 continue;
1458
1459 if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
1460 (m->m_flags & (M_BCAST | M_MCAST)) == 0)
1461 continue;
1462
1463 if ((dst_if->if_flags & IFF_RUNNING) == 0)
1464 continue;
1465
1466 #ifdef ALTQ
1467 if (ALTQ_IS_ENABLED(&dst_if->if_snd) == 0)
1468 #endif
1469 if (IF_QFULL(&dst_if->if_snd)) {
1470 IF_DROP(&dst_if->if_snd);
1471 sc->sc_if.if_oerrors++;
1472 continue;
1473 }
1474
1475 /* Drop non-IP frames if the appropriate flag is set. */
1476 if (p->bif_flags & IFBIF_BLOCKNONIP &&
1477 bridge_blocknonip(eh, m))
1478 continue;
1479
1480 if (bridge_filterrule(&p->bif_brlout, eh, m) == BRL_ACTION_BLOCK)
1481 continue;
1482
1483 /* If last one, reuse the passed-in mbuf */
1484 if (LIST_NEXT(p, next) == LIST_END(&sc->sc_iflist)) {
1485 mc = m;
1486 used = 1;
1487 } else {
1488 struct mbuf *m1, *m2, *mx;
1489
1490 m1 = m_copym2(m, 0, sizeof(struct ether_header),
1491 M_DONTWAIT);
1492 if (m1 == NULL) {
1493 sc->sc_if.if_oerrors++;
1494 continue;
1495 }
1496 m2 = m_copym2(m, sizeof(struct ether_header),
1497 M_COPYALL, M_DONTWAIT);
1498 if (m2 == NULL) {
1499 m_freem(m1);
1500 sc->sc_if.if_oerrors++;
1501 continue;
1502 }
1503
1504 for (mx = m1; mx->m_next != NULL; mx = mx->m_next)
1505 /*EMPTY*/;
1506 mx->m_next = m2;
1507
1508 if (m1->m_flags & M_PKTHDR) {
1509 int len = 0;
1510
1511 for (mx = m1; mx != NULL; mx = mx->m_next)
1512 len += mx->m_len;
1513 m1->m_pkthdr.len = len;
1514 }
1515 mc = m1;
1516 }
1517
1518 #if NPF > 0
1519 mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc);
1520 if (mc == NULL)
1521 continue;
1522 #endif
1523
1524 if ((len - sizeof(struct ether_header)) > dst_if->if_mtu)
1525 bridge_fragment(sc, dst_if, eh, mc);
1526 else {
1527 bridge_ifenqueue(sc, dst_if, mc);
1528 }
1529 }
1530
1531 if (!used)
1532 m_freem(m);
1533 }
1534
1535 void
bridge_span(struct bridge_softc * sc,struct ether_header * eh,struct mbuf * morig)1536 bridge_span(struct bridge_softc *sc, struct ether_header *eh,
1537 struct mbuf *morig)
1538 {
1539 struct bridge_iflist *p;
1540 struct ifnet *ifp;
1541 struct mbuf *mc, *m;
1542 int error;
1543
1544 if (LIST_EMPTY(&sc->sc_spanlist))
1545 return;
1546
1547 m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT);
1548 if (m == NULL)
1549 return;
1550 if (eh != NULL) {
1551 M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
1552 if (m == NULL)
1553 return;
1554 bcopy(eh, mtod(m, caddr_t), sizeof(struct ether_header));
1555 }
1556
1557 LIST_FOREACH(p, &sc->sc_spanlist, next) {
1558 ifp = p->ifp;
1559
1560 if ((ifp->if_flags & IFF_RUNNING) == 0)
1561 continue;
1562
1563 #ifdef ALTQ
1564 if (ALTQ_IS_ENABLED(&ifp->if_snd) == 0)
1565 #endif
1566 if (IF_QFULL(&ifp->if_snd)) {
1567 IF_DROP(&ifp->if_snd);
1568 sc->sc_if.if_oerrors++;
1569 continue;
1570 }
1571
1572 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1573 if (mc == NULL) {
1574 sc->sc_if.if_oerrors++;
1575 continue;
1576 }
1577
1578 error = bridge_ifenqueue(sc, ifp, mc);
1579 if (error)
1580 continue;
1581 }
1582 m_freem(m);
1583 }
1584
1585 struct ifnet *
bridge_rtupdate(struct bridge_softc * sc,struct ether_addr * ea,struct ifnet * ifp,int setflags,u_int8_t flags)1586 bridge_rtupdate(struct bridge_softc *sc, struct ether_addr *ea,
1587 struct ifnet *ifp, int setflags, u_int8_t flags)
1588 {
1589 struct bridge_rtnode *p, *q;
1590 u_int32_t h;
1591 int dir;
1592
1593 if (sc->sc_rts == NULL) {
1594 if (setflags && flags == IFBAF_STATIC) {
1595 sc->sc_rts = (struct bridge_rthead *)malloc(
1596 BRIDGE_RTABLE_SIZE *
1597 (sizeof(struct bridge_rthead)),M_DEVBUF,M_NOWAIT);
1598 if (sc->sc_rts == NULL)
1599 goto done;
1600
1601 for (h = 0; h < BRIDGE_RTABLE_SIZE; h++) {
1602 LIST_INIT(&sc->sc_rts[h]);
1603 }
1604 sc->sc_hashkey = arc4random();
1605 } else
1606 goto done;
1607 }
1608
1609 h = bridge_hash(sc, ea);
1610 p = LIST_FIRST(&sc->sc_rts[h]);
1611 if (p == LIST_END(&sc->sc_rts[h])) {
1612 if (sc->sc_brtcnt >= sc->sc_brtmax)
1613 goto done;
1614 p = (struct bridge_rtnode *)malloc(
1615 sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1616 if (p == NULL)
1617 goto done;
1618
1619 bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1620 p->brt_if = ifp;
1621 p->brt_age = 1;
1622
1623 if (setflags)
1624 p->brt_flags = flags;
1625 else
1626 p->brt_flags = IFBAF_DYNAMIC;
1627
1628 LIST_INSERT_HEAD(&sc->sc_rts[h], p, brt_next);
1629 sc->sc_brtcnt++;
1630 goto want;
1631 }
1632
1633 do {
1634 q = p;
1635 p = LIST_NEXT(p, brt_next);
1636
1637 dir = memcmp(ea, &q->brt_addr, sizeof(q->brt_addr));
1638 if (dir == 0) {
1639 if (setflags) {
1640 q->brt_if = ifp;
1641 q->brt_flags = flags;
1642 }
1643
1644 if (q->brt_if == ifp)
1645 q->brt_age = 1;
1646 ifp = q->brt_if;
1647 goto want;
1648 }
1649
1650 if (dir > 0) {
1651 if (sc->sc_brtcnt >= sc->sc_brtmax)
1652 goto done;
1653 p = (struct bridge_rtnode *)malloc(
1654 sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1655 if (p == NULL)
1656 goto done;
1657
1658 bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1659 p->brt_if = ifp;
1660 p->brt_age = 1;
1661
1662 if (setflags)
1663 p->brt_flags = flags;
1664 else
1665 p->brt_flags = IFBAF_DYNAMIC;
1666
1667 LIST_INSERT_BEFORE(q, p, brt_next);
1668 sc->sc_brtcnt++;
1669 goto want;
1670 }
1671
1672 if (p == LIST_END(&sc->sc_rts[h])) {
1673 if (sc->sc_brtcnt >= sc->sc_brtmax)
1674 goto done;
1675 p = (struct bridge_rtnode *)malloc(
1676 sizeof(struct bridge_rtnode), M_DEVBUF, M_NOWAIT);
1677 if (p == NULL)
1678 goto done;
1679
1680 bcopy(ea, &p->brt_addr, sizeof(p->brt_addr));
1681 p->brt_if = ifp;
1682 p->brt_age = 1;
1683
1684 if (setflags)
1685 p->brt_flags = flags;
1686 else
1687 p->brt_flags = IFBAF_DYNAMIC;
1688 LIST_INSERT_AFTER(q, p, brt_next);
1689 sc->sc_brtcnt++;
1690 goto want;
1691 }
1692 } while (p != LIST_END(&sc->sc_rts[h]));
1693
1694 done:
1695 ifp = NULL;
1696 want:
1697 return (ifp);
1698 }
1699
1700 struct ifnet *
bridge_rtlookup(struct bridge_softc * sc,struct ether_addr * ea)1701 bridge_rtlookup(struct bridge_softc *sc, struct ether_addr *ea)
1702 {
1703 struct bridge_rtnode *p;
1704 u_int32_t h;
1705 int dir;
1706
1707 if (sc->sc_rts == NULL)
1708 goto fail;
1709
1710 h = bridge_hash(sc, ea);
1711 LIST_FOREACH(p, &sc->sc_rts[h], brt_next) {
1712 dir = memcmp(ea, &p->brt_addr, sizeof(p->brt_addr));
1713 if (dir == 0)
1714 return (p->brt_if);
1715 if (dir > 0)
1716 goto fail;
1717 }
1718 fail:
1719 return (NULL);
1720 }
1721
1722 /*
1723 * The following hash function is adapted from 'Hash Functions' by Bob Jenkins
1724 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997).
1725 * "You may use this code any way you wish, private, educational, or
1726 * commercial. It's free."
1727 */
1728 #define mix(a,b,c) \
1729 do { \
1730 a -= b; a -= c; a ^= (c >> 13); \
1731 b -= c; b -= a; b ^= (a << 8); \
1732 c -= a; c -= b; c ^= (b >> 13); \
1733 a -= b; a -= c; a ^= (c >> 12); \
1734 b -= c; b -= a; b ^= (a << 16); \
1735 c -= a; c -= b; c ^= (b >> 5); \
1736 a -= b; a -= c; a ^= (c >> 3); \
1737 b -= c; b -= a; b ^= (a << 10); \
1738 c -= a; c -= b; c ^= (b >> 15); \
1739 } while (0)
1740
1741 u_int32_t
bridge_hash(struct bridge_softc * sc,struct ether_addr * addr)1742 bridge_hash(struct bridge_softc *sc, struct ether_addr *addr)
1743 {
1744 u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_hashkey;
1745
1746 b += addr->ether_addr_octet[5] << 8;
1747 b += addr->ether_addr_octet[4];
1748 a += addr->ether_addr_octet[3] << 24;
1749 a += addr->ether_addr_octet[2] << 16;
1750 a += addr->ether_addr_octet[1] << 8;
1751 a += addr->ether_addr_octet[0];
1752
1753 mix(a, b, c);
1754 return (c & BRIDGE_RTABLE_MASK);
1755 }
1756
1757 /*
1758 * Trim the routing table so that we've got a number of routes
1759 * less than or equal to the maximum.
1760 */
1761 void
bridge_rttrim(struct bridge_softc * sc)1762 bridge_rttrim(struct bridge_softc *sc)
1763 {
1764 struct bridge_rtnode *n, *p;
1765 int i;
1766
1767 if (sc->sc_rts == NULL)
1768 goto done;
1769
1770 /*
1771 * Make sure we have to trim the address table
1772 */
1773 if (sc->sc_brtcnt <= sc->sc_brtmax)
1774 goto done;
1775
1776 /*
1777 * Force an aging cycle, this might trim enough addresses.
1778 */
1779 bridge_rtage(sc);
1780
1781 if (sc->sc_brtcnt <= sc->sc_brtmax)
1782 goto done;
1783
1784 for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1785 n = LIST_FIRST(&sc->sc_rts[i]);
1786 while (n != LIST_END(&sc->sc_rts[i])) {
1787 p = LIST_NEXT(n, brt_next);
1788 if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1789 LIST_REMOVE(n, brt_next);
1790 sc->sc_brtcnt--;
1791 free(n, M_DEVBUF);
1792 n = p;
1793 if (sc->sc_brtcnt <= sc->sc_brtmax)
1794 goto done;
1795 }
1796 }
1797 }
1798
1799 done:
1800 if (sc->sc_rts != NULL && sc->sc_brtcnt == 0 &&
1801 (sc->sc_if.if_flags & IFF_UP) == 0) {
1802 free(sc->sc_rts, M_DEVBUF);
1803 sc->sc_rts = NULL;
1804 }
1805 }
1806
1807 void
bridge_timer(void * vsc)1808 bridge_timer(void *vsc)
1809 {
1810 struct bridge_softc *sc = vsc;
1811 int s;
1812
1813 s = splsoftnet();
1814 bridge_rtage(sc);
1815 splx(s);
1816 }
1817
1818 /*
1819 * Perform an aging cycle
1820 */
1821 void
bridge_rtage(struct bridge_softc * sc)1822 bridge_rtage(struct bridge_softc *sc)
1823 {
1824 struct bridge_rtnode *n, *p;
1825 int i;
1826
1827 if (sc->sc_rts == NULL)
1828 return;
1829
1830 for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1831 n = LIST_FIRST(&sc->sc_rts[i]);
1832 while (n != LIST_END(&sc->sc_rts[i])) {
1833 if ((n->brt_flags & IFBAF_TYPEMASK) == IFBAF_STATIC) {
1834 n->brt_age = !n->brt_age;
1835 if (n->brt_age)
1836 n->brt_age = 0;
1837 n = LIST_NEXT(n, brt_next);
1838 } else if (n->brt_age) {
1839 n->brt_age = 0;
1840 n = LIST_NEXT(n, brt_next);
1841 } else {
1842 p = LIST_NEXT(n, brt_next);
1843 LIST_REMOVE(n, brt_next);
1844 sc->sc_brtcnt--;
1845 free(n, M_DEVBUF);
1846 n = p;
1847 }
1848 }
1849 }
1850
1851 if (sc->sc_brttimeout != 0)
1852 timeout_add(&sc->sc_brtimeout, sc->sc_brttimeout * hz);
1853 }
1854
1855 /*
1856 * Remove all dynamic addresses from the cache
1857 */
1858 int
bridge_rtflush(struct bridge_softc * sc,int full)1859 bridge_rtflush(struct bridge_softc *sc, int full)
1860 {
1861 int i;
1862 struct bridge_rtnode *p, *n;
1863
1864 if (sc->sc_rts == NULL)
1865 return (0);
1866
1867 for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1868 n = LIST_FIRST(&sc->sc_rts[i]);
1869 while (n != LIST_END(&sc->sc_rts[i])) {
1870 if (full ||
1871 (n->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) {
1872 p = LIST_NEXT(n, brt_next);
1873 LIST_REMOVE(n, brt_next);
1874 sc->sc_brtcnt--;
1875 free(n, M_DEVBUF);
1876 n = p;
1877 } else
1878 n = LIST_NEXT(n, brt_next);
1879 }
1880 }
1881
1882 if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
1883 free(sc->sc_rts, M_DEVBUF);
1884 sc->sc_rts = NULL;
1885 }
1886
1887 return (0);
1888 }
1889
1890 /*
1891 * Remove an address from the cache
1892 */
1893 int
bridge_rtdaddr(struct bridge_softc * sc,struct ether_addr * ea)1894 bridge_rtdaddr(struct bridge_softc *sc, struct ether_addr *ea)
1895 {
1896 int h;
1897 struct bridge_rtnode *p;
1898
1899 if (sc->sc_rts == NULL)
1900 return (ENOENT);
1901
1902 h = bridge_hash(sc, ea);
1903 LIST_FOREACH(p, &sc->sc_rts[h], brt_next) {
1904 if (bcmp(ea, &p->brt_addr, sizeof(p->brt_addr)) == 0) {
1905 LIST_REMOVE(p, brt_next);
1906 sc->sc_brtcnt--;
1907 free(p, M_DEVBUF);
1908 if (sc->sc_brtcnt == 0 &&
1909 (sc->sc_if.if_flags & IFF_UP) == 0) {
1910 free(sc->sc_rts, M_DEVBUF);
1911 sc->sc_rts = NULL;
1912 }
1913 return (0);
1914 }
1915 }
1916
1917 return (ENOENT);
1918 }
1919 /*
1920 * Delete routes to a specific interface member.
1921 */
1922 void
bridge_rtdelete(struct bridge_softc * sc,struct ifnet * ifp,int dynonly)1923 bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp, int dynonly)
1924 {
1925 int i;
1926 struct bridge_rtnode *n, *p;
1927
1928 if (sc->sc_rts == NULL)
1929 return;
1930
1931 /*
1932 * Loop through all of the hash buckets and traverse each
1933 * chain looking for routes to this interface.
1934 */
1935 for (i = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1936 n = LIST_FIRST(&sc->sc_rts[i]);
1937 while (n != LIST_END(&sc->sc_rts[i])) {
1938 if (n->brt_if != ifp) {
1939 /* Not ours */
1940 n = LIST_NEXT(n, brt_next);
1941 continue;
1942 }
1943 if (dynonly &&
1944 (n->brt_flags & IFBAF_TYPEMASK) != IFBAF_DYNAMIC) {
1945 /* only deleting dynamics */
1946 n = LIST_NEXT(n, brt_next);
1947 continue;
1948 }
1949 p = LIST_NEXT(n, brt_next);
1950 LIST_REMOVE(n, brt_next);
1951 sc->sc_brtcnt--;
1952 free(n, M_DEVBUF);
1953 n = p;
1954 }
1955 }
1956 if (sc->sc_brtcnt == 0 && (sc->sc_if.if_flags & IFF_UP) == 0) {
1957 free(sc->sc_rts, M_DEVBUF);
1958 sc->sc_rts = NULL;
1959 }
1960 }
1961
1962 /*
1963 * Gather all of the routes for this interface.
1964 */
1965 int
bridge_rtfind(struct bridge_softc * sc,struct ifbaconf * baconf)1966 bridge_rtfind(struct bridge_softc *sc, struct ifbaconf *baconf)
1967 {
1968 int i, error = 0, onlycnt = 0;
1969 u_int32_t cnt = 0;
1970 struct bridge_rtnode *n;
1971 struct ifbareq bareq;
1972
1973 if (sc->sc_rts == NULL)
1974 goto done;
1975
1976 if (baconf->ifbac_len == 0)
1977 onlycnt = 1;
1978
1979 for (i = 0, cnt = 0; i < BRIDGE_RTABLE_SIZE; i++) {
1980 LIST_FOREACH(n, &sc->sc_rts[i], brt_next) {
1981 if (!onlycnt) {
1982 if (baconf->ifbac_len < sizeof(struct ifbareq))
1983 goto done;
1984 bcopy(sc->sc_if.if_xname, bareq.ifba_name,
1985 sizeof(bareq.ifba_name));
1986 bcopy(n->brt_if->if_xname, bareq.ifba_ifsname,
1987 sizeof(bareq.ifba_ifsname));
1988 bcopy(&n->brt_addr, &bareq.ifba_dst,
1989 sizeof(bareq.ifba_dst));
1990 bareq.ifba_age = n->brt_age;
1991 bareq.ifba_flags = n->brt_flags;
1992 error = copyout((caddr_t)&bareq,
1993 (caddr_t)(baconf->ifbac_req + cnt), sizeof(bareq));
1994 if (error)
1995 goto done;
1996 baconf->ifbac_len -= sizeof(struct ifbareq);
1997 }
1998 cnt++;
1999 }
2000 }
2001 done:
2002 baconf->ifbac_len = cnt * sizeof(struct ifbareq);
2003 return (error);
2004 }
2005
2006 /*
2007 * Block non-ip frames:
2008 * Returns 0 if frame is ip, and 1 if it should be dropped.
2009 */
2010 int
bridge_blocknonip(struct ether_header * eh,struct mbuf * m)2011 bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
2012 {
2013 struct llc llc;
2014 u_int16_t etype;
2015
2016 if (m->m_pkthdr.len < sizeof(struct ether_header))
2017 return (1);
2018
2019 etype = ntohs(eh->ether_type);
2020 switch (etype) {
2021 case ETHERTYPE_ARP:
2022 case ETHERTYPE_REVARP:
2023 case ETHERTYPE_IP:
2024 case ETHERTYPE_IPV6:
2025 return (0);
2026 }
2027
2028 if (etype > ETHERMTU)
2029 return (1);
2030
2031 if (m->m_pkthdr.len <
2032 (sizeof(struct ether_header) + LLC_SNAPFRAMELEN))
2033 return (1);
2034
2035 m_copydata(m, sizeof(struct ether_header), LLC_SNAPFRAMELEN,
2036 (caddr_t)&llc);
2037
2038 etype = ntohs(llc.llc_snap.ether_type);
2039 if (llc.llc_dsap == LLC_SNAP_LSAP &&
2040 llc.llc_ssap == LLC_SNAP_LSAP &&
2041 llc.llc_control == LLC_UI &&
2042 llc.llc_snap.org_code[0] == 0 &&
2043 llc.llc_snap.org_code[1] == 0 &&
2044 llc.llc_snap.org_code[2] == 0 &&
2045 (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
2046 etype == ETHERTYPE_IP || etype == ETHERTYPE_IPV6)) {
2047 return (0);
2048 }
2049
2050 return (1);
2051 }
2052
2053 u_int8_t
bridge_filterrule(struct brl_head * h,struct ether_header * eh,struct mbuf * m)2054 bridge_filterrule(struct brl_head *h, struct ether_header *eh, struct mbuf *m)
2055 {
2056 struct brl_node *n;
2057 u_int8_t flags;
2058
2059 SIMPLEQ_FOREACH(n, h, brl_next) {
2060 flags = n->brl_flags & (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID);
2061 if (flags == 0)
2062 goto return_action;
2063 if (flags == (BRL_FLAG_SRCVALID|BRL_FLAG_DSTVALID)) {
2064 if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
2065 continue;
2066 if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
2067 continue;
2068 goto return_action;
2069 }
2070 if (flags == BRL_FLAG_SRCVALID) {
2071 if (bcmp(eh->ether_shost, &n->brl_src, ETHER_ADDR_LEN))
2072 continue;
2073 goto return_action;
2074 }
2075 if (flags == BRL_FLAG_DSTVALID) {
2076 if (bcmp(eh->ether_dhost, &n->brl_dst, ETHER_ADDR_LEN))
2077 continue;
2078 goto return_action;
2079 }
2080 }
2081 return (BRL_ACTION_PASS);
2082
2083 return_action:
2084 #if NPF > 0
2085 pf_tag_packet(m, NULL, n->brl_tag);
2086 #endif
2087 return (n->brl_action);
2088 }
2089
2090 int
bridge_addrule(struct bridge_iflist * bif,struct ifbrlreq * req,int out)2091 bridge_addrule(struct bridge_iflist *bif, struct ifbrlreq *req, int out)
2092 {
2093 struct brl_node *n;
2094
2095 n = (struct brl_node *)malloc(sizeof(struct brl_node), M_DEVBUF, M_NOWAIT);
2096 if (n == NULL)
2097 return (ENOMEM);
2098 bcopy(&req->ifbr_src, &n->brl_src, sizeof(struct ether_addr));
2099 bcopy(&req->ifbr_dst, &n->brl_dst, sizeof(struct ether_addr));
2100 n->brl_action = req->ifbr_action;
2101 n->brl_flags = req->ifbr_flags;
2102 #if NPF > 0
2103 if (req->ifbr_tagname[0])
2104 n->brl_tag = pf_tagname2tag(req->ifbr_tagname);
2105 else
2106 n->brl_tag = 0;
2107 #endif
2108 if (out) {
2109 n->brl_flags &= ~BRL_FLAG_IN;
2110 n->brl_flags |= BRL_FLAG_OUT;
2111 SIMPLEQ_INSERT_TAIL(&bif->bif_brlout, n, brl_next);
2112 } else {
2113 n->brl_flags &= ~BRL_FLAG_OUT;
2114 n->brl_flags |= BRL_FLAG_IN;
2115 SIMPLEQ_INSERT_TAIL(&bif->bif_brlin, n, brl_next);
2116 }
2117 return (0);
2118 }
2119
2120 int
bridge_flushrule(struct bridge_iflist * bif)2121 bridge_flushrule(struct bridge_iflist *bif)
2122 {
2123 struct brl_node *p;
2124
2125 while (!SIMPLEQ_EMPTY(&bif->bif_brlin)) {
2126 p = SIMPLEQ_FIRST(&bif->bif_brlin);
2127 SIMPLEQ_REMOVE_HEAD(&bif->bif_brlin, brl_next);
2128 #if NPF > 0
2129 pf_tag_unref(p->brl_tag);
2130 #endif
2131 free(p, M_DEVBUF);
2132 }
2133 while (!SIMPLEQ_EMPTY(&bif->bif_brlout)) {
2134 p = SIMPLEQ_FIRST(&bif->bif_brlout);
2135 SIMPLEQ_REMOVE_HEAD(&bif->bif_brlout, brl_next);
2136 #if NPF > 0
2137 pf_tag_unref(p->brl_tag);
2138 #endif
2139 free(p, M_DEVBUF);
2140 }
2141 return (0);
2142 }
2143
2144 #ifdef IPSEC
2145 int
bridge_ipsec(int dir,int af,int hlen,struct mbuf * m)2146 bridge_ipsec(int dir, int af, int hlen, struct mbuf *m)
2147 {
2148 union sockaddr_union dst;
2149 struct timeval tv;
2150 struct tdb *tdb;
2151 u_int32_t spi;
2152 u_int16_t cpi;
2153 int error, off = 0, s;
2154 u_int8_t proto = 0;
2155 #ifdef INET
2156 struct ip *ip;
2157 #endif /* INET */
2158 #ifdef INET6
2159 struct ip6_hdr *ip6;
2160 #endif /* INET6 */
2161
2162 if (dir == BRIDGE_IN) {
2163 switch (af) {
2164 #ifdef INET
2165 case AF_INET:
2166 if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
2167 break;
2168
2169 ip = mtod(m, struct ip *);
2170 proto = ip->ip_p;
2171 off = offsetof(struct ip, ip_p);
2172
2173 if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
2174 proto != IPPROTO_IPCOMP)
2175 goto skiplookup;
2176
2177 bzero(&dst, sizeof(union sockaddr_union));
2178 dst.sa.sa_family = AF_INET;
2179 dst.sin.sin_len = sizeof(struct sockaddr_in);
2180 m_copydata(m, offsetof(struct ip, ip_dst),
2181 sizeof(struct in_addr),
2182 (caddr_t)&dst.sin.sin_addr);
2183
2184 if (ip->ip_p == IPPROTO_ESP)
2185 m_copydata(m, hlen, sizeof(u_int32_t),
2186 (caddr_t)&spi);
2187 else if (ip->ip_p == IPPROTO_AH)
2188 m_copydata(m, hlen + sizeof(u_int32_t),
2189 sizeof(u_int32_t), (caddr_t)&spi);
2190 else if (ip->ip_p == IPPROTO_IPCOMP) {
2191 m_copydata(m, hlen + sizeof(u_int16_t),
2192 sizeof(u_int16_t), (caddr_t)&cpi);
2193 spi = ntohl(htons(cpi));
2194 }
2195 break;
2196 #endif /* INET */
2197 #ifdef INET6
2198 case AF_INET6:
2199 if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
2200 break;
2201
2202 ip6 = mtod(m, struct ip6_hdr *);
2203
2204 /* XXX We should chase down the header chain */
2205 proto = ip6->ip6_nxt;
2206 off = offsetof(struct ip6_hdr, ip6_nxt);
2207
2208 if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
2209 proto != IPPROTO_IPCOMP)
2210 goto skiplookup;
2211
2212 bzero(&dst, sizeof(union sockaddr_union));
2213 dst.sa.sa_family = AF_INET6;
2214 dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
2215 m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
2216 sizeof(struct in6_addr),
2217 (caddr_t)&dst.sin6.sin6_addr);
2218
2219 if (proto == IPPROTO_ESP)
2220 m_copydata(m, hlen, sizeof(u_int32_t),
2221 (caddr_t)&spi);
2222 else if (proto == IPPROTO_AH)
2223 m_copydata(m, hlen + sizeof(u_int32_t),
2224 sizeof(u_int32_t), (caddr_t)&spi);
2225 else if (proto == IPPROTO_IPCOMP) {
2226 m_copydata(m, hlen + sizeof(u_int16_t),
2227 sizeof(u_int16_t), (caddr_t)&cpi);
2228 spi = ntohl(htons(cpi));
2229 }
2230 break;
2231 #endif /* INET6 */
2232 default:
2233 return (0);
2234 }
2235
2236 if (proto == 0)
2237 goto skiplookup;
2238
2239 s = spltdb();
2240
2241 tdb = gettdb(spi, &dst, proto);
2242 if (tdb != NULL && (tdb->tdb_flags & TDBF_INVALID) == 0 &&
2243 tdb->tdb_xform != NULL) {
2244 if (tdb->tdb_first_use == 0) {
2245 int pri;
2246
2247 pri = splhigh();
2248 tdb->tdb_first_use = time.tv_sec;
2249 splx(pri);
2250
2251 tv.tv_usec = 0;
2252
2253 /* Check for wrap-around. */
2254 if (tdb->tdb_exp_first_use + tdb->tdb_first_use
2255 < tdb->tdb_first_use)
2256 tv.tv_sec = ((unsigned long)-1) / 2;
2257 else
2258 tv.tv_sec = tdb->tdb_exp_first_use +
2259 tdb->tdb_first_use;
2260
2261 if (tdb->tdb_flags & TDBF_FIRSTUSE)
2262 timeout_add(&tdb->tdb_first_tmo,
2263 hzto(&tv));
2264
2265 /* Check for wrap-around. */
2266 if (tdb->tdb_first_use +
2267 tdb->tdb_soft_first_use
2268 < tdb->tdb_first_use)
2269 tv.tv_sec = ((unsigned long)-1) / 2;
2270 else
2271 tv.tv_sec = tdb->tdb_first_use +
2272 tdb->tdb_soft_first_use;
2273
2274 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
2275 timeout_add(&tdb->tdb_sfirst_tmo,
2276 hzto(&tv));
2277 }
2278
2279 (*(tdb->tdb_xform->xf_input))(m, tdb, hlen, off);
2280 splx(s);
2281 return (1);
2282 } else {
2283 splx(s);
2284 skiplookup:
2285 /* XXX do an input policy lookup */
2286 return (0);
2287 }
2288 } else { /* Outgoing from the bridge. */
2289 tdb = ipsp_spd_lookup(m, af, hlen, &error,
2290 IPSP_DIRECTION_OUT, NULL, NULL);
2291 if (tdb != NULL) {
2292 /*
2293 * We don't need to do loop detection, the
2294 * bridge will do that for us.
2295 */
2296 #if NPF > 0
2297 switch (af) {
2298 #ifdef INET
2299 case AF_INET:
2300 if (pf_test(dir, &encif[0].sc_if,
2301 &m) != PF_PASS) {
2302 m_freem(m);
2303 return (1);
2304 }
2305 break;
2306 #endif /* INET */
2307 #ifdef INET6
2308 case AF_INET6:
2309 if (pf_test6(dir, &encif[0].sc_if,
2310 &m) != PF_PASS) {
2311 m_freem(m);
2312 return (1);
2313 }
2314 break;
2315 #endif /* INET6 */
2316 }
2317 if (m == NULL)
2318 return (1);
2319 #endif /* NPF */
2320 error = ipsp_process_packet(m, tdb, af, 0);
2321 return (1);
2322 } else
2323 return (0);
2324 }
2325
2326 return (0);
2327 }
2328 #endif /* IPSEC */
2329
2330 #if NPF > 0
2331 /*
2332 * Filter IP packets by peeking into the ethernet frame. This violates
2333 * the ISO model, but allows us to act as a IP filter at the data link
2334 * layer. As a result, most of this code will look familiar to those
2335 * who've read net/if_ethersubr.c and netinet/ip_input.c
2336 */
2337 struct mbuf *
bridge_filter(struct bridge_softc * sc,int dir,struct ifnet * ifp,struct ether_header * eh,struct mbuf * m)2338 bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
2339 struct ether_header *eh, struct mbuf *m)
2340 {
2341 struct llc llc;
2342 int hassnap = 0;
2343 struct ip *ip;
2344 int hlen;
2345 u_int16_t etype;
2346
2347 etype = ntohs(eh->ether_type);
2348
2349 if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
2350 if (etype > ETHERMTU ||
2351 m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
2352 sizeof(struct ether_header)))
2353 return (m);
2354
2355 m_copydata(m, sizeof(struct ether_header),
2356 LLC_SNAPFRAMELEN, (caddr_t)&llc);
2357
2358 if (llc.llc_dsap != LLC_SNAP_LSAP ||
2359 llc.llc_ssap != LLC_SNAP_LSAP ||
2360 llc.llc_control != LLC_UI ||
2361 llc.llc_snap.org_code[0] ||
2362 llc.llc_snap.org_code[1] ||
2363 llc.llc_snap.org_code[2])
2364 return (m);
2365
2366 etype = ntohs(llc.llc_snap.ether_type);
2367 if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
2368 return (m);
2369 hassnap = 1;
2370 }
2371
2372 m_adj(m, sizeof(struct ether_header));
2373 if (hassnap)
2374 m_adj(m, LLC_SNAPFRAMELEN);
2375
2376 switch (etype) {
2377
2378 case ETHERTYPE_IP:
2379 if (m->m_pkthdr.len < sizeof(struct ip))
2380 goto dropit;
2381
2382 /* Copy minimal header, and drop invalids */
2383 if (m->m_len < sizeof(struct ip) &&
2384 (m = m_pullup(m, sizeof(struct ip))) == NULL) {
2385 ipstat.ips_toosmall++;
2386 return (NULL);
2387 }
2388 ip = mtod(m, struct ip *);
2389
2390 if (ip->ip_v != IPVERSION) {
2391 ipstat.ips_badvers++;
2392 goto dropit;
2393 }
2394
2395 hlen = ip->ip_hl << 2; /* get whole header length */
2396 if (hlen < sizeof(struct ip)) {
2397 ipstat.ips_badhlen++;
2398 goto dropit;
2399 }
2400
2401 if (hlen > m->m_len) {
2402 if ((m = m_pullup(m, hlen)) == NULL) {
2403 ipstat.ips_badhlen++;
2404 return (NULL);
2405 }
2406 ip = mtod(m, struct ip *);
2407 }
2408
2409 if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
2410 ipstat.ips_badsum++;
2411 goto dropit;
2412 }
2413
2414 if (ntohs(ip->ip_len) < hlen)
2415 goto dropit;
2416
2417 if (m->m_pkthdr.len < ntohs(ip->ip_len))
2418 goto dropit;
2419 if (m->m_pkthdr.len > ntohs(ip->ip_len)) {
2420 if (m->m_len == m->m_pkthdr.len) {
2421 m->m_len = ntohs(ip->ip_len);
2422 m->m_pkthdr.len = ntohs(ip->ip_len);
2423 } else
2424 m_adj(m, ntohs(ip->ip_len) - m->m_pkthdr.len);
2425 }
2426
2427 #ifdef IPSEC
2428 if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
2429 bridge_ipsec(dir, AF_INET, hlen, m))
2430 return (NULL);
2431 #endif /* IPSEC */
2432
2433 #if NPF > 0
2434 /* Finally, we get to filter the packet! */
2435 m->m_pkthdr.rcvif = ifp;
2436 if (pf_test_eh(dir, ifp, &m, eh) != PF_PASS)
2437 goto dropit;
2438 if (m == NULL)
2439 goto dropit;
2440 #endif /* NPF */
2441
2442 /* Rebuild the IP header */
2443 if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
2444 return (NULL);
2445 if (m->m_len < sizeof(struct ip))
2446 goto dropit;
2447 ip = mtod(m, struct ip *);
2448 ip->ip_sum = 0;
2449 ip->ip_sum = in_cksum(m, hlen);
2450
2451 break;
2452
2453 #ifdef INET6
2454 case ETHERTYPE_IPV6: {
2455 struct ip6_hdr *ip6;
2456
2457 if (m->m_len < sizeof(struct ip6_hdr)) {
2458 if ((m = m_pullup(m, sizeof(struct ip6_hdr)))
2459 == NULL) {
2460 ip6stat.ip6s_toosmall++;
2461 return (NULL);
2462 }
2463 }
2464
2465 ip6 = mtod(m, struct ip6_hdr *);
2466
2467 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
2468 ip6stat.ip6s_badvers++;
2469 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
2470 goto dropit;
2471 }
2472
2473 #ifdef IPSEC
2474 hlen = sizeof(struct ip6_hdr);
2475
2476 if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
2477 bridge_ipsec(dir, AF_INET6, hlen, m))
2478 return (NULL);
2479 #endif /* IPSEC */
2480
2481 #if NPF > 0
2482 if (pf_test6_eh(dir, ifp, &m, eh) != PF_PASS)
2483 goto dropit;
2484 if (m == NULL)
2485 return (NULL);
2486 #endif /* NPF */
2487
2488 break;
2489 }
2490 #endif /* INET6 */
2491
2492 default:
2493 goto dropit;
2494 break;
2495 }
2496
2497 /* Reattach SNAP header */
2498 if (hassnap) {
2499 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
2500 if (m == NULL)
2501 goto dropit;
2502 bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
2503 }
2504
2505 /* Reattach ethernet header */
2506 M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
2507 if (m == NULL)
2508 goto dropit;
2509 bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
2510
2511 return (m);
2512
2513 dropit:
2514 if (m != NULL)
2515 m_freem(m);
2516 return (NULL);
2517 }
2518 #endif /* NPF > 0 */
2519
2520 void
bridge_fragment(struct bridge_softc * sc,struct ifnet * ifp,struct ether_header * eh,struct mbuf * m)2521 bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
2522 struct ether_header *eh, struct mbuf *m)
2523 {
2524 struct llc llc;
2525 struct mbuf *m0;
2526 int s, len, error = 0;
2527 int hassnap = 0;
2528 #ifdef INET
2529 u_int16_t etype;
2530 struct ip *ip;
2531 #endif
2532
2533 #ifndef INET
2534 goto dropit;
2535 #else
2536 etype = ntohs(eh->ether_type);
2537 #if NVLAN > 0
2538 if (etype == ETHERTYPE_8021Q &&
2539 (ifp->if_capabilities & IFCAP_VLAN_MTU) &&
2540 ((m->m_pkthdr.len - sizeof(struct ether_vlan_header)) <=
2541 ifp->if_mtu)) {
2542 s = splimp();
2543 bridge_ifenqueue(sc, ifp, m);
2544 splx(s);
2545 return;
2546 }
2547 #endif
2548 if (etype != ETHERTYPE_IP) {
2549 if (etype > ETHERMTU ||
2550 m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
2551 sizeof(struct ether_header)))
2552 goto dropit;
2553
2554 m_copydata(m, sizeof(struct ether_header),
2555 LLC_SNAPFRAMELEN, (caddr_t)&llc);
2556
2557 if (llc.llc_dsap != LLC_SNAP_LSAP ||
2558 llc.llc_ssap != LLC_SNAP_LSAP ||
2559 llc.llc_control != LLC_UI ||
2560 llc.llc_snap.org_code[0] ||
2561 llc.llc_snap.org_code[1] ||
2562 llc.llc_snap.org_code[2] ||
2563 llc.llc_snap.ether_type != htons(ETHERTYPE_IP))
2564 goto dropit;
2565
2566 hassnap = 1;
2567 }
2568
2569 m_adj(m, sizeof(struct ether_header));
2570 if (hassnap)
2571 m_adj(m, LLC_SNAPFRAMELEN);
2572
2573 if (m->m_len < sizeof(struct ip) &&
2574 (m = m_pullup(m, sizeof(struct ip))) == NULL)
2575 goto dropit;
2576 ip = mtod(m, struct ip *);
2577
2578 /* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
2579 if (ip->ip_off & htons(IP_DF)) {
2580 bridge_send_icmp_err(sc, ifp, eh, m, hassnap, &llc,
2581 ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
2582 return;
2583 }
2584
2585 error = ip_fragment(m, ifp, ifp->if_mtu);
2586 if (error) {
2587 m = NULL;
2588 goto dropit;
2589 }
2590
2591 for (; m; m = m0) {
2592 m0 = m->m_nextpkt;
2593 m->m_nextpkt = NULL;
2594 if (error == 0) {
2595 if (hassnap) {
2596 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
2597 if (m == NULL) {
2598 error = ENOBUFS;
2599 continue;
2600 }
2601 bcopy(&llc, mtod(m, caddr_t),
2602 LLC_SNAPFRAMELEN);
2603 }
2604 M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
2605 if (m == NULL) {
2606 error = ENOBUFS;
2607 continue;
2608 }
2609 len = m->m_pkthdr.len;
2610 bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
2611 s = splimp();
2612 error = bridge_ifenqueue(sc, ifp, m);
2613 if (error) {
2614 splx(s);
2615 continue;
2616 }
2617 splx(s);
2618 } else
2619 m_freem(m);
2620 }
2621
2622 if (error == 0)
2623 ipstat.ips_fragmented++;
2624
2625 return;
2626 #endif /* INET */
2627 dropit:
2628 if (m != NULL)
2629 m_freem(m);
2630 }
2631
2632 int
bridge_ifenqueue(struct bridge_softc * sc,struct ifnet * ifp,struct mbuf * m)2633 bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
2634 {
2635 int error, len;
2636 short mflags;
2637
2638 len = m->m_pkthdr.len;
2639 mflags = m->m_flags;
2640 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
2641 if (error) {
2642 sc->sc_if.if_oerrors++;
2643 return (error);
2644 }
2645 sc->sc_if.if_opackets++;
2646 sc->sc_if.if_obytes += len;
2647 ifp->if_obytes += len;
2648 if (mflags & M_MCAST)
2649 ifp->if_omcasts++;
2650 if ((ifp->if_flags & IFF_OACTIVE) == 0)
2651 (*ifp->if_start)(ifp);
2652
2653 return (0);
2654 }
2655
2656 #ifdef INET
2657 void
bridge_send_icmp_err(struct bridge_softc * sc,struct ifnet * ifp,struct ether_header * eh,struct mbuf * n,int hassnap,struct llc * llc,int type,int code)2658 bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
2659 struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
2660 int type, int code)
2661 {
2662 struct ip *ip;
2663 struct icmp *icp;
2664 struct in_addr t;
2665 struct mbuf *m, *n2;
2666 int hlen;
2667 u_int8_t ether_tmp[ETHER_ADDR_LEN];
2668
2669 n2 = m_copym(n, 0, M_COPYALL, M_DONTWAIT);
2670 if (!n2) {
2671 m_freem(n);
2672 return;
2673 }
2674 m = icmp_do_error(n, type, code, 0, ifp);
2675 if (m == NULL) {
2676 m_freem(n2);
2677 return;
2678 }
2679
2680 n = n2;
2681
2682 ip = mtod(m, struct ip *);
2683 hlen = ip->ip_hl << 2;
2684 t = ip->ip_dst;
2685 ip->ip_dst = ip->ip_src;
2686 ip->ip_src = t;
2687
2688 m->m_data += hlen;
2689 m->m_len -= hlen;
2690 icp = mtod(m, struct icmp *);
2691 icp->icmp_cksum = 0;
2692 icp->icmp_cksum = in_cksum(m, ntohs(ip->ip_len) - hlen);
2693 m->m_data -= hlen;
2694 m->m_len += hlen;
2695
2696 ip->ip_v = IPVERSION;
2697 ip->ip_off &= htons(IP_DF);
2698 ip->ip_id = htons(ip_randomid());
2699 ip->ip_ttl = MAXTTL;
2700 ip->ip_sum = 0;
2701 ip->ip_sum = in_cksum(m, hlen);
2702
2703 /* Swap ethernet addresses */
2704 bcopy(&eh->ether_dhost, ðer_tmp, sizeof(ether_tmp));
2705 bcopy(&eh->ether_shost, &eh->ether_dhost, sizeof(ether_tmp));
2706 bcopy(ðer_tmp, &eh->ether_shost, sizeof(ether_tmp));
2707
2708 /* Reattach SNAP header */
2709 if (hassnap) {
2710 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
2711 if (m == NULL)
2712 goto dropit;
2713 bcopy(llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
2714 }
2715
2716 /* Reattach ethernet header */
2717 M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
2718 if (m == NULL)
2719 goto dropit;
2720 bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
2721
2722 bridge_output(ifp, m, NULL, NULL);
2723 m_freem(n);
2724 return;
2725
2726 dropit:
2727 m_freem(n);
2728 }
2729 #endif
2730