if_bridge.c revision 1.70
1/* $NetBSD: if_bridge.c,v 1.70 2009/05/17 11:34:21 cegger Exp $ */ 2 3/* 4 * Copyright 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38/* 39 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) 40 * All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by Jason L. Wright 53 * 4. The name of the author may not be used to endorse or promote products 54 * derived from this software without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 58 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 59 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 60 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 61 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 62 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 64 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 65 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 66 * POSSIBILITY OF SUCH DAMAGE. 67 * 68 * OpenBSD: if_bridge.c,v 1.60 2001/06/15 03:38:33 itojun Exp 69 */ 70 71/* 72 * Network interface bridge support. 73 * 74 * TODO: 75 * 76 * - Currently only supports Ethernet-like interfaces (Ethernet, 77 * 802.11, VLANs on Ethernet, etc.) Figure out a nice way 78 * to bridge other types of interfaces (FDDI-FDDI, and maybe 79 * consider heterogenous bridges). 80 */ 81 82#include <sys/cdefs.h> 83__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.70 2009/05/17 11:34:21 cegger Exp $"); 84 85#include "opt_bridge_ipf.h" 86#include "opt_inet.h" 87#include "opt_pfil_hooks.h" 88#include "bpfilter.h" 89 90#include <sys/param.h> 91#include <sys/kernel.h> 92#include <sys/mbuf.h> 93#include <sys/queue.h> 94#include <sys/socket.h> 95#include <sys/socketvar.h> /* for softnet_lock */ 96#include <sys/sockio.h> 97#include <sys/systm.h> 98#include <sys/proc.h> 99#include <sys/pool.h> 100#include <sys/kauth.h> 101#include <sys/cpu.h> 102 103#if NBPFILTER > 0 104#include <net/bpf.h> 105#endif 106#include <net/if.h> 107#include <net/if_dl.h> 108#include <net/if_types.h> 109#include <net/if_llc.h> 110 111#include <net/if_ether.h> 112#include <net/if_bridgevar.h> 113 114#if defined(BRIDGE_IPF) && defined(PFIL_HOOKS) 115/* Used for bridge_ip[6]_checkbasic */ 116#include <netinet/in.h> 117#include <netinet/in_systm.h> 118#include <netinet/ip.h> 119#include <netinet/ip_var.h> 120#include <netinet/ip_private.h> /* XXX */ 121 122#include <netinet/ip6.h> 123#include <netinet6/in6_var.h> 124#include <netinet6/ip6_var.h> 125#include <netinet6/ip6_private.h> /* XXX */ 126#endif /* BRIDGE_IPF && PFIL_HOOKS */ 127 128/* 129 * Size of the route hash table. Must be a power of two. 130 */ 131#ifndef BRIDGE_RTHASH_SIZE 132#define BRIDGE_RTHASH_SIZE 1024 133#endif 134 135#define BRIDGE_RTHASH_MASK (BRIDGE_RTHASH_SIZE - 1) 136 137#include "carp.h" 138#if NCARP > 0 139#include <netinet/in.h> 140#include <netinet/in_var.h> 141#include <netinet/ip_carp.h> 142#endif 143 144/* 145 * Maximum number of addresses to cache. 146 */ 147#ifndef BRIDGE_RTABLE_MAX 148#define BRIDGE_RTABLE_MAX 100 149#endif 150 151/* 152 * Spanning tree defaults. 153 */ 154#define BSTP_DEFAULT_MAX_AGE (20 * 256) 155#define BSTP_DEFAULT_HELLO_TIME (2 * 256) 156#define BSTP_DEFAULT_FORWARD_DELAY (15 * 256) 157#define BSTP_DEFAULT_HOLD_TIME (1 * 256) 158#define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000 159#define BSTP_DEFAULT_PORT_PRIORITY 0x80 160#define BSTP_DEFAULT_PATH_COST 55 161 162/* 163 * Timeout (in seconds) for entries learned dynamically. 164 */ 165#ifndef BRIDGE_RTABLE_TIMEOUT 166#define BRIDGE_RTABLE_TIMEOUT (20 * 60) /* same as ARP */ 167#endif 168 169/* 170 * Number of seconds between walks of the route list. 171 */ 172#ifndef BRIDGE_RTABLE_PRUNE_PERIOD 173#define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60) 174#endif 175 176int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; 177 178static struct pool bridge_rtnode_pool; 179 180void bridgeattach(int); 181 182static int bridge_clone_create(struct if_clone *, int); 183static int bridge_clone_destroy(struct ifnet *); 184 185static int bridge_ioctl(struct ifnet *, u_long, void *); 186static int bridge_init(struct ifnet *); 187static void bridge_stop(struct ifnet *, int); 188static void bridge_start(struct ifnet *); 189 190static void bridge_forward(void *); 191 192static void bridge_timer(void *); 193 194static void bridge_broadcast(struct bridge_softc *, struct ifnet *, 195 struct mbuf *); 196 197static int bridge_rtupdate(struct bridge_softc *, const uint8_t *, 198 struct ifnet *, int, uint8_t); 199static struct ifnet *bridge_rtlookup(struct bridge_softc *, const uint8_t *); 200static void bridge_rttrim(struct bridge_softc *); 201static void bridge_rtage(struct bridge_softc *); 202static void bridge_rtflush(struct bridge_softc *, int); 203static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *); 204static void bridge_rtdelete(struct bridge_softc *, struct ifnet *ifp); 205 206static int bridge_rtable_init(struct bridge_softc *); 207static void bridge_rtable_fini(struct bridge_softc *); 208 209static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *, 210 const uint8_t *); 211static int bridge_rtnode_insert(struct bridge_softc *, 212 struct bridge_rtnode *); 213static void bridge_rtnode_destroy(struct bridge_softc *, 214 struct bridge_rtnode *); 215 216static struct bridge_iflist *bridge_lookup_member(struct bridge_softc *, 217 const char *name); 218static struct bridge_iflist *bridge_lookup_member_if(struct bridge_softc *, 219 struct ifnet *ifp); 220static void bridge_delete_member(struct bridge_softc *, 221 struct bridge_iflist *); 222 223static int bridge_ioctl_add(struct bridge_softc *, void *); 224static int bridge_ioctl_del(struct bridge_softc *, void *); 225static int bridge_ioctl_gifflags(struct bridge_softc *, void *); 226static int bridge_ioctl_sifflags(struct bridge_softc *, void *); 227static int bridge_ioctl_scache(struct bridge_softc *, void *); 228static int bridge_ioctl_gcache(struct bridge_softc *, void *); 229static int bridge_ioctl_gifs(struct bridge_softc *, void *); 230static int bridge_ioctl_rts(struct bridge_softc *, void *); 231static int bridge_ioctl_saddr(struct bridge_softc *, void *); 232static int bridge_ioctl_sto(struct bridge_softc *, void *); 233static int bridge_ioctl_gto(struct bridge_softc *, void *); 234static int bridge_ioctl_daddr(struct bridge_softc *, void *); 235static int bridge_ioctl_flush(struct bridge_softc *, void *); 236static int bridge_ioctl_gpri(struct bridge_softc *, void *); 237static int bridge_ioctl_spri(struct bridge_softc *, void *); 238static int bridge_ioctl_ght(struct bridge_softc *, void *); 239static int bridge_ioctl_sht(struct bridge_softc *, void *); 240static int bridge_ioctl_gfd(struct bridge_softc *, void *); 241static int bridge_ioctl_sfd(struct bridge_softc *, void *); 242static int bridge_ioctl_gma(struct bridge_softc *, void *); 243static int bridge_ioctl_sma(struct bridge_softc *, void *); 244static int bridge_ioctl_sifprio(struct bridge_softc *, void *); 245static int bridge_ioctl_sifcost(struct bridge_softc *, void *); 246#if defined(BRIDGE_IPF) && defined(PFIL_HOOKS) 247static int bridge_ioctl_gfilt(struct bridge_softc *, void *); 248static int bridge_ioctl_sfilt(struct bridge_softc *, void *); 249static int bridge_ipf(void *, struct mbuf **, struct ifnet *, int); 250static int bridge_ip_checkbasic(struct mbuf **mp); 251# ifdef INET6 252static int bridge_ip6_checkbasic(struct mbuf **mp); 253# endif /* INET6 */ 254#endif /* BRIDGE_IPF && PFIL_HOOKS */ 255 256struct bridge_control { 257 int (*bc_func)(struct bridge_softc *, void *); 258 int bc_argsize; 259 int bc_flags; 260}; 261 262#define BC_F_COPYIN 0x01 /* copy arguments in */ 263#define BC_F_COPYOUT 0x02 /* copy arguments out */ 264#define BC_F_SUSER 0x04 /* do super-user check */ 265 266static const struct bridge_control bridge_control_table[] = { 267[BRDGADD] = {bridge_ioctl_add, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 268[BRDGDEL] = {bridge_ioctl_del, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 269 270[BRDGGIFFLGS] = {bridge_ioctl_gifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_COPYOUT}, 271[BRDGSIFFLGS] = {bridge_ioctl_sifflags, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 272 273[BRDGSCACHE] = {bridge_ioctl_scache, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 274[BRDGGCACHE] = {bridge_ioctl_gcache, sizeof(struct ifbrparam), BC_F_COPYOUT}, 275 276[BRDGGIFS] = {bridge_ioctl_gifs, sizeof(struct ifbifconf), BC_F_COPYIN|BC_F_COPYOUT}, 277[BRDGRTS] = {bridge_ioctl_rts, sizeof(struct ifbaconf), BC_F_COPYIN|BC_F_COPYOUT}, 278 279[BRDGSADDR] = {bridge_ioctl_saddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER}, 280 281[BRDGSTO] = {bridge_ioctl_sto, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 282[BRDGGTO] = {bridge_ioctl_gto, sizeof(struct ifbrparam), BC_F_COPYOUT}, 283 284[BRDGDADDR] = {bridge_ioctl_daddr, sizeof(struct ifbareq), BC_F_COPYIN|BC_F_SUSER}, 285 286[BRDGFLUSH] = {bridge_ioctl_flush, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 287 288[BRDGGPRI] = {bridge_ioctl_gpri, sizeof(struct ifbrparam), BC_F_COPYOUT}, 289[BRDGSPRI] = {bridge_ioctl_spri, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 290 291[BRDGGHT] = {bridge_ioctl_ght, sizeof(struct ifbrparam), BC_F_COPYOUT}, 292[BRDGSHT] = {bridge_ioctl_sht, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 293 294[BRDGGFD] = {bridge_ioctl_gfd, sizeof(struct ifbrparam), BC_F_COPYOUT}, 295[BRDGSFD] = {bridge_ioctl_sfd, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 296 297[BRDGGMA] = {bridge_ioctl_gma, sizeof(struct ifbrparam), BC_F_COPYOUT}, 298[BRDGSMA] = {bridge_ioctl_sma, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 299 300[BRDGSIFPRIO] = {bridge_ioctl_sifprio, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 301 302[BRDGSIFCOST] = {bridge_ioctl_sifcost, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER}, 303#if defined(BRIDGE_IPF) && defined(PFIL_HOOKS) 304[BRDGGFILT] = {bridge_ioctl_gfilt, sizeof(struct ifbrparam), BC_F_COPYOUT}, 305[BRDGSFILT] = {bridge_ioctl_sfilt, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER}, 306#endif /* BRIDGE_IPF && PFIL_HOOKS */ 307}; 308static const int bridge_control_table_size = __arraycount(bridge_control_table); 309 310static LIST_HEAD(, bridge_softc) bridge_list; 311 312static struct if_clone bridge_cloner = 313 IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy); 314 315/* 316 * bridgeattach: 317 * 318 * Pseudo-device attach routine. 319 */ 320void 321bridgeattach(int n) 322{ 323 324 pool_init(&bridge_rtnode_pool, sizeof(struct bridge_rtnode), 325 0, 0, 0, "brtpl", NULL, IPL_NET); 326 327 LIST_INIT(&bridge_list); 328 if_clone_attach(&bridge_cloner); 329} 330 331/* 332 * bridge_clone_create: 333 * 334 * Create a new bridge instance. 335 */ 336static int 337bridge_clone_create(struct if_clone *ifc, int unit) 338{ 339 struct bridge_softc *sc; 340 struct ifnet *ifp; 341 int s; 342 343 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 344 ifp = &sc->sc_if; 345 346 sc->sc_brtmax = BRIDGE_RTABLE_MAX; 347 sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT; 348 sc->sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; 349 sc->sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; 350 sc->sc_bridge_forward_delay = BSTP_DEFAULT_FORWARD_DELAY; 351 sc->sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; 352 sc->sc_hold_time = BSTP_DEFAULT_HOLD_TIME; 353 sc->sc_filter_flags = 0; 354 355 /* software interrupt to do the work */ 356 sc->sc_softintr = softint_establish(SOFTINT_NET, bridge_forward, sc); 357 if (sc->sc_softintr == NULL) { 358 free(sc, M_DEVBUF); 359 return ENOMEM; 360 } 361 362 /* Initialize our routing table. */ 363 bridge_rtable_init(sc); 364 365 callout_init(&sc->sc_brcallout, 0); 366 callout_init(&sc->sc_bstpcallout, 0); 367 368 LIST_INIT(&sc->sc_iflist); 369 370 if_initname(ifp, ifc->ifc_name, unit); 371 ifp->if_softc = sc; 372 ifp->if_mtu = ETHERMTU; 373 ifp->if_ioctl = bridge_ioctl; 374 ifp->if_output = bridge_output; 375 ifp->if_start = bridge_start; 376 ifp->if_stop = bridge_stop; 377 ifp->if_init = bridge_init; 378 ifp->if_type = IFT_BRIDGE; 379 ifp->if_addrlen = 0; 380 ifp->if_dlt = DLT_EN10MB; 381 ifp->if_hdrlen = ETHER_HDR_LEN; 382 IFQ_SET_READY(&ifp->if_snd); 383 384 if_attach(ifp); 385 386 if_alloc_sadl(ifp); 387 388 s = splnet(); 389 LIST_INSERT_HEAD(&bridge_list, sc, sc_list); 390 splx(s); 391 392 return (0); 393} 394 395/* 396 * bridge_clone_destroy: 397 * 398 * Destroy a bridge instance. 399 */ 400static int 401bridge_clone_destroy(struct ifnet *ifp) 402{ 403 struct bridge_softc *sc = ifp->if_softc; 404 struct bridge_iflist *bif; 405 int s; 406 407 s = splnet(); 408 409 bridge_stop(ifp, 1); 410 411 while ((bif = LIST_FIRST(&sc->sc_iflist)) != NULL) 412 bridge_delete_member(sc, bif); 413 414 LIST_REMOVE(sc, sc_list); 415 416 splx(s); 417 418 if_detach(ifp); 419 420 /* Tear down the routing table. */ 421 bridge_rtable_fini(sc); 422 423 softint_disestablish(sc->sc_softintr); 424 425 free(sc, M_DEVBUF); 426 427 return (0); 428} 429 430/* 431 * bridge_ioctl: 432 * 433 * Handle a control request from the operator. 434 */ 435static int 436bridge_ioctl(struct ifnet *ifp, u_long cmd, void *data) 437{ 438 struct bridge_softc *sc = ifp->if_softc; 439 struct lwp *l = curlwp; /* XXX */ 440 union { 441 struct ifbreq ifbreq; 442 struct ifbifconf ifbifconf; 443 struct ifbareq ifbareq; 444 struct ifbaconf ifbaconf; 445 struct ifbrparam ifbrparam; 446 } args; 447 struct ifdrv *ifd = (struct ifdrv *) data; 448 const struct bridge_control *bc = NULL; /* XXXGCC */ 449 int s, error = 0; 450 451 /* Authorize command before calling splnet(). */ 452 switch (cmd) { 453 case SIOCGDRVSPEC: 454 case SIOCSDRVSPEC: 455 if (ifd->ifd_cmd >= bridge_control_table_size) { 456 error = EINVAL; 457 return error; 458 } 459 460 bc = &bridge_control_table[ifd->ifd_cmd]; 461 462 /* We only care about BC_F_SUSER at this point. */ 463 if ((bc->bc_flags & BC_F_SUSER) == 0) 464 break; 465 466 error = kauth_authorize_generic(l->l_cred, 467 KAUTH_GENERIC_ISSUSER, NULL); 468 if (error) 469 return (error); 470 471 break; 472 } 473 474 s = splnet(); 475 476 switch (cmd) { 477 case SIOCGDRVSPEC: 478 case SIOCSDRVSPEC: 479 KASSERT(bc != NULL); 480 if (cmd == SIOCGDRVSPEC && 481 (bc->bc_flags & BC_F_COPYOUT) == 0) { 482 error = EINVAL; 483 break; 484 } 485 else if (cmd == SIOCSDRVSPEC && 486 (bc->bc_flags & BC_F_COPYOUT) != 0) { 487 error = EINVAL; 488 break; 489 } 490 491 /* BC_F_SUSER is checked above, before splnet(). */ 492 493 if (ifd->ifd_len != bc->bc_argsize || 494 ifd->ifd_len > sizeof(args)) { 495 error = EINVAL; 496 break; 497 } 498 499 memset(&args, 0, sizeof(args)); 500 if (bc->bc_flags & BC_F_COPYIN) { 501 error = copyin(ifd->ifd_data, &args, ifd->ifd_len); 502 if (error) 503 break; 504 } 505 506 error = (*bc->bc_func)(sc, &args); 507 if (error) 508 break; 509 510 if (bc->bc_flags & BC_F_COPYOUT) 511 error = copyout(&args, ifd->ifd_data, ifd->ifd_len); 512 513 break; 514 515 case SIOCSIFFLAGS: 516 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 517 break; 518 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 519 case IFF_RUNNING: 520 /* 521 * If interface is marked down and it is running, 522 * then stop and disable it. 523 */ 524 (*ifp->if_stop)(ifp, 1); 525 break; 526 case IFF_UP: 527 /* 528 * If interface is marked up and it is stopped, then 529 * start it. 530 */ 531 error = (*ifp->if_init)(ifp); 532 break; 533 default: 534 break; 535 } 536 break; 537 538 default: 539 error = ifioctl_common(ifp, cmd, data); 540 break; 541 } 542 543 splx(s); 544 545 return (error); 546} 547 548/* 549 * bridge_lookup_member: 550 * 551 * Lookup a bridge member interface. Must be called at splnet(). 552 */ 553static struct bridge_iflist * 554bridge_lookup_member(struct bridge_softc *sc, const char *name) 555{ 556 struct bridge_iflist *bif; 557 struct ifnet *ifp; 558 559 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 560 ifp = bif->bif_ifp; 561 if (strcmp(ifp->if_xname, name) == 0) 562 return (bif); 563 } 564 565 return (NULL); 566} 567 568/* 569 * bridge_lookup_member_if: 570 * 571 * Lookup a bridge member interface by ifnet*. Must be called at splnet(). 572 */ 573static struct bridge_iflist * 574bridge_lookup_member_if(struct bridge_softc *sc, struct ifnet *member_ifp) 575{ 576 struct bridge_iflist *bif; 577 578 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 579 if (bif->bif_ifp == member_ifp) 580 return (bif); 581 } 582 583 return (NULL); 584} 585 586/* 587 * bridge_delete_member: 588 * 589 * Delete the specified member interface. 590 */ 591static void 592bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif) 593{ 594 struct ifnet *ifs = bif->bif_ifp; 595 596 switch (ifs->if_type) { 597 case IFT_ETHER: 598 /* 599 * Take the interface out of promiscuous mode. 600 */ 601 (void) ifpromisc(ifs, 0); 602 break; 603 default: 604#ifdef DIAGNOSTIC 605 panic("bridge_delete_member: impossible"); 606#endif 607 break; 608 } 609 610 ifs->if_bridge = NULL; 611 LIST_REMOVE(bif, bif_next); 612 613 bridge_rtdelete(sc, ifs); 614 615 free(bif, M_DEVBUF); 616 617 if (sc->sc_if.if_flags & IFF_RUNNING) 618 bstp_initialization(sc); 619} 620 621static int 622bridge_ioctl_add(struct bridge_softc *sc, void *arg) 623{ 624 struct ifbreq *req = arg; 625 struct bridge_iflist *bif = NULL; 626 struct ifnet *ifs; 627 int error = 0; 628 629 ifs = ifunit(req->ifbr_ifsname); 630 if (ifs == NULL) 631 return (ENOENT); 632 633 if (sc->sc_if.if_mtu != ifs->if_mtu) 634 return (EINVAL); 635 636 if (ifs->if_bridge == sc) 637 return (EEXIST); 638 639 if (ifs->if_bridge != NULL) 640 return (EBUSY); 641 642 bif = malloc(sizeof(*bif), M_DEVBUF, M_NOWAIT); 643 if (bif == NULL) 644 return (ENOMEM); 645 646 switch (ifs->if_type) { 647 case IFT_ETHER: 648 /* 649 * Place the interface into promiscuous mode. 650 */ 651 error = ifpromisc(ifs, 1); 652 if (error) 653 goto out; 654 break; 655 default: 656 error = EINVAL; 657 goto out; 658 } 659 660 bif->bif_ifp = ifs; 661 bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; 662 bif->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; 663 bif->bif_path_cost = BSTP_DEFAULT_PATH_COST; 664 665 ifs->if_bridge = sc; 666 LIST_INSERT_HEAD(&sc->sc_iflist, bif, bif_next); 667 668 if (sc->sc_if.if_flags & IFF_RUNNING) 669 bstp_initialization(sc); 670 else 671 bstp_stop(sc); 672 673 out: 674 if (error) { 675 if (bif != NULL) 676 free(bif, M_DEVBUF); 677 } 678 return (error); 679} 680 681static int 682bridge_ioctl_del(struct bridge_softc *sc, void *arg) 683{ 684 struct ifbreq *req = arg; 685 struct bridge_iflist *bif; 686 687 bif = bridge_lookup_member(sc, req->ifbr_ifsname); 688 if (bif == NULL) 689 return (ENOENT); 690 691 bridge_delete_member(sc, bif); 692 693 return (0); 694} 695 696static int 697bridge_ioctl_gifflags(struct bridge_softc *sc, void *arg) 698{ 699 struct ifbreq *req = arg; 700 struct bridge_iflist *bif; 701 702 bif = bridge_lookup_member(sc, req->ifbr_ifsname); 703 if (bif == NULL) 704 return (ENOENT); 705 706 req->ifbr_ifsflags = bif->bif_flags; 707 req->ifbr_state = bif->bif_state; 708 req->ifbr_priority = bif->bif_priority; 709 req->ifbr_path_cost = bif->bif_path_cost; 710 req->ifbr_portno = bif->bif_ifp->if_index & 0xff; 711 712 return (0); 713} 714 715static int 716bridge_ioctl_sifflags(struct bridge_softc *sc, void *arg) 717{ 718 struct ifbreq *req = arg; 719 struct bridge_iflist *bif; 720 721 bif = bridge_lookup_member(sc, req->ifbr_ifsname); 722 if (bif == NULL) 723 return (ENOENT); 724 725 if (req->ifbr_ifsflags & IFBIF_STP) { 726 switch (bif->bif_ifp->if_type) { 727 case IFT_ETHER: 728 /* These can do spanning tree. */ 729 break; 730 731 default: 732 /* Nothing else can. */ 733 return (EINVAL); 734 } 735 } 736 737 bif->bif_flags = req->ifbr_ifsflags; 738 739 if (sc->sc_if.if_flags & IFF_RUNNING) 740 bstp_initialization(sc); 741 742 return (0); 743} 744 745static int 746bridge_ioctl_scache(struct bridge_softc *sc, void *arg) 747{ 748 struct ifbrparam *param = arg; 749 750 sc->sc_brtmax = param->ifbrp_csize; 751 bridge_rttrim(sc); 752 753 return (0); 754} 755 756static int 757bridge_ioctl_gcache(struct bridge_softc *sc, void *arg) 758{ 759 struct ifbrparam *param = arg; 760 761 param->ifbrp_csize = sc->sc_brtmax; 762 763 return (0); 764} 765 766static int 767bridge_ioctl_gifs(struct bridge_softc *sc, void *arg) 768{ 769 struct ifbifconf *bifc = arg; 770 struct bridge_iflist *bif; 771 struct ifbreq breq; 772 int count, len, error = 0; 773 774 count = 0; 775 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) 776 count++; 777 778 if (bifc->ifbic_len == 0) { 779 bifc->ifbic_len = sizeof(breq) * count; 780 return (0); 781 } 782 783 count = 0; 784 len = bifc->ifbic_len; 785 memset(&breq, 0, sizeof breq); 786 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 787 if (len < sizeof(breq)) 788 break; 789 790 strlcpy(breq.ifbr_ifsname, bif->bif_ifp->if_xname, 791 sizeof(breq.ifbr_ifsname)); 792 breq.ifbr_ifsflags = bif->bif_flags; 793 breq.ifbr_state = bif->bif_state; 794 breq.ifbr_priority = bif->bif_priority; 795 breq.ifbr_path_cost = bif->bif_path_cost; 796 breq.ifbr_portno = bif->bif_ifp->if_index & 0xff; 797 error = copyout(&breq, bifc->ifbic_req + count, sizeof(breq)); 798 if (error) 799 break; 800 count++; 801 len -= sizeof(breq); 802 } 803 804 bifc->ifbic_len = sizeof(breq) * count; 805 return (error); 806} 807 808static int 809bridge_ioctl_rts(struct bridge_softc *sc, void *arg) 810{ 811 struct ifbaconf *bac = arg; 812 struct bridge_rtnode *brt; 813 struct ifbareq bareq; 814 int count = 0, error = 0, len; 815 816 if (bac->ifbac_len == 0) 817 return (0); 818 819 len = bac->ifbac_len; 820 LIST_FOREACH(brt, &sc->sc_rtlist, brt_list) { 821 if (len < sizeof(bareq)) 822 goto out; 823 memset(&bareq, 0, sizeof(bareq)); 824 strlcpy(bareq.ifba_ifsname, brt->brt_ifp->if_xname, 825 sizeof(bareq.ifba_ifsname)); 826 memcpy(bareq.ifba_dst, brt->brt_addr, sizeof(brt->brt_addr)); 827 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { 828 bareq.ifba_expire = brt->brt_expire - time_uptime; 829 } else 830 bareq.ifba_expire = 0; 831 bareq.ifba_flags = brt->brt_flags; 832 833 error = copyout(&bareq, bac->ifbac_req + count, sizeof(bareq)); 834 if (error) 835 goto out; 836 count++; 837 len -= sizeof(bareq); 838 } 839 out: 840 bac->ifbac_len = sizeof(bareq) * count; 841 return (error); 842} 843 844static int 845bridge_ioctl_saddr(struct bridge_softc *sc, void *arg) 846{ 847 struct ifbareq *req = arg; 848 struct bridge_iflist *bif; 849 int error; 850 851 bif = bridge_lookup_member(sc, req->ifba_ifsname); 852 if (bif == NULL) 853 return (ENOENT); 854 855 error = bridge_rtupdate(sc, req->ifba_dst, bif->bif_ifp, 1, 856 req->ifba_flags); 857 858 return (error); 859} 860 861static int 862bridge_ioctl_sto(struct bridge_softc *sc, void *arg) 863{ 864 struct ifbrparam *param = arg; 865 866 sc->sc_brttimeout = param->ifbrp_ctime; 867 868 return (0); 869} 870 871static int 872bridge_ioctl_gto(struct bridge_softc *sc, void *arg) 873{ 874 struct ifbrparam *param = arg; 875 876 param->ifbrp_ctime = sc->sc_brttimeout; 877 878 return (0); 879} 880 881static int 882bridge_ioctl_daddr(struct bridge_softc *sc, void *arg) 883{ 884 struct ifbareq *req = arg; 885 886 return (bridge_rtdaddr(sc, req->ifba_dst)); 887} 888 889static int 890bridge_ioctl_flush(struct bridge_softc *sc, void *arg) 891{ 892 struct ifbreq *req = arg; 893 894 bridge_rtflush(sc, req->ifbr_ifsflags); 895 896 return (0); 897} 898 899static int 900bridge_ioctl_gpri(struct bridge_softc *sc, void *arg) 901{ 902 struct ifbrparam *param = arg; 903 904 param->ifbrp_prio = sc->sc_bridge_priority; 905 906 return (0); 907} 908 909static int 910bridge_ioctl_spri(struct bridge_softc *sc, void *arg) 911{ 912 struct ifbrparam *param = arg; 913 914 sc->sc_bridge_priority = param->ifbrp_prio; 915 916 if (sc->sc_if.if_flags & IFF_RUNNING) 917 bstp_initialization(sc); 918 919 return (0); 920} 921 922static int 923bridge_ioctl_ght(struct bridge_softc *sc, void *arg) 924{ 925 struct ifbrparam *param = arg; 926 927 param->ifbrp_hellotime = sc->sc_bridge_hello_time >> 8; 928 929 return (0); 930} 931 932static int 933bridge_ioctl_sht(struct bridge_softc *sc, void *arg) 934{ 935 struct ifbrparam *param = arg; 936 937 if (param->ifbrp_hellotime == 0) 938 return (EINVAL); 939 sc->sc_bridge_hello_time = param->ifbrp_hellotime << 8; 940 941 if (sc->sc_if.if_flags & IFF_RUNNING) 942 bstp_initialization(sc); 943 944 return (0); 945} 946 947static int 948bridge_ioctl_gfd(struct bridge_softc *sc, void *arg) 949{ 950 struct ifbrparam *param = arg; 951 952 param->ifbrp_fwddelay = sc->sc_bridge_forward_delay >> 8; 953 954 return (0); 955} 956 957static int 958bridge_ioctl_sfd(struct bridge_softc *sc, void *arg) 959{ 960 struct ifbrparam *param = arg; 961 962 if (param->ifbrp_fwddelay == 0) 963 return (EINVAL); 964 sc->sc_bridge_forward_delay = param->ifbrp_fwddelay << 8; 965 966 if (sc->sc_if.if_flags & IFF_RUNNING) 967 bstp_initialization(sc); 968 969 return (0); 970} 971 972static int 973bridge_ioctl_gma(struct bridge_softc *sc, void *arg) 974{ 975 struct ifbrparam *param = arg; 976 977 param->ifbrp_maxage = sc->sc_bridge_max_age >> 8; 978 979 return (0); 980} 981 982static int 983bridge_ioctl_sma(struct bridge_softc *sc, void *arg) 984{ 985 struct ifbrparam *param = arg; 986 987 if (param->ifbrp_maxage == 0) 988 return (EINVAL); 989 sc->sc_bridge_max_age = param->ifbrp_maxage << 8; 990 991 if (sc->sc_if.if_flags & IFF_RUNNING) 992 bstp_initialization(sc); 993 994 return (0); 995} 996 997static int 998bridge_ioctl_sifprio(struct bridge_softc *sc, void *arg) 999{ 1000 struct ifbreq *req = arg; 1001 struct bridge_iflist *bif; 1002 1003 bif = bridge_lookup_member(sc, req->ifbr_ifsname); 1004 if (bif == NULL) 1005 return (ENOENT); 1006 1007 bif->bif_priority = req->ifbr_priority; 1008 1009 if (sc->sc_if.if_flags & IFF_RUNNING) 1010 bstp_initialization(sc); 1011 1012 return (0); 1013} 1014 1015#if defined(BRIDGE_IPF) && defined(PFIL_HOOKS) 1016static int 1017bridge_ioctl_gfilt(struct bridge_softc *sc, void *arg) 1018{ 1019 struct ifbrparam *param = arg; 1020 1021 param->ifbrp_filter = sc->sc_filter_flags; 1022 1023 return (0); 1024} 1025 1026static int 1027bridge_ioctl_sfilt(struct bridge_softc *sc, void *arg) 1028{ 1029 struct ifbrparam *param = arg; 1030 uint32_t nflags, oflags; 1031 1032 if (param->ifbrp_filter & ~IFBF_FILT_MASK) 1033 return (EINVAL); 1034 1035 nflags = param->ifbrp_filter; 1036 oflags = sc->sc_filter_flags; 1037 1038 if ((nflags & IFBF_FILT_USEIPF) && !(oflags & IFBF_FILT_USEIPF)) { 1039 pfil_add_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT, 1040 &sc->sc_if.if_pfil); 1041 } 1042 if (!(nflags & IFBF_FILT_USEIPF) && (oflags & IFBF_FILT_USEIPF)) { 1043 pfil_remove_hook((void *)bridge_ipf, NULL, PFIL_IN|PFIL_OUT, 1044 &sc->sc_if.if_pfil); 1045 } 1046 1047 sc->sc_filter_flags = nflags; 1048 1049 return (0); 1050} 1051#endif /* BRIDGE_IPF && PFIL_HOOKS */ 1052 1053static int 1054bridge_ioctl_sifcost(struct bridge_softc *sc, void *arg) 1055{ 1056 struct ifbreq *req = arg; 1057 struct bridge_iflist *bif; 1058 1059 bif = bridge_lookup_member(sc, req->ifbr_ifsname); 1060 if (bif == NULL) 1061 return (ENOENT); 1062 1063 bif->bif_path_cost = req->ifbr_path_cost; 1064 1065 if (sc->sc_if.if_flags & IFF_RUNNING) 1066 bstp_initialization(sc); 1067 1068 return (0); 1069} 1070 1071/* 1072 * bridge_ifdetach: 1073 * 1074 * Detach an interface from a bridge. Called when a member 1075 * interface is detaching. 1076 */ 1077void 1078bridge_ifdetach(struct ifnet *ifp) 1079{ 1080 struct bridge_softc *sc = ifp->if_bridge; 1081 struct ifbreq breq; 1082 1083 memset(&breq, 0, sizeof(breq)); 1084 snprintf(breq.ifbr_ifsname, sizeof(breq.ifbr_ifsname), ifp->if_xname); 1085 1086 (void) bridge_ioctl_del(sc, &breq); 1087} 1088 1089/* 1090 * bridge_init: 1091 * 1092 * Initialize a bridge interface. 1093 */ 1094static int 1095bridge_init(struct ifnet *ifp) 1096{ 1097 struct bridge_softc *sc = ifp->if_softc; 1098 1099 if (ifp->if_flags & IFF_RUNNING) 1100 return (0); 1101 1102 callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz, 1103 bridge_timer, sc); 1104 1105 ifp->if_flags |= IFF_RUNNING; 1106 bstp_initialization(sc); 1107 return (0); 1108} 1109 1110/* 1111 * bridge_stop: 1112 * 1113 * Stop the bridge interface. 1114 */ 1115static void 1116bridge_stop(struct ifnet *ifp, int disable) 1117{ 1118 struct bridge_softc *sc = ifp->if_softc; 1119 1120 if ((ifp->if_flags & IFF_RUNNING) == 0) 1121 return; 1122 1123 callout_stop(&sc->sc_brcallout); 1124 bstp_stop(sc); 1125 1126 IF_PURGE(&ifp->if_snd); 1127 1128 bridge_rtflush(sc, IFBF_FLUSHDYN); 1129 1130 ifp->if_flags &= ~IFF_RUNNING; 1131} 1132 1133/* 1134 * bridge_enqueue: 1135 * 1136 * Enqueue a packet on a bridge member interface. 1137 * 1138 * NOTE: must be called at splnet(). 1139 */ 1140void 1141bridge_enqueue(struct bridge_softc *sc, struct ifnet *dst_ifp, struct mbuf *m, 1142 int runfilt) 1143{ 1144 ALTQ_DECL(struct altq_pktattr pktattr;) 1145 int len, error; 1146 short mflags; 1147 1148 /* 1149 * Clear any in-bound checksum flags for this packet. 1150 */ 1151 m->m_pkthdr.csum_flags = 0; 1152 1153#ifdef PFIL_HOOKS 1154 if (runfilt) { 1155 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, 1156 dst_ifp, PFIL_OUT) != 0) { 1157 if (m != NULL) 1158 m_freem(m); 1159 return; 1160 } 1161 if (m == NULL) 1162 return; 1163 } 1164#endif /* PFIL_HOOKS */ 1165 1166#ifdef ALTQ 1167 /* 1168 * If ALTQ is enabled on the member interface, do 1169 * classification; the queueing discipline might 1170 * not require classification, but might require 1171 * the address family/header pointer in the pktattr. 1172 */ 1173 if (ALTQ_IS_ENABLED(&dst_ifp->if_snd)) { 1174 /* XXX IFT_ETHER */ 1175 altq_etherclassify(&dst_ifp->if_snd, m, &pktattr); 1176 } 1177#endif /* ALTQ */ 1178 1179 len = m->m_pkthdr.len; 1180 m->m_flags |= M_PROTO1; 1181 mflags = m->m_flags; 1182 IFQ_ENQUEUE(&dst_ifp->if_snd, m, &pktattr, error); 1183 if (error) { 1184 /* mbuf is already freed */ 1185 sc->sc_if.if_oerrors++; 1186 return; 1187 } 1188 1189 sc->sc_if.if_opackets++; 1190 sc->sc_if.if_obytes += len; 1191 1192 dst_ifp->if_obytes += len; 1193 1194 if (mflags & M_MCAST) { 1195 sc->sc_if.if_omcasts++; 1196 dst_ifp->if_omcasts++; 1197 } 1198 1199 if ((dst_ifp->if_flags & IFF_OACTIVE) == 0) 1200 (*dst_ifp->if_start)(dst_ifp); 1201} 1202 1203/* 1204 * bridge_output: 1205 * 1206 * Send output from a bridge member interface. This 1207 * performs the bridging function for locally originated 1208 * packets. 1209 * 1210 * The mbuf has the Ethernet header already attached. We must 1211 * enqueue or free the mbuf before returning. 1212 */ 1213int 1214bridge_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa, 1215 struct rtentry *rt) 1216{ 1217 struct ether_header *eh; 1218 struct ifnet *dst_if; 1219 struct bridge_softc *sc; 1220 int s; 1221 1222 if (m->m_len < ETHER_HDR_LEN) { 1223 m = m_pullup(m, ETHER_HDR_LEN); 1224 if (m == NULL) 1225 return (0); 1226 } 1227 1228 eh = mtod(m, struct ether_header *); 1229 sc = ifp->if_bridge; 1230 1231 s = splnet(); 1232 1233 /* 1234 * If bridge is down, but the original output interface is up, 1235 * go ahead and send out that interface. Otherwise, the packet 1236 * is dropped below. 1237 */ 1238 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 1239 dst_if = ifp; 1240 goto sendunicast; 1241 } 1242 1243 /* 1244 * If the packet is a multicast, or we don't know a better way to 1245 * get there, send to all interfaces. 1246 */ 1247 if (ETHER_IS_MULTICAST(eh->ether_dhost)) 1248 dst_if = NULL; 1249 else 1250 dst_if = bridge_rtlookup(sc, eh->ether_dhost); 1251 if (dst_if == NULL) { 1252 struct bridge_iflist *bif; 1253 struct mbuf *mc; 1254 int used = 0; 1255 1256 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 1257 dst_if = bif->bif_ifp; 1258 if ((dst_if->if_flags & IFF_RUNNING) == 0) 1259 continue; 1260 1261 /* 1262 * If this is not the original output interface, 1263 * and the interface is participating in spanning 1264 * tree, make sure the port is in a state that 1265 * allows forwarding. 1266 */ 1267 if (dst_if != ifp && 1268 (bif->bif_flags & IFBIF_STP) != 0) { 1269 switch (bif->bif_state) { 1270 case BSTP_IFSTATE_BLOCKING: 1271 case BSTP_IFSTATE_LISTENING: 1272 case BSTP_IFSTATE_DISABLED: 1273 continue; 1274 } 1275 } 1276 1277 if (LIST_NEXT(bif, bif_next) == NULL) { 1278 used = 1; 1279 mc = m; 1280 } else { 1281 mc = m_copym(m, 0, M_COPYALL, M_NOWAIT); 1282 if (mc == NULL) { 1283 sc->sc_if.if_oerrors++; 1284 continue; 1285 } 1286 } 1287 1288 bridge_enqueue(sc, dst_if, mc, 0); 1289 } 1290 if (used == 0) 1291 m_freem(m); 1292 splx(s); 1293 return (0); 1294 } 1295 1296 sendunicast: 1297 /* 1298 * XXX Spanning tree consideration here? 1299 */ 1300 1301 if ((dst_if->if_flags & IFF_RUNNING) == 0) { 1302 m_freem(m); 1303 splx(s); 1304 return (0); 1305 } 1306 1307 bridge_enqueue(sc, dst_if, m, 0); 1308 1309 splx(s); 1310 return (0); 1311} 1312 1313/* 1314 * bridge_start: 1315 * 1316 * Start output on a bridge. 1317 * 1318 * NOTE: This routine should never be called in this implementation. 1319 */ 1320static void 1321bridge_start(struct ifnet *ifp) 1322{ 1323 1324 printf("%s: bridge_start() called\n", ifp->if_xname); 1325} 1326 1327/* 1328 * bridge_forward: 1329 * 1330 * The forwarding function of the bridge. 1331 */ 1332static void 1333bridge_forward(void *v) 1334{ 1335 struct bridge_softc *sc = v; 1336 struct mbuf *m; 1337 struct bridge_iflist *bif; 1338 struct ifnet *src_if, *dst_if; 1339 struct ether_header *eh; 1340 int s; 1341 1342 mutex_enter(softnet_lock); 1343 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) { 1344 mutex_exit(softnet_lock); 1345 return; 1346 } 1347 1348 s = splnet(); 1349 while (1) { 1350 IFQ_POLL(&sc->sc_if.if_snd, m); 1351 if (m == NULL) 1352 break; 1353 IFQ_DEQUEUE(&sc->sc_if.if_snd, m); 1354 1355 src_if = m->m_pkthdr.rcvif; 1356 1357 sc->sc_if.if_ipackets++; 1358 sc->sc_if.if_ibytes += m->m_pkthdr.len; 1359 1360 /* 1361 * Look up the bridge_iflist. 1362 */ 1363 bif = bridge_lookup_member_if(sc, src_if); 1364 if (bif == NULL) { 1365 /* Interface is not a bridge member (anymore?) */ 1366 m_freem(m); 1367 continue; 1368 } 1369 1370 if (bif->bif_flags & IFBIF_STP) { 1371 switch (bif->bif_state) { 1372 case BSTP_IFSTATE_BLOCKING: 1373 case BSTP_IFSTATE_LISTENING: 1374 case BSTP_IFSTATE_DISABLED: 1375 m_freem(m); 1376 continue; 1377 } 1378 } 1379 1380 eh = mtod(m, struct ether_header *); 1381 1382 /* 1383 * If the interface is learning, and the source 1384 * address is valid and not multicast, record 1385 * the address. 1386 */ 1387 if ((bif->bif_flags & IFBIF_LEARNING) != 0 && 1388 ETHER_IS_MULTICAST(eh->ether_shost) == 0 && 1389 (eh->ether_shost[0] == 0 && 1390 eh->ether_shost[1] == 0 && 1391 eh->ether_shost[2] == 0 && 1392 eh->ether_shost[3] == 0 && 1393 eh->ether_shost[4] == 0 && 1394 eh->ether_shost[5] == 0) == 0) { 1395 (void) bridge_rtupdate(sc, eh->ether_shost, 1396 src_if, 0, IFBAF_DYNAMIC); 1397 } 1398 1399 if ((bif->bif_flags & IFBIF_STP) != 0 && 1400 bif->bif_state == BSTP_IFSTATE_LEARNING) { 1401 m_freem(m); 1402 continue; 1403 } 1404 1405 /* 1406 * At this point, the port either doesn't participate 1407 * in spanning tree or it is in the forwarding state. 1408 */ 1409 1410 /* 1411 * If the packet is unicast, destined for someone on 1412 * "this" side of the bridge, drop it. 1413 */ 1414 if ((m->m_flags & (M_BCAST|M_MCAST)) == 0) { 1415 dst_if = bridge_rtlookup(sc, eh->ether_dhost); 1416 if (src_if == dst_if) { 1417 m_freem(m); 1418 continue; 1419 } 1420 } else { 1421 /* ...forward it to all interfaces. */ 1422 sc->sc_if.if_imcasts++; 1423 dst_if = NULL; 1424 } 1425 1426#ifdef PFIL_HOOKS 1427 if (pfil_run_hooks(&sc->sc_if.if_pfil, &m, 1428 m->m_pkthdr.rcvif, PFIL_IN) != 0) { 1429 if (m != NULL) 1430 m_freem(m); 1431 continue; 1432 } 1433 if (m == NULL) 1434 continue; 1435#endif /* PFIL_HOOKS */ 1436 1437 if (dst_if == NULL) { 1438 bridge_broadcast(sc, src_if, m); 1439 continue; 1440 } 1441 1442 /* 1443 * At this point, we're dealing with a unicast frame 1444 * going to a different interface. 1445 */ 1446 if ((dst_if->if_flags & IFF_RUNNING) == 0) { 1447 m_freem(m); 1448 continue; 1449 } 1450 bif = bridge_lookup_member_if(sc, dst_if); 1451 if (bif == NULL) { 1452 /* Not a member of the bridge (anymore?) */ 1453 m_freem(m); 1454 continue; 1455 } 1456 1457 if (bif->bif_flags & IFBIF_STP) { 1458 switch (bif->bif_state) { 1459 case BSTP_IFSTATE_DISABLED: 1460 case BSTP_IFSTATE_BLOCKING: 1461 m_freem(m); 1462 continue; 1463 } 1464 } 1465 1466 bridge_enqueue(sc, dst_if, m, 1); 1467 } 1468 splx(s); 1469 mutex_exit(softnet_lock); 1470} 1471 1472/* 1473 * bridge_input: 1474 * 1475 * Receive input from a member interface. Queue the packet for 1476 * bridging if it is not for us. 1477 * should be called at splnet() 1478 */ 1479struct mbuf * 1480bridge_input(struct ifnet *ifp, struct mbuf *m) 1481{ 1482 struct bridge_softc *sc = ifp->if_bridge; 1483 struct bridge_iflist *bif; 1484 struct ether_header *eh; 1485 struct mbuf *mc; 1486 1487 if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 1488 return (m); 1489 1490 bif = bridge_lookup_member_if(sc, ifp); 1491 if (bif == NULL) 1492 return (m); 1493 1494 eh = mtod(m, struct ether_header *); 1495 1496 if (m->m_flags & (M_BCAST|M_MCAST)) { 1497 if (bif->bif_flags & IFBIF_STP) { 1498 /* Tap off 802.1D packets; they do not get forwarded. */ 1499 if (memcmp(eh->ether_dhost, bstp_etheraddr, 1500 ETHER_ADDR_LEN) == 0) { 1501 m = bstp_input(sc, bif, m); 1502 if (m == NULL) 1503 return (NULL); 1504 } 1505 1506 switch (bif->bif_state) { 1507 case BSTP_IFSTATE_BLOCKING: 1508 case BSTP_IFSTATE_LISTENING: 1509 case BSTP_IFSTATE_DISABLED: 1510 return (m); 1511 } 1512 } 1513 1514 /* 1515 * Make a deep copy of the packet and enqueue the copy 1516 * for bridge processing; return the original packet for 1517 * local processing. 1518 */ 1519 if (IF_QFULL(&sc->sc_if.if_snd)) { 1520 IF_DROP(&sc->sc_if.if_snd); 1521 return (m); 1522 } 1523 mc = m_dup(m, 0, M_COPYALL, M_NOWAIT); 1524 if (mc == NULL) 1525 return (m); 1526 1527 /* Perform the bridge forwarding function with the copy. */ 1528 IF_ENQUEUE(&sc->sc_if.if_snd, mc); 1529 softint_schedule(sc->sc_softintr); 1530 1531 /* Return the original packet for local processing. */ 1532 return (m); 1533 } 1534 1535 if (bif->bif_flags & IFBIF_STP) { 1536 switch (bif->bif_state) { 1537 case BSTP_IFSTATE_BLOCKING: 1538 case BSTP_IFSTATE_LISTENING: 1539 case BSTP_IFSTATE_DISABLED: 1540 return (m); 1541 } 1542 } 1543 1544 /* 1545 * Unicast. Make sure it's not for us. 1546 */ 1547 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 1548 /* It is destined for us. */ 1549 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_dhost, 1550 ETHER_ADDR_LEN) == 0 1551#if NCARP > 0 1552 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp, 1553 eh, IFT_ETHER, 0) != NULL) 1554#endif /* NCARP > 0 */ 1555 ) { 1556 if (bif->bif_flags & IFBIF_LEARNING) 1557 (void) bridge_rtupdate(sc, 1558 eh->ether_shost, ifp, 0, IFBAF_DYNAMIC); 1559 m->m_pkthdr.rcvif = bif->bif_ifp; 1560 return (m); 1561 } 1562 1563 /* We just received a packet that we sent out. */ 1564 if (memcmp(CLLADDR(bif->bif_ifp->if_sadl), eh->ether_shost, 1565 ETHER_ADDR_LEN) == 0 1566#if NCARP > 0 1567 || (bif->bif_ifp->if_carp && carp_ourether(bif->bif_ifp->if_carp, 1568 eh, IFT_ETHER, 1) != NULL) 1569#endif /* NCARP > 0 */ 1570 ) { 1571 m_freem(m); 1572 return (NULL); 1573 } 1574 } 1575 1576 /* Perform the bridge forwarding function. */ 1577 if (IF_QFULL(&sc->sc_if.if_snd)) { 1578 IF_DROP(&sc->sc_if.if_snd); 1579 m_freem(m); 1580 return (NULL); 1581 } 1582 IF_ENQUEUE(&sc->sc_if.if_snd, m); 1583 softint_schedule(sc->sc_softintr); 1584 1585 return (NULL); 1586} 1587 1588/* 1589 * bridge_broadcast: 1590 * 1591 * Send a frame to all interfaces that are members of 1592 * the bridge, except for the one on which the packet 1593 * arrived. 1594 */ 1595static void 1596bridge_broadcast(struct bridge_softc *sc, struct ifnet *src_if, 1597 struct mbuf *m) 1598{ 1599 struct bridge_iflist *bif; 1600 struct mbuf *mc; 1601 struct ifnet *dst_if; 1602 int used = 0; 1603 1604 LIST_FOREACH(bif, &sc->sc_iflist, bif_next) { 1605 dst_if = bif->bif_ifp; 1606 if (dst_if == src_if) 1607 continue; 1608 1609 if (bif->bif_flags & IFBIF_STP) { 1610 switch (bif->bif_state) { 1611 case BSTP_IFSTATE_BLOCKING: 1612 case BSTP_IFSTATE_DISABLED: 1613 continue; 1614 } 1615 } 1616 1617 if ((bif->bif_flags & IFBIF_DISCOVER) == 0 && 1618 (m->m_flags & (M_BCAST|M_MCAST)) == 0) 1619 continue; 1620 1621 if ((dst_if->if_flags & IFF_RUNNING) == 0) 1622 continue; 1623 1624 if (LIST_NEXT(bif, bif_next) == NULL) { 1625 mc = m; 1626 used = 1; 1627 } else { 1628 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 1629 if (mc == NULL) { 1630 sc->sc_if.if_oerrors++; 1631 continue; 1632 } 1633 } 1634 1635 bridge_enqueue(sc, dst_if, mc, 1); 1636 } 1637 if (used == 0) 1638 m_freem(m); 1639} 1640 1641/* 1642 * bridge_rtupdate: 1643 * 1644 * Add a bridge routing entry. 1645 */ 1646static int 1647bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, 1648 struct ifnet *dst_if, int setflags, uint8_t flags) 1649{ 1650 struct bridge_rtnode *brt; 1651 int error, s; 1652 1653 /* 1654 * A route for this destination might already exist. If so, 1655 * update it, otherwise create a new one. 1656 */ 1657 if ((brt = bridge_rtnode_lookup(sc, dst)) == NULL) { 1658 if (sc->sc_brtcnt >= sc->sc_brtmax) 1659 return (ENOSPC); 1660 1661 /* 1662 * Allocate a new bridge forwarding node, and 1663 * initialize the expiration time and Ethernet 1664 * address. 1665 */ 1666 s = splnet(); 1667 brt = pool_get(&bridge_rtnode_pool, PR_NOWAIT); 1668 splx(s); 1669 if (brt == NULL) 1670 return (ENOMEM); 1671 1672 memset(brt, 0, sizeof(*brt)); 1673 brt->brt_expire = time_uptime + sc->sc_brttimeout; 1674 brt->brt_flags = IFBAF_DYNAMIC; 1675 memcpy(brt->brt_addr, dst, ETHER_ADDR_LEN); 1676 1677 if ((error = bridge_rtnode_insert(sc, brt)) != 0) { 1678 s = splnet(); 1679 pool_put(&bridge_rtnode_pool, brt); 1680 splx(s); 1681 return (error); 1682 } 1683 } 1684 1685 brt->brt_ifp = dst_if; 1686 if (setflags) { 1687 brt->brt_flags = flags; 1688 if (flags & IFBAF_STATIC) 1689 brt->brt_expire = 0; 1690 else 1691 brt->brt_expire = time_uptime + sc->sc_brttimeout; 1692 } 1693 1694 return (0); 1695} 1696 1697/* 1698 * bridge_rtlookup: 1699 * 1700 * Lookup the destination interface for an address. 1701 */ 1702static struct ifnet * 1703bridge_rtlookup(struct bridge_softc *sc, const uint8_t *addr) 1704{ 1705 struct bridge_rtnode *brt; 1706 1707 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL) 1708 return (NULL); 1709 1710 return (brt->brt_ifp); 1711} 1712 1713/* 1714 * bridge_rttrim: 1715 * 1716 * Trim the routine table so that we have a number 1717 * of routing entries less than or equal to the 1718 * maximum number. 1719 */ 1720static void 1721bridge_rttrim(struct bridge_softc *sc) 1722{ 1723 struct bridge_rtnode *brt, *nbrt; 1724 1725 /* Make sure we actually need to do this. */ 1726 if (sc->sc_brtcnt <= sc->sc_brtmax) 1727 return; 1728 1729 /* Force an aging cycle; this might trim enough addresses. */ 1730 bridge_rtage(sc); 1731 if (sc->sc_brtcnt <= sc->sc_brtmax) 1732 return; 1733 1734 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) { 1735 nbrt = LIST_NEXT(brt, brt_list); 1736 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { 1737 bridge_rtnode_destroy(sc, brt); 1738 if (sc->sc_brtcnt <= sc->sc_brtmax) 1739 return; 1740 } 1741 } 1742} 1743 1744/* 1745 * bridge_timer: 1746 * 1747 * Aging timer for the bridge. 1748 */ 1749static void 1750bridge_timer(void *arg) 1751{ 1752 struct bridge_softc *sc = arg; 1753 int s; 1754 1755 s = splnet(); 1756 bridge_rtage(sc); 1757 splx(s); 1758 1759 if (sc->sc_if.if_flags & IFF_RUNNING) 1760 callout_reset(&sc->sc_brcallout, 1761 bridge_rtable_prune_period * hz, bridge_timer, sc); 1762} 1763 1764/* 1765 * bridge_rtage: 1766 * 1767 * Perform an aging cycle. 1768 */ 1769static void 1770bridge_rtage(struct bridge_softc *sc) 1771{ 1772 struct bridge_rtnode *brt, *nbrt; 1773 1774 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) { 1775 nbrt = LIST_NEXT(brt, brt_list); 1776 if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) { 1777 if (time_uptime >= brt->brt_expire) 1778 bridge_rtnode_destroy(sc, brt); 1779 } 1780 } 1781} 1782 1783/* 1784 * bridge_rtflush: 1785 * 1786 * Remove all dynamic addresses from the bridge. 1787 */ 1788static void 1789bridge_rtflush(struct bridge_softc *sc, int full) 1790{ 1791 struct bridge_rtnode *brt, *nbrt; 1792 1793 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) { 1794 nbrt = LIST_NEXT(brt, brt_list); 1795 if (full || (brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC) 1796 bridge_rtnode_destroy(sc, brt); 1797 } 1798} 1799 1800/* 1801 * bridge_rtdaddr: 1802 * 1803 * Remove an address from the table. 1804 */ 1805static int 1806bridge_rtdaddr(struct bridge_softc *sc, const uint8_t *addr) 1807{ 1808 struct bridge_rtnode *brt; 1809 1810 if ((brt = bridge_rtnode_lookup(sc, addr)) == NULL) 1811 return (ENOENT); 1812 1813 bridge_rtnode_destroy(sc, brt); 1814 return (0); 1815} 1816 1817/* 1818 * bridge_rtdelete: 1819 * 1820 * Delete routes to a speicifc member interface. 1821 */ 1822static void 1823bridge_rtdelete(struct bridge_softc *sc, struct ifnet *ifp) 1824{ 1825 struct bridge_rtnode *brt, *nbrt; 1826 1827 for (brt = LIST_FIRST(&sc->sc_rtlist); brt != NULL; brt = nbrt) { 1828 nbrt = LIST_NEXT(brt, brt_list); 1829 if (brt->brt_ifp == ifp) 1830 bridge_rtnode_destroy(sc, brt); 1831 } 1832} 1833 1834/* 1835 * bridge_rtable_init: 1836 * 1837 * Initialize the route table for this bridge. 1838 */ 1839static int 1840bridge_rtable_init(struct bridge_softc *sc) 1841{ 1842 int i; 1843 1844 sc->sc_rthash = malloc(sizeof(*sc->sc_rthash) * BRIDGE_RTHASH_SIZE, 1845 M_DEVBUF, M_NOWAIT); 1846 if (sc->sc_rthash == NULL) 1847 return (ENOMEM); 1848 1849 for (i = 0; i < BRIDGE_RTHASH_SIZE; i++) 1850 LIST_INIT(&sc->sc_rthash[i]); 1851 1852 sc->sc_rthash_key = arc4random(); 1853 1854 LIST_INIT(&sc->sc_rtlist); 1855 1856 return (0); 1857} 1858 1859/* 1860 * bridge_rtable_fini: 1861 * 1862 * Deconstruct the route table for this bridge. 1863 */ 1864static void 1865bridge_rtable_fini(struct bridge_softc *sc) 1866{ 1867 1868 free(sc->sc_rthash, M_DEVBUF); 1869} 1870 1871/* 1872 * The following hash function is adapted from "Hash Functions" by Bob Jenkins 1873 * ("Algorithm Alley", Dr. Dobbs Journal, September 1997). 1874 */ 1875#define mix(a, b, c) \ 1876do { \ 1877 a -= b; a -= c; a ^= (c >> 13); \ 1878 b -= c; b -= a; b ^= (a << 8); \ 1879 c -= a; c -= b; c ^= (b >> 13); \ 1880 a -= b; a -= c; a ^= (c >> 12); \ 1881 b -= c; b -= a; b ^= (a << 16); \ 1882 c -= a; c -= b; c ^= (b >> 5); \ 1883 a -= b; a -= c; a ^= (c >> 3); \ 1884 b -= c; b -= a; b ^= (a << 10); \ 1885 c -= a; c -= b; c ^= (b >> 15); \ 1886} while (/*CONSTCOND*/0) 1887 1888static inline uint32_t 1889bridge_rthash(struct bridge_softc *sc, const uint8_t *addr) 1890{ 1891 uint32_t a = 0x9e3779b9, b = 0x9e3779b9, c = sc->sc_rthash_key; 1892 1893 b += addr[5] << 8; 1894 b += addr[4]; 1895 a += addr[3] << 24; 1896 a += addr[2] << 16; 1897 a += addr[1] << 8; 1898 a += addr[0]; 1899 1900 mix(a, b, c); 1901 1902 return (c & BRIDGE_RTHASH_MASK); 1903} 1904 1905#undef mix 1906 1907/* 1908 * bridge_rtnode_lookup: 1909 * 1910 * Look up a bridge route node for the specified destination. 1911 */ 1912static struct bridge_rtnode * 1913bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr) 1914{ 1915 struct bridge_rtnode *brt; 1916 uint32_t hash; 1917 int dir; 1918 1919 hash = bridge_rthash(sc, addr); 1920 LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) { 1921 dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN); 1922 if (dir == 0) 1923 return (brt); 1924 if (dir > 0) 1925 return (NULL); 1926 } 1927 1928 return (NULL); 1929} 1930 1931/* 1932 * bridge_rtnode_insert: 1933 * 1934 * Insert the specified bridge node into the route table. We 1935 * assume the entry is not already in the table. 1936 */ 1937static int 1938bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt) 1939{ 1940 struct bridge_rtnode *lbrt; 1941 uint32_t hash; 1942 int dir; 1943 1944 hash = bridge_rthash(sc, brt->brt_addr); 1945 1946 lbrt = LIST_FIRST(&sc->sc_rthash[hash]); 1947 if (lbrt == NULL) { 1948 LIST_INSERT_HEAD(&sc->sc_rthash[hash], brt, brt_hash); 1949 goto out; 1950 } 1951 1952 do { 1953 dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN); 1954 if (dir == 0) 1955 return (EEXIST); 1956 if (dir > 0) { 1957 LIST_INSERT_BEFORE(lbrt, brt, brt_hash); 1958 goto out; 1959 } 1960 if (LIST_NEXT(lbrt, brt_hash) == NULL) { 1961 LIST_INSERT_AFTER(lbrt, brt, brt_hash); 1962 goto out; 1963 } 1964 lbrt = LIST_NEXT(lbrt, brt_hash); 1965 } while (lbrt != NULL); 1966 1967#ifdef DIAGNOSTIC 1968 panic("bridge_rtnode_insert: impossible"); 1969#endif 1970 1971 out: 1972 LIST_INSERT_HEAD(&sc->sc_rtlist, brt, brt_list); 1973 sc->sc_brtcnt++; 1974 1975 return (0); 1976} 1977 1978/* 1979 * bridge_rtnode_destroy: 1980 * 1981 * Destroy a bridge rtnode. 1982 */ 1983static void 1984bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt) 1985{ 1986 int s = splnet(); 1987 1988 LIST_REMOVE(brt, brt_hash); 1989 1990 LIST_REMOVE(brt, brt_list); 1991 sc->sc_brtcnt--; 1992 pool_put(&bridge_rtnode_pool, brt); 1993 1994 splx(s); 1995} 1996 1997#if defined(BRIDGE_IPF) && defined(PFIL_HOOKS) 1998extern struct pfil_head inet_pfil_hook; /* XXX */ 1999extern struct pfil_head inet6_pfil_hook; /* XXX */ 2000 2001/* 2002 * Send bridge packets through IPF if they are one of the types IPF can deal 2003 * with, or if they are ARP or REVARP. (IPF will pass ARP and REVARP without 2004 * question.) 2005 */ 2006static int 2007bridge_ipf(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir) 2008{ 2009 int snap, error; 2010 struct ether_header *eh1, eh2; 2011 struct llc llc1; 2012 uint16_t ether_type; 2013 2014 snap = 0; 2015 error = -1; /* Default error if not error == 0 */ 2016 eh1 = mtod(*mp, struct ether_header *); 2017 ether_type = ntohs(eh1->ether_type); 2018 2019 /* 2020 * Check for SNAP/LLC. 2021 */ 2022 if (ether_type < ETHERMTU) { 2023 struct llc *llc2 = (struct llc *)(eh1 + 1); 2024 2025 if ((*mp)->m_len >= ETHER_HDR_LEN + 8 && 2026 llc2->llc_dsap == LLC_SNAP_LSAP && 2027 llc2->llc_ssap == LLC_SNAP_LSAP && 2028 llc2->llc_control == LLC_UI) { 2029 ether_type = htons(llc2->llc_un.type_snap.ether_type); 2030 snap = 1; 2031 } 2032 } 2033 2034 /* 2035 * If we're trying to filter bridge traffic, don't look at anything 2036 * other than IP and ARP traffic. If the filter doesn't understand 2037 * IPv6, don't allow IPv6 through the bridge either. This is lame 2038 * since if we really wanted, say, an AppleTalk filter, we are hosed, 2039 * but of course we don't have an AppleTalk filter to begin with. 2040 * (Note that since IPF doesn't understand ARP it will pass *ALL* 2041 * ARP traffic.) 2042 */ 2043 switch (ether_type) { 2044 case ETHERTYPE_ARP: 2045 case ETHERTYPE_REVARP: 2046 return 0; /* Automatically pass */ 2047 case ETHERTYPE_IP: 2048# ifdef INET6 2049 case ETHERTYPE_IPV6: 2050# endif /* INET6 */ 2051 break; 2052 default: 2053 goto bad; 2054 } 2055 2056 /* Strip off the Ethernet header and keep a copy. */ 2057 m_copydata(*mp, 0, ETHER_HDR_LEN, (void *) &eh2); 2058 m_adj(*mp, ETHER_HDR_LEN); 2059 2060 /* Strip off snap header, if present */ 2061 if (snap) { 2062 m_copydata(*mp, 0, sizeof(struct llc), (void *) &llc1); 2063 m_adj(*mp, sizeof(struct llc)); 2064 } 2065 2066 /* 2067 * Check basic packet sanity and run IPF through pfil. 2068 */ 2069 KASSERT(!cpu_intr_p()); 2070 switch (ether_type) 2071 { 2072 case ETHERTYPE_IP : 2073 error = (dir == PFIL_IN) ? bridge_ip_checkbasic(mp) : 0; 2074 if (error == 0) 2075 error = pfil_run_hooks(&inet_pfil_hook, mp, ifp, dir); 2076 break; 2077# ifdef INET6 2078 case ETHERTYPE_IPV6 : 2079 error = (dir == PFIL_IN) ? bridge_ip6_checkbasic(mp) : 0; 2080 if (error == 0) 2081 error = pfil_run_hooks(&inet6_pfil_hook, mp, ifp, dir); 2082 break; 2083# endif 2084 default : 2085 error = 0; 2086 break; 2087 } 2088 2089 if (*mp == NULL) 2090 return error; 2091 if (error != 0) 2092 goto bad; 2093 2094 error = -1; 2095 2096 /* 2097 * Finally, put everything back the way it was and return 2098 */ 2099 if (snap) { 2100 M_PREPEND(*mp, sizeof(struct llc), M_DONTWAIT); 2101 if (*mp == NULL) 2102 return error; 2103 bcopy(&llc1, mtod(*mp, void *), sizeof(struct llc)); 2104 } 2105 2106 M_PREPEND(*mp, ETHER_HDR_LEN, M_DONTWAIT); 2107 if (*mp == NULL) 2108 return error; 2109 bcopy(&eh2, mtod(*mp, void *), ETHER_HDR_LEN); 2110 2111 return 0; 2112 2113 bad: 2114 m_freem(*mp); 2115 *mp = NULL; 2116 return error; 2117} 2118 2119/* 2120 * Perform basic checks on header size since 2121 * IPF assumes ip_input has already processed 2122 * it for it. Cut-and-pasted from ip_input.c. 2123 * Given how simple the IPv6 version is, 2124 * does the IPv4 version really need to be 2125 * this complicated? 2126 * 2127 * XXX Should we update ipstat here, or not? 2128 * XXX Right now we update ipstat but not 2129 * XXX csum_counter. 2130 */ 2131static int 2132bridge_ip_checkbasic(struct mbuf **mp) 2133{ 2134 struct mbuf *m = *mp; 2135 struct ip *ip; 2136 int len, hlen; 2137 2138 if (*mp == NULL) 2139 return -1; 2140 2141 if (IP_HDR_ALIGNED_P(mtod(m, void *)) == 0) { 2142 if ((m = m_copyup(m, sizeof(struct ip), 2143 (max_linkhdr + 3) & ~3)) == NULL) { 2144 /* XXXJRT new stat, please */ 2145 ip_statinc(IP_STAT_TOOSMALL); 2146 goto bad; 2147 } 2148 } else if (__predict_false(m->m_len < sizeof (struct ip))) { 2149 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) { 2150 ip_statinc(IP_STAT_TOOSMALL); 2151 goto bad; 2152 } 2153 } 2154 ip = mtod(m, struct ip *); 2155 if (ip == NULL) goto bad; 2156 2157 if (ip->ip_v != IPVERSION) { 2158 ip_statinc(IP_STAT_BADVERS); 2159 goto bad; 2160 } 2161 hlen = ip->ip_hl << 2; 2162 if (hlen < sizeof(struct ip)) { /* minimum header length */ 2163 ip_statinc(IP_STAT_BADHLEN); 2164 goto bad; 2165 } 2166 if (hlen > m->m_len) { 2167 if ((m = m_pullup(m, hlen)) == 0) { 2168 ip_statinc(IP_STAT_BADHLEN); 2169 goto bad; 2170 } 2171 ip = mtod(m, struct ip *); 2172 if (ip == NULL) goto bad; 2173 } 2174 2175 switch (m->m_pkthdr.csum_flags & 2176 ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) | 2177 M_CSUM_IPv4_BAD)) { 2178 case M_CSUM_IPv4|M_CSUM_IPv4_BAD: 2179 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); */ 2180 goto bad; 2181 2182 case M_CSUM_IPv4: 2183 /* Checksum was okay. */ 2184 /* INET_CSUM_COUNTER_INCR(&ip_hwcsum_ok); */ 2185 break; 2186 2187 default: 2188 /* Must compute it ourselves. */ 2189 /* INET_CSUM_COUNTER_INCR(&ip_swcsum); */ 2190 if (in_cksum(m, hlen) != 0) 2191 goto bad; 2192 break; 2193 } 2194 2195 /* Retrieve the packet length. */ 2196 len = ntohs(ip->ip_len); 2197 2198 /* 2199 * Check for additional length bogosity 2200 */ 2201 if (len < hlen) { 2202 ip_statinc(IP_STAT_BADLEN); 2203 goto bad; 2204 } 2205 2206 /* 2207 * Check that the amount of data in the buffers 2208 * is as at least much as the IP header would have us expect. 2209 * Drop packet if shorter than we expect. 2210 */ 2211 if (m->m_pkthdr.len < len) { 2212 ip_statinc(IP_STAT_TOOSHORT); 2213 goto bad; 2214 } 2215 2216 /* Checks out, proceed */ 2217 *mp = m; 2218 return 0; 2219 2220 bad: 2221 *mp = m; 2222 return -1; 2223} 2224 2225# ifdef INET6 2226/* 2227 * Same as above, but for IPv6. 2228 * Cut-and-pasted from ip6_input.c. 2229 * XXX Should we update ip6stat, or not? 2230 */ 2231static int 2232bridge_ip6_checkbasic(struct mbuf **mp) 2233{ 2234 struct mbuf *m = *mp; 2235 struct ip6_hdr *ip6; 2236 2237 /* 2238 * If the IPv6 header is not aligned, slurp it up into a new 2239 * mbuf with space for link headers, in the event we forward 2240 * it. Otherwise, if it is aligned, make sure the entire base 2241 * IPv6 header is in the first mbuf of the chain. 2242 */ 2243 if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { 2244 struct ifnet *inifp = m->m_pkthdr.rcvif; 2245 if ((m = m_copyup(m, sizeof(struct ip6_hdr), 2246 (max_linkhdr + 3) & ~3)) == NULL) { 2247 /* XXXJRT new stat, please */ 2248 ip6_statinc(IP6_STAT_TOOSMALL); 2249 in6_ifstat_inc(inifp, ifs6_in_hdrerr); 2250 goto bad; 2251 } 2252 } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { 2253 struct ifnet *inifp = m->m_pkthdr.rcvif; 2254 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { 2255 ip6_statinc(IP6_STAT_TOOSMALL); 2256 in6_ifstat_inc(inifp, ifs6_in_hdrerr); 2257 goto bad; 2258 } 2259 } 2260 2261 ip6 = mtod(m, struct ip6_hdr *); 2262 2263 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 2264 ip6_statinc(IP6_STAT_BADVERS); 2265 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); 2266 goto bad; 2267 } 2268 2269 /* Checks out, proceed */ 2270 *mp = m; 2271 return 0; 2272 2273 bad: 2274 *mp = m; 2275 return -1; 2276} 2277# endif /* INET6 */ 2278#endif /* BRIDGE_IPF && PFIL_HOOKS */ 2279