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

Cache object: 04342c05b1938ae27e9b1088c0ca19da


[ 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.