The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/if_bridge.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 545ceadef93000735b8829f964147c50


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.