root/net/if_bridge.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bridgeattach
  2. bridge_clone_create
  3. bridge_clone_destroy
  4. bridge_delete
  5. bridge_ioctl
  6. bridge_ifdetach
  7. bridge_update
  8. bridge_bifconf
  9. bridge_brlconf
  10. bridge_init
  11. bridge_stop
  12. bridge_output
  13. bridge_start
  14. bridgeintr
  15. bridgeintr_frame
  16. bridge_input
  17. bridge_broadcast
  18. bridge_span
  19. bridge_rtupdate
  20. bridge_rtlookup
  21. bridge_hash
  22. bridge_rttrim
  23. bridge_timer
  24. bridge_rtage
  25. bridge_rtagenode
  26. bridge_rtflush
  27. bridge_rtdaddr
  28. bridge_rtdelete
  29. bridge_rtfind
  30. bridge_blocknonip
  31. bridge_filterrule
  32. bridge_addrule
  33. bridge_flushrule
  34. bridge_ipsec
  35. bridge_filter
  36. bridge_fragment
  37. bridge_ifenqueue
  38. bridge_send_icmp_err

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

/* [<][>][^][v][top][bottom][index][help] */