LCOV - code coverage report
Current view: top level - net - if_bridge.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 969 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_bridge.c,v 1.308 2018/04/19 22:31:25 dlg 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             : #include "vlan.h"
      39             : #include "mpw.h"
      40             : 
      41             : #include <sys/param.h>
      42             : #include <sys/systm.h>
      43             : #include <sys/mbuf.h>
      44             : #include <sys/socket.h>
      45             : #include <sys/ioctl.h>
      46             : #include <sys/kernel.h>
      47             : 
      48             : #include <net/if.h>
      49             : #include <net/if_types.h>
      50             : #include <net/if_llc.h>
      51             : #include <net/netisr.h>
      52             : 
      53             : #include <netinet/in.h>
      54             : #include <netinet/ip.h>
      55             : #include <netinet/ip_var.h>
      56             : #include <netinet/if_ether.h>
      57             : #include <netinet/ip_icmp.h>
      58             : 
      59             : #ifdef IPSEC
      60             : #include <netinet/ip_ipsp.h>
      61             : #include <net/if_enc.h>
      62             : #endif
      63             : 
      64             : #ifdef INET6
      65             : #include <netinet6/in6_var.h>
      66             : #include <netinet/ip6.h>
      67             : #include <netinet6/ip6_var.h>
      68             : #endif
      69             : 
      70             : #if NPF > 0
      71             : #include <net/pfvar.h>
      72             : #define BRIDGE_IN       PF_IN
      73             : #define BRIDGE_OUT      PF_OUT
      74             : #else
      75             : #define BRIDGE_IN       0
      76             : #define BRIDGE_OUT      1
      77             : #endif
      78             : 
      79             : #if NBPFILTER > 0
      80             : #include <net/bpf.h>
      81             : #endif
      82             : 
      83             : #if NCARP > 0
      84             : #include <netinet/ip_carp.h>
      85             : #endif
      86             : 
      87             : #if NVLAN > 0
      88             : #include <net/if_vlan_var.h>
      89             : #endif
      90             : 
      91             : #include <net/if_bridge.h>
      92             : 
      93             : /*
      94             :  * Maximum number of addresses to cache
      95             :  */
      96             : #ifndef BRIDGE_RTABLE_MAX
      97             : #define BRIDGE_RTABLE_MAX       100
      98             : #endif
      99             : 
     100             : /*
     101             :  * Timeout (in seconds) for entries learned dynamically
     102             :  */
     103             : #ifndef BRIDGE_RTABLE_TIMEOUT
     104             : #define BRIDGE_RTABLE_TIMEOUT   240
     105             : #endif
     106             : 
     107             : void    bridgeattach(int);
     108             : int     bridge_ioctl(struct ifnet *, u_long, caddr_t);
     109             : void    bridge_ifdetach(void *);
     110             : void    bridge_spandetach(void *);
     111             : int     bridge_input(struct ifnet *, struct mbuf *, void *);
     112             : void    bridge_process(struct ifnet *, struct mbuf *);
     113             : void    bridgeintr_frame(struct bridge_softc *, struct ifnet *, struct mbuf *);
     114             : void    bridge_broadcast(struct bridge_softc *, struct ifnet *,
     115             :     struct ether_header *, struct mbuf *);
     116             : void    bridge_localbroadcast(struct bridge_softc *, struct ifnet *,
     117             :     struct ether_header *, struct mbuf *);
     118             : void    bridge_span(struct bridge_softc *, struct mbuf *);
     119             : void    bridge_stop(struct bridge_softc *);
     120             : void    bridge_init(struct bridge_softc *);
     121             : int     bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
     122             : int bridge_blocknonip(struct ether_header *, struct mbuf *);
     123             : void    bridge_ifinput(struct ifnet *, struct mbuf *);
     124             : int     bridge_dummy_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     125             :     struct rtentry *);
     126             : #ifdef IPSEC
     127             : int bridge_ipsec(struct bridge_softc *, struct ifnet *,
     128             :     struct ether_header *, int, struct llc *,
     129             :     int, int, int, struct mbuf *);
     130             : #endif
     131             : int     bridge_clone_create(struct if_clone *, int);
     132             : int     bridge_clone_destroy(struct ifnet *ifp);
     133             : int     bridge_delete(struct bridge_softc *, struct bridge_iflist *);
     134             : 
     135             : #define ETHERADDR_IS_IP_MCAST(a) \
     136             :         /* struct etheraddr *a; */                              \
     137             :         ((a)->ether_addr_octet[0] == 0x01 &&                 \
     138             :          (a)->ether_addr_octet[1] == 0x00 &&                 \
     139             :          (a)->ether_addr_octet[2] == 0x5e)
     140             : 
     141             : struct niqueue bridgeintrq = NIQUEUE_INITIALIZER(1024, NETISR_BRIDGE);
     142             : 
     143             : struct if_clone bridge_cloner =
     144             :     IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy);
     145             : 
     146             : void
     147           0 : bridgeattach(int n)
     148             : {
     149           0 :         if_clone_attach(&bridge_cloner);
     150           0 : }
     151             : 
     152             : int
     153           0 : bridge_clone_create(struct if_clone *ifc, int unit)
     154             : {
     155             :         struct bridge_softc *sc;
     156             :         struct ifnet *ifp;
     157             :         int i;
     158             : 
     159           0 :         sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
     160           0 :         sc->sc_stp = bstp_create(&sc->sc_if);
     161           0 :         if (!sc->sc_stp) {
     162           0 :                 free(sc, M_DEVBUF, sizeof *sc);
     163           0 :                 return (ENOMEM);
     164             :         }
     165             : 
     166           0 :         sc->sc_brtmax = BRIDGE_RTABLE_MAX;
     167           0 :         sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
     168           0 :         timeout_set(&sc->sc_brtimeout, bridge_rtage, sc);
     169           0 :         TAILQ_INIT(&sc->sc_iflist);
     170           0 :         TAILQ_INIT(&sc->sc_spanlist);
     171           0 :         for (i = 0; i < BRIDGE_RTABLE_SIZE; i++)
     172           0 :                 LIST_INIT(&sc->sc_rts[i]);
     173           0 :         arc4random_buf(&sc->sc_hashkey, sizeof(sc->sc_hashkey));
     174             :         ifp = &sc->sc_if;
     175           0 :         snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
     176             :             unit);
     177           0 :         ifp->if_softc = sc;
     178           0 :         ifp->if_mtu = ETHERMTU;
     179           0 :         ifp->if_ioctl = bridge_ioctl;
     180           0 :         ifp->if_output = bridge_dummy_output;
     181           0 :         ifp->if_xflags = IFXF_CLONED;
     182           0 :         ifp->if_start = NULL;
     183           0 :         ifp->if_type = IFT_BRIDGE;
     184           0 :         ifp->if_hdrlen = ETHER_HDR_LEN;
     185             : 
     186           0 :         if_attach(ifp);
     187           0 :         if_alloc_sadl(ifp);
     188             : 
     189             : #if NBPFILTER > 0
     190           0 :         bpfattach(&sc->sc_if.if_bpf, ifp,
     191             :             DLT_EN10MB, ETHER_HDR_LEN);
     192             : #endif
     193             : 
     194           0 :         if_ih_insert(ifp, ether_input, NULL);
     195             : 
     196           0 :         return (0);
     197           0 : }
     198             : 
     199             : int
     200           0 : bridge_dummy_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     201             :     struct rtentry *rt)
     202             : {
     203           0 :         m_freem(m);
     204           0 :         return (EAFNOSUPPORT);
     205             : }
     206             : 
     207             : int
     208           0 : bridge_clone_destroy(struct ifnet *ifp)
     209             : {
     210           0 :         struct bridge_softc *sc = ifp->if_softc;
     211             :         struct bridge_iflist *bif;
     212             : 
     213           0 :         bridge_stop(sc);
     214           0 :         bridge_rtflush(sc, IFBF_FLUSHALL);
     215           0 :         while ((bif = TAILQ_FIRST(&sc->sc_iflist)) != NULL)
     216           0 :                 bridge_delete(sc, bif);
     217           0 :         while ((bif = TAILQ_FIRST(&sc->sc_spanlist)) != NULL)
     218           0 :                 bridge_spandetach(bif);
     219             : 
     220           0 :         bstp_destroy(sc->sc_stp);
     221             : 
     222             :         /* Undo pseudo-driver changes. */
     223           0 :         if_deactivate(ifp);
     224             : 
     225           0 :         if_ih_remove(ifp, ether_input, NULL);
     226             : 
     227           0 :         KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs));
     228             : 
     229           0 :         if_detach(ifp);
     230             : 
     231           0 :         free(sc, M_DEVBUF, sizeof *sc);
     232           0 :         return (0);
     233             : }
     234             : 
     235             : int
     236           0 : bridge_delete(struct bridge_softc *sc, struct bridge_iflist *p)
     237             : {
     238             :         int error;
     239             : 
     240           0 :         if (p->bif_flags & IFBIF_STP)
     241           0 :                 bstp_delete(p->bif_stp);
     242             : 
     243           0 :         p->ifp->if_bridgeport = NULL;
     244           0 :         error = ifpromisc(p->ifp, 0);
     245           0 :         hook_disestablish(p->ifp->if_detachhooks, p->bif_dhcookie);
     246             : 
     247           0 :         if_ih_remove(p->ifp, bridge_input, NULL);
     248           0 :         TAILQ_REMOVE(&sc->sc_iflist, p, next);
     249           0 :         bridge_rtdelete(sc, p->ifp, 0);
     250           0 :         bridge_flushrule(p);
     251           0 :         free(p, M_DEVBUF, sizeof *p);
     252             : 
     253           0 :         return (error);
     254             : }
     255             : 
     256             : int
     257           0 : bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
     258             : {
     259           0 :         struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc;
     260           0 :         struct ifbreq *req = (struct ifbreq *)data;
     261           0 :         struct ifbropreq *brop = (struct ifbropreq *)data;
     262             :         struct ifnet *ifs;
     263             :         struct bridge_iflist *p;
     264             :         struct bstp_port *bp;
     265           0 :         struct bstp_state *bs = sc->sc_stp;
     266             :         int error = 0;
     267             : 
     268           0 :         switch (cmd) {
     269             :         case SIOCBRDGADD:
     270             :         /* bridge(4) does not distinguish between routing/forwarding ports */
     271             :         case SIOCBRDGADDL:
     272           0 :                 if ((error = suser(curproc)) != 0)
     273             :                         break;
     274             : 
     275           0 :                 ifs = ifunit(req->ifbr_ifsname);
     276             : 
     277             :                 /* try to create the interface if it does't exist */
     278           0 :                 if (ifs == NULL && if_clone_create(req->ifbr_ifsname, 0) == 0)
     279           0 :                         ifs = ifunit(req->ifbr_ifsname);
     280             : 
     281           0 :                 if (ifs == NULL) {                      /* no such interface */
     282             :                         error = ENOENT;
     283           0 :                         break;
     284             :                 }
     285             : 
     286           0 :                 if (ifs->if_bridgeport != NULL) {
     287           0 :                         p = (struct bridge_iflist *)ifs->if_bridgeport;
     288           0 :                         if (p->bridge_sc == sc)
     289           0 :                                 error = EEXIST;
     290             :                         else
     291             :                                 error = EBUSY;
     292             :                         break;
     293             :                 }
     294             : 
     295             :                 /* If it's in the span list, it can't be a member. */
     296           0 :                 TAILQ_FOREACH(p, &sc->sc_spanlist, next)
     297           0 :                         if (p->ifp == ifs)
     298             :                                 break;
     299           0 :                 if (p != NULL) {
     300             :                         error = EBUSY;
     301           0 :                         break;
     302             :                 }
     303             : 
     304           0 :                 if (ifs->if_type == IFT_ETHER) {
     305           0 :                         error = ifpromisc(ifs, 1);
     306           0 :                         if (error != 0)
     307             :                                 break;
     308             :                 }
     309             : #if NMPW > 0
     310           0 :                 else if (ifs->if_type == IFT_MPLSTUNNEL) {
     311             :                         /* Nothing needed */
     312             :                 }
     313             : #endif /* NMPW */
     314             :                 else {
     315             :                         error = EINVAL;
     316           0 :                         break;
     317             :                 }
     318             : 
     319           0 :                 p = malloc(sizeof(*p), M_DEVBUF, M_NOWAIT|M_ZERO);
     320           0 :                 if (p == NULL) {
     321           0 :                         if (ifs->if_type == IFT_ETHER)
     322           0 :                                 ifpromisc(ifs, 0);
     323             :                         error = ENOMEM;
     324           0 :                         break;
     325             :                 }
     326             : 
     327           0 :                 p->bridge_sc = sc;
     328           0 :                 p->ifp = ifs;
     329           0 :                 p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER;
     330           0 :                 SIMPLEQ_INIT(&p->bif_brlin);
     331           0 :                 SIMPLEQ_INIT(&p->bif_brlout);
     332           0 :                 ifs->if_bridgeport = (caddr_t)p;
     333           0 :                 p->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
     334           0 :                     bridge_ifdetach, ifs);
     335           0 :                 if_ih_insert(p->ifp, bridge_input, NULL);
     336           0 :                 TAILQ_INSERT_TAIL(&sc->sc_iflist, p, next);
     337           0 :                 break;
     338             :         case SIOCBRDGDEL:
     339           0 :                 if ((error = suser(curproc)) != 0)
     340             :                         break;
     341           0 :                 ifs = ifunit(req->ifbr_ifsname);
     342           0 :                 if (ifs == NULL) {
     343             :                         error = ENOENT;
     344           0 :                         break;
     345             :                 }
     346           0 :                 p = (struct bridge_iflist *)ifs->if_bridgeport;
     347           0 :                 if (p == NULL || p->bridge_sc != sc) {
     348             :                         error = ESRCH;
     349           0 :                         break;
     350             :                 }
     351           0 :                 error = bridge_delete(sc, p);
     352           0 :                 break;
     353             :         case SIOCBRDGIFS:
     354           0 :                 error = bridge_bifconf(sc, (struct ifbifconf *)data);
     355           0 :                 break;
     356             :         case SIOCBRDGADDS:
     357           0 :                 if ((error = suser(curproc)) != 0)
     358             :                         break;
     359           0 :                 ifs = ifunit(req->ifbr_ifsname);
     360           0 :                 if (ifs == NULL) {                      /* no such interface */
     361             :                         error = ENOENT;
     362           0 :                         break;
     363             :                 }
     364           0 :                 if (ifs->if_type != IFT_ETHER &&
     365           0 :                     ifs->if_type != IFT_MPLSTUNNEL) {
     366             :                         error = EINVAL;
     367           0 :                         break;
     368             :                 }
     369           0 :                 if (ifs->if_bridgeport != NULL) {
     370             :                         error = EBUSY;
     371           0 :                         break;
     372             :                 }
     373           0 :                 TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
     374           0 :                         if (p->ifp == ifs)
     375             :                                 break;
     376             :                 }
     377           0 :                 if (p != NULL) {
     378             :                         error = EEXIST;
     379           0 :                         break;
     380             :                 }
     381           0 :                 p = malloc(sizeof(*p), M_DEVBUF, M_NOWAIT|M_ZERO);
     382           0 :                 if (p == NULL) {
     383             :                         error = ENOMEM;
     384           0 :                         break;
     385             :                 }
     386           0 :                 p->ifp = ifs;
     387           0 :                 p->bif_flags = IFBIF_SPAN;
     388           0 :                 p->bridge_sc = sc;
     389           0 :                 p->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
     390             :                     bridge_spandetach, p);
     391           0 :                 SIMPLEQ_INIT(&p->bif_brlin);
     392           0 :                 SIMPLEQ_INIT(&p->bif_brlout);
     393           0 :                 TAILQ_INSERT_TAIL(&sc->sc_spanlist, p, next);
     394           0 :                 break;
     395             :         case SIOCBRDGDELS:
     396           0 :                 if ((error = suser(curproc)) != 0)
     397             :                         break;
     398           0 :                 TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
     399           0 :                         if (strncmp(p->ifp->if_xname, req->ifbr_ifsname,
     400           0 :                             sizeof(p->ifp->if_xname)) == 0) {
     401           0 :                                 bridge_spandetach(p);
     402           0 :                                 break;
     403             :                         }
     404             :                 }
     405           0 :                 if (p == NULL) {
     406             :                         error = ENOENT;
     407           0 :                         break;
     408             :                 }
     409             :                 break;
     410             :         case SIOCBRDGGIFFLGS:
     411           0 :                 ifs = ifunit(req->ifbr_ifsname);
     412           0 :                 if (ifs == NULL) {
     413             :                         error = ENOENT;
     414           0 :                         break;
     415             :                 }
     416           0 :                 p = (struct bridge_iflist *)ifs->if_bridgeport;
     417           0 :                 if (p == NULL || p->bridge_sc != sc) {
     418             :                         error = ESRCH;
     419           0 :                         break;
     420             :                 }
     421           0 :                 req->ifbr_ifsflags = p->bif_flags;
     422           0 :                 req->ifbr_portno = p->ifp->if_index & 0xfff;
     423           0 :                 req->ifbr_protected = p->bif_protected;
     424           0 :                 if (p->bif_flags & IFBIF_STP) {
     425           0 :                         bp = p->bif_stp;
     426           0 :                         req->ifbr_state = bstp_getstate(bs, bp);
     427           0 :                         req->ifbr_priority = bp->bp_priority;
     428           0 :                         req->ifbr_path_cost = bp->bp_path_cost;
     429           0 :                         req->ifbr_proto = bp->bp_protover;
     430           0 :                         req->ifbr_role = bp->bp_role;
     431           0 :                         req->ifbr_stpflags = bp->bp_flags;
     432           0 :                         req->ifbr_fwd_trans = bp->bp_forward_transitions;
     433           0 :                         req->ifbr_desg_bridge = bp->bp_desg_pv.pv_dbridge_id;
     434           0 :                         req->ifbr_desg_port = bp->bp_desg_pv.pv_dport_id;
     435           0 :                         req->ifbr_root_bridge = bp->bp_desg_pv.pv_root_id;
     436           0 :                         req->ifbr_root_cost = bp->bp_desg_pv.pv_cost;
     437           0 :                         req->ifbr_root_port = bp->bp_desg_pv.pv_port_id;
     438             : 
     439             :                         /* Copy STP state options as flags */
     440           0 :                         if (bp->bp_operedge)
     441           0 :                                 req->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
     442           0 :                         if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
     443           0 :                                 req->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
     444           0 :                         if (bp->bp_ptp_link)
     445           0 :                                 req->ifbr_ifsflags |= IFBIF_BSTP_PTP;
     446           0 :                         if (bp->bp_flags & BSTP_PORT_AUTOPTP)
     447           0 :                                 req->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
     448             :                 }
     449             :                 break;
     450             :         case SIOCBRDGSIFFLGS:
     451           0 :                 if ((error = suser(curproc)) != 0)
     452             :                         break;
     453           0 :                 ifs = ifunit(req->ifbr_ifsname);
     454           0 :                 if (ifs == NULL) {
     455             :                         error = ENOENT;
     456           0 :                         break;
     457             :                 }
     458           0 :                 p = (struct bridge_iflist *)ifs->if_bridgeport;
     459           0 :                 if (p == NULL || p->bridge_sc != sc) {
     460             :                         error = ESRCH;
     461           0 :                         break;
     462             :                 }
     463           0 :                 if (req->ifbr_ifsflags & IFBIF_RO_MASK) {
     464             :                         error = EINVAL;
     465           0 :                         break;
     466             :                 }
     467           0 :                 if (req->ifbr_ifsflags & IFBIF_STP) {
     468           0 :                         if ((p->bif_flags & IFBIF_STP) == 0) {
     469             :                                 /* Enable STP */
     470           0 :                                 if ((p->bif_stp = bstp_add(sc->sc_stp,
     471           0 :                                     p->ifp)) == NULL) {
     472             :                                         error = ENOMEM;
     473           0 :                                         break;
     474             :                                 }
     475             :                         } else {
     476             :                                 /* Update STP flags */
     477           0 :                                 bstp_ifsflags(p->bif_stp, req->ifbr_ifsflags);
     478             :                         }
     479           0 :                 } else if (p->bif_flags & IFBIF_STP) {
     480           0 :                         bstp_delete(p->bif_stp);
     481           0 :                         p->bif_stp = NULL;
     482           0 :                 }
     483           0 :                 p->bif_flags = req->ifbr_ifsflags;
     484           0 :                 break;
     485             :         case SIOCSIFFLAGS:
     486           0 :                 if ((ifp->if_flags & IFF_UP) == IFF_UP)
     487           0 :                         bridge_init(sc);
     488             : 
     489           0 :                 if ((ifp->if_flags & IFF_UP) == 0)
     490           0 :                         bridge_stop(sc);
     491             : 
     492             :                 break;
     493             :         case SIOCBRDGGPARAM:
     494           0 :                 if ((bp = bs->bs_root_port) == NULL)
     495           0 :                         brop->ifbop_root_port = 0;
     496             :                 else
     497           0 :                         brop->ifbop_root_port = bp->bp_ifp->if_index;
     498           0 :                 brop->ifbop_maxage = bs->bs_bridge_max_age >> 8;
     499           0 :                 brop->ifbop_hellotime = bs->bs_bridge_htime >> 8;
     500           0 :                 brop->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8;
     501           0 :                 brop->ifbop_holdcount = bs->bs_txholdcount;
     502           0 :                 brop->ifbop_priority = bs->bs_bridge_priority;
     503           0 :                 brop->ifbop_protocol = bs->bs_protover;
     504           0 :                 brop->ifbop_root_bridge = bs->bs_root_pv.pv_root_id;
     505           0 :                 brop->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
     506           0 :                 brop->ifbop_root_port = bs->bs_root_pv.pv_port_id;
     507           0 :                 brop->ifbop_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
     508           0 :                 brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
     509           0 :                 brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
     510           0 :                 break;
     511             :         case SIOCBRDGSIFPROT:
     512           0 :                 ifs = ifunit(req->ifbr_ifsname);
     513           0 :                 if (ifs == NULL) {
     514             :                         error = ENOENT;
     515           0 :                         break;
     516             :                 }
     517           0 :                 p = (struct bridge_iflist *)ifs->if_bridgeport;
     518           0 :                 if (p == NULL || p->bridge_sc != sc) {
     519             :                         error = ESRCH;
     520           0 :                         break;
     521             :                 }
     522           0 :                 p->bif_protected = req->ifbr_protected;
     523           0 :                 break;
     524             :         case SIOCBRDGRTS:
     525             :         case SIOCBRDGGCACHE:
     526             :         case SIOCBRDGGPRI:
     527             :         case SIOCBRDGGMA:
     528             :         case SIOCBRDGGHT:
     529             :         case SIOCBRDGGFD:
     530             :         case SIOCBRDGGTO:
     531             :         case SIOCBRDGGRL:
     532             :                 break;
     533             :         case SIOCBRDGFLUSH:
     534             :         case SIOCBRDGSADDR:
     535             :         case SIOCBRDGDADDR:
     536             :         case SIOCBRDGSCACHE:
     537             :         case SIOCBRDGSTO:
     538             :         case SIOCBRDGARL:
     539             :         case SIOCBRDGFRL:
     540             :         case SIOCBRDGSPRI:
     541             :         case SIOCBRDGSFD:
     542             :         case SIOCBRDGSMA:
     543             :         case SIOCBRDGSHT:
     544             :         case SIOCBRDGSTXHC:
     545             :         case SIOCBRDGSPROTO:
     546             :         case SIOCBRDGSIFPRIO:
     547             :         case SIOCBRDGSIFCOST:
     548           0 :                 error = suser(curproc);
     549           0 :                 break;
     550             :         default:
     551             :                 error = ENOTTY;
     552           0 :                 break;
     553             :         }
     554             : 
     555           0 :         if (!error)
     556           0 :                 error = bridgectl_ioctl(ifp, cmd, data);
     557             : 
     558           0 :         if (!error)
     559           0 :                 error = bstp_ioctl(ifp, cmd, data);
     560             : 
     561           0 :         return (error);
     562             : }
     563             : 
     564             : /* Detach an interface from a bridge.  */
     565             : void
     566           0 : bridge_ifdetach(void *arg)
     567             : {
     568           0 :         struct ifnet *ifp = (struct ifnet *)arg;
     569             :         struct bridge_softc *sc;
     570             :         struct bridge_iflist *bif;
     571             : 
     572           0 :         bif = (struct bridge_iflist *)ifp->if_bridgeport;
     573           0 :         sc = bif->bridge_sc;
     574             : 
     575           0 :         bridge_delete(sc, bif);
     576           0 : }
     577             : 
     578             : void
     579           0 : bridge_spandetach(void *arg)
     580             : {
     581           0 :         struct bridge_iflist *p = (struct bridge_iflist *)arg;
     582           0 :         struct bridge_softc *sc = p->bridge_sc;
     583             : 
     584           0 :         hook_disestablish(p->ifp->if_detachhooks, p->bif_dhcookie);
     585           0 :         TAILQ_REMOVE(&sc->sc_spanlist, p, next);
     586           0 :         free(p, M_DEVBUF, sizeof(*p));
     587           0 : }
     588             : 
     589             : int
     590           0 : bridge_bifconf(struct bridge_softc *sc, struct ifbifconf *bifc)
     591             : {
     592             :         struct bridge_iflist *p;
     593             :         struct bstp_port *bp;
     594           0 :         struct bstp_state *bs = sc->sc_stp;
     595             :         u_int32_t total = 0, i = 0;
     596             :         int error = 0;
     597             :         struct ifbreq *breq = NULL;
     598             : 
     599           0 :         TAILQ_FOREACH(p, &sc->sc_iflist, next)
     600           0 :                 total++;
     601             : 
     602           0 :         TAILQ_FOREACH(p, &sc->sc_spanlist, next)
     603           0 :                 total++;
     604             : 
     605           0 :         if (bifc->ifbic_len == 0) {
     606             :                 i = total;
     607           0 :                 goto done;
     608             :         }
     609             : 
     610           0 :         if ((breq = (struct ifbreq *)
     611           0 :             malloc(sizeof(*breq), M_DEVBUF, M_NOWAIT)) == NULL)
     612             :                 goto done;
     613             : 
     614           0 :         TAILQ_FOREACH(p, &sc->sc_iflist, next) {
     615           0 :                 bzero(breq, sizeof(*breq));
     616           0 :                 if (bifc->ifbic_len < sizeof(*breq))
     617             :                         break;
     618           0 :                 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
     619           0 :                 strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
     620           0 :                 breq->ifbr_ifsflags = p->bif_flags;
     621           0 :                 breq->ifbr_portno = p->ifp->if_index & 0xfff;
     622           0 :                 breq->ifbr_protected = p->bif_protected;
     623           0 :                 if (p->bif_flags & IFBIF_STP) {
     624           0 :                         bp = p->bif_stp;
     625           0 :                         breq->ifbr_state = bstp_getstate(sc->sc_stp, bp);
     626           0 :                         breq->ifbr_priority = bp->bp_priority;
     627           0 :                         breq->ifbr_path_cost = bp->bp_path_cost;
     628           0 :                         breq->ifbr_proto = bp->bp_protover;
     629           0 :                         breq->ifbr_role = bp->bp_role;
     630           0 :                         breq->ifbr_stpflags = bp->bp_flags;
     631           0 :                         breq->ifbr_fwd_trans = bp->bp_forward_transitions;
     632           0 :                         breq->ifbr_root_bridge = bs->bs_root_pv.pv_root_id;
     633           0 :                         breq->ifbr_root_cost = bs->bs_root_pv.pv_cost;
     634           0 :                         breq->ifbr_root_port = bs->bs_root_pv.pv_port_id;
     635           0 :                         breq->ifbr_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
     636           0 :                         breq->ifbr_desg_port = bs->bs_root_pv.pv_dport_id;
     637             : 
     638             :                         /* Copy STP state options as flags */
     639           0 :                         if (bp->bp_operedge)
     640           0 :                                 breq->ifbr_ifsflags |= IFBIF_BSTP_EDGE;
     641           0 :                         if (bp->bp_flags & BSTP_PORT_AUTOEDGE)
     642           0 :                                 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOEDGE;
     643           0 :                         if (bp->bp_ptp_link)
     644           0 :                                 breq->ifbr_ifsflags |= IFBIF_BSTP_PTP;
     645           0 :                         if (bp->bp_flags & BSTP_PORT_AUTOPTP)
     646           0 :                                 breq->ifbr_ifsflags |= IFBIF_BSTP_AUTOPTP;
     647             :                 }
     648           0 :                 error = copyout((caddr_t)breq,
     649           0 :                     (caddr_t)(bifc->ifbic_req + i), sizeof(*breq));
     650           0 :                 if (error)
     651             :                         goto done;
     652           0 :                 i++;
     653           0 :                 bifc->ifbic_len -= sizeof(*breq);
     654             :         }
     655           0 :         TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
     656           0 :                 bzero(breq, sizeof(*breq));
     657           0 :                 if (bifc->ifbic_len < sizeof(*breq))
     658             :                         break;
     659           0 :                 strlcpy(breq->ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
     660           0 :                 strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
     661           0 :                 breq->ifbr_ifsflags = p->bif_flags | IFBIF_SPAN;
     662           0 :                 breq->ifbr_portno = p->ifp->if_index & 0xfff;
     663           0 :                 error = copyout((caddr_t)breq,
     664           0 :                     (caddr_t)(bifc->ifbic_req + i), sizeof(*breq));
     665           0 :                 if (error)
     666             :                         goto done;
     667           0 :                 i++;
     668           0 :                 bifc->ifbic_len -= sizeof(*breq);
     669             :         }
     670             : 
     671             : done:
     672           0 :         if (breq != NULL)
     673           0 :                 free(breq, M_DEVBUF, sizeof *breq);
     674           0 :         bifc->ifbic_len = i * sizeof(*breq);
     675           0 :         return (error);
     676             : }
     677             : 
     678             : void
     679           0 : bridge_init(struct bridge_softc *sc)
     680             : {
     681           0 :         struct ifnet *ifp = &sc->sc_if;
     682             : 
     683           0 :         if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING)
     684           0 :                 return;
     685             : 
     686           0 :         ifp->if_flags |= IFF_RUNNING;
     687           0 :         bstp_initialization(sc->sc_stp);
     688             : 
     689           0 :         if (sc->sc_brttimeout != 0)
     690           0 :                 timeout_add_sec(&sc->sc_brtimeout, sc->sc_brttimeout);
     691           0 : }
     692             : 
     693             : /*
     694             :  * Stop the bridge and deallocate the routing table.
     695             :  */
     696             : void
     697           0 : bridge_stop(struct bridge_softc *sc)
     698             : {
     699           0 :         struct ifnet *ifp = &sc->sc_if;
     700             : 
     701             :         /*
     702             :          * If we're not running, there's nothing to do.
     703             :          */
     704           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0)
     705           0 :                 return;
     706             : 
     707           0 :         timeout_del(&sc->sc_brtimeout);
     708             : 
     709           0 :         bridge_rtflush(sc, IFBF_FLUSHDYN);
     710             : 
     711           0 :         ifp->if_flags &= ~IFF_RUNNING;
     712           0 : }
     713             : 
     714             : /*
     715             :  * Send output from the bridge.  The mbuf has the ethernet header
     716             :  * already attached.  We must enqueue or free the mbuf before exiting.
     717             :  */
     718             : int
     719           0 : bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
     720             :     struct rtentry *rt)
     721             : {
     722             :         struct ether_header *eh;
     723             :         struct ifnet *dst_if = NULL;
     724             :         struct bridge_rtnode *dst_p = NULL;
     725             :         struct ether_addr *dst;
     726             :         struct bridge_softc *sc;
     727             :         struct bridge_tunneltag *brtag;
     728             :         struct bridge_iflist *ifl;
     729             :         int error;
     730             : 
     731             :         /* ifp must be a member interface of the bridge. */
     732           0 :         if (ifp->if_bridgeport == NULL) {
     733           0 :                 m_freem(m);
     734           0 :                 return (EINVAL);
     735             :         }
     736           0 :         sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc;
     737             : 
     738           0 :         if (m->m_len < sizeof(*eh)) {
     739           0 :                 m = m_pullup(m, sizeof(*eh));
     740           0 :                 if (m == NULL)
     741           0 :                         return (ENOBUFS);
     742             :         }
     743           0 :         eh = mtod(m, struct ether_header *);
     744           0 :         dst = (struct ether_addr *)&eh->ether_dhost[0];
     745             : 
     746             :         /*
     747             :          * If bridge is down, but original output interface is up,
     748             :          * go ahead and send out that interface.  Otherwise the packet
     749             :          * is dropped below.
     750             :          */
     751           0 :         if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) {
     752             :                 dst_if = ifp;
     753           0 :                 goto sendunicast;
     754             :         }
     755             : 
     756             : #if NBPFILTER > 0
     757           0 :         if (sc->sc_if.if_bpf)
     758           0 :                 bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT);
     759             : #endif
     760           0 :         ifp->if_opackets++;
     761           0 :         ifp->if_obytes += m->m_pkthdr.len;
     762             : 
     763             :         /*
     764             :          * If the packet is a broadcast or we don't know a better way to
     765             :          * get there, send to all interfaces.
     766             :          */
     767           0 :         if ((dst_p = bridge_rtlookup(sc, dst)) != NULL)
     768           0 :                 dst_if = dst_p->brt_if;
     769           0 :         if (dst_if == NULL || ETHER_IS_MULTICAST(eh->ether_dhost)) {
     770             :                 struct bridge_iflist *p;
     771             :                 struct mbuf *mc;
     772             :                 int used = 0;
     773             : 
     774           0 :                 bridge_span(sc, m);
     775             : 
     776           0 :                 TAILQ_FOREACH(p, &sc->sc_iflist, next) {
     777           0 :                         dst_if = p->ifp;
     778           0 :                         if ((dst_if->if_flags & IFF_RUNNING) == 0)
     779             :                                 continue;
     780             : 
     781             :                         /*
     782             :                          * If this is not the original output interface,
     783             :                          * and the interface is participating in spanning
     784             :                          * tree, make sure the port is in a state that
     785             :                          * allows forwarding.
     786             :                          */
     787           0 :                         if (dst_if != ifp &&
     788           0 :                             (p->bif_flags & IFBIF_STP) &&
     789           0 :                             (p->bif_state == BSTP_IFSTATE_DISCARDING))
     790             :                                 continue;
     791             : #if NMPW > 0
     792             :                         /*
     793             :                          * Split horizon: avoid broadcasting messages from
     794             :                          * wire to another wire.
     795             :                          */
     796           0 :                         if (ifp->if_type == IFT_MPLSTUNNEL &&
     797           0 :                             dst_if->if_type == IFT_MPLSTUNNEL)
     798             :                                 continue;
     799             : #endif /* NMPW */
     800           0 :                         if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
     801           0 :                             (m->m_flags & (M_BCAST | M_MCAST)) == 0)
     802             :                                 continue;
     803             : 
     804           0 :                         if (TAILQ_NEXT(p, next) == NULL) {
     805             :                                 used = 1;
     806             :                                 mc = m;
     807           0 :                         } else {
     808           0 :                                 mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
     809           0 :                                 if (mc == NULL) {
     810           0 :                                         sc->sc_if.if_oerrors++;
     811           0 :                                         continue;
     812             :                                 }
     813             :                         }
     814             : 
     815           0 :                         ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
     816           0 :                         KASSERT(ifl != NULL);
     817           0 :                         if (bridge_filterrule(&ifl->bif_brlout, eh, mc) ==
     818             :                             BRL_ACTION_BLOCK)
     819             :                                 continue;
     820             : 
     821           0 :                         error = bridge_ifenqueue(sc, dst_if, mc);
     822             :                         if (error)
     823           0 :                                 continue;
     824             :                 }
     825           0 :                 if (!used)
     826           0 :                         m_freem(m);
     827             :                 return (0);
     828             :         }
     829             : 
     830             : sendunicast:
     831           0 :         if ((dst_p != NULL) &&
     832           0 :             (dst_p->brt_tunnel.brtag_peer.sa.sa_family != AF_UNSPEC) &&
     833           0 :             ((brtag = bridge_tunneltag(m)) != NULL))
     834           0 :                 bridge_copytag(&dst_p->brt_tunnel, brtag);
     835             : 
     836           0 :         bridge_span(sc, m);
     837           0 :         if ((dst_if->if_flags & IFF_RUNNING) == 0) {
     838           0 :                 m_freem(m);
     839           0 :                 return (ENETDOWN);
     840             :         }
     841           0 :         bridge_ifenqueue(sc, dst_if, m);
     842           0 :         return (0);
     843           0 : }
     844             : 
     845             : /*
     846             :  * Loop through each bridge interface and process their input queues.
     847             :  */
     848             : void
     849           0 : bridgeintr(void)
     850             : {
     851           0 :         struct mbuf_list ml;
     852             :         struct mbuf *m;
     853             :         struct ifnet *ifp;
     854             : 
     855           0 :         niq_delist(&bridgeintrq, &ml);
     856           0 :         if (ml_empty(&ml))
     857           0 :                 return;
     858             : 
     859           0 :         while ((m = ml_dequeue(&ml)) != NULL) {
     860             : 
     861           0 :                 ifp = if_get(m->m_pkthdr.ph_ifidx);
     862           0 :                 if (ifp == NULL) {
     863           0 :                         m_freem(m);
     864           0 :                         continue;
     865             :                 }
     866             : 
     867           0 :                 bridge_process(ifp, m);
     868             : 
     869           0 :                 if_put(ifp);
     870             :         }
     871           0 : }
     872             : 
     873             : /*
     874             :  * Process a single frame.  Frame must be freed or queued before returning.
     875             :  */
     876             : void
     877           0 : bridgeintr_frame(struct bridge_softc *sc, struct ifnet *src_if, struct mbuf *m)
     878             : {
     879             :         struct ifnet *dst_if;
     880             :         struct bridge_iflist *ifl;
     881             :         struct bridge_rtnode *dst_p;
     882             :         struct ether_addr *dst, *src;
     883           0 :         struct ether_header eh;
     884             :         u_int32_t protected;
     885             :         int len;
     886             : 
     887             : 
     888           0 :         sc->sc_if.if_ipackets++;
     889           0 :         sc->sc_if.if_ibytes += m->m_pkthdr.len;
     890             : 
     891           0 :         ifl = (struct bridge_iflist *)src_if->if_bridgeport;
     892           0 :         KASSERT(ifl != NULL);
     893             : 
     894           0 :         if (m->m_pkthdr.len < sizeof(eh)) {
     895           0 :                 m_freem(m);
     896           0 :                 return;
     897             :         }
     898           0 :         m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&eh);
     899           0 :         dst = (struct ether_addr *)&eh.ether_dhost[0];
     900           0 :         src = (struct ether_addr *)&eh.ether_shost[0];
     901             : 
     902             :         /*
     903             :          * If interface is learning, and if source address
     904             :          * is not broadcast or multicast, record its address.
     905             :          */
     906           0 :         if ((ifl->bif_flags & IFBIF_LEARNING) &&
     907           0 :             (eh.ether_shost[0] & 1) == 0 &&
     908           0 :             !(eh.ether_shost[0] == 0 && eh.ether_shost[1] == 0 &&
     909           0 :             eh.ether_shost[2] == 0 && eh.ether_shost[3] == 0 &&
     910           0 :             eh.ether_shost[4] == 0 && eh.ether_shost[5] == 0))
     911           0 :                 bridge_rtupdate(sc, src, src_if, 0, IFBAF_DYNAMIC, m);
     912             : 
     913           0 :         if ((ifl->bif_flags & IFBIF_STP) &&
     914           0 :             (ifl->bif_state == BSTP_IFSTATE_LEARNING)) {
     915           0 :                 m_freem(m);
     916           0 :                 return;
     917             :         }
     918             : 
     919             :         /*
     920             :          * At this point, the port either doesn't participate in stp or
     921             :          * it's in the forwarding state
     922             :          */
     923             : 
     924             :         /*
     925             :          * If packet is unicast, destined for someone on "this"
     926             :          * side of the bridge, drop it.
     927             :          */
     928           0 :         if (!ETHER_IS_MULTICAST(eh.ether_dhost)) {
     929           0 :                 if ((dst_p = bridge_rtlookup(sc, dst)) != NULL)
     930           0 :                         dst_if = dst_p->brt_if;
     931             :                 else
     932             :                         dst_if = NULL;
     933           0 :                 if (dst_if == src_if) {
     934           0 :                         m_freem(m);
     935           0 :                         return;
     936             :                 }
     937             :         } else {
     938           0 :                 if (memcmp(etherbroadcastaddr, eh.ether_dhost,
     939           0 :                     sizeof(etherbroadcastaddr)) == 0)
     940           0 :                         m->m_flags |= M_BCAST;
     941             :                 else
     942           0 :                         m->m_flags |= M_MCAST;
     943             :                 dst_if = NULL;
     944             :         }
     945             : 
     946             :         /*
     947             :          * Multicast packets get handled a little differently:
     948             :          * If interface is:
     949             :          *      -link0,-link1   (default) Forward all multicast
     950             :          *                      as broadcast.
     951             :          *      -link0,link1    Drop non-IP multicast, forward
     952             :          *                      as broadcast IP multicast.
     953             :          *      link0,-link1    Drop IP multicast, forward as
     954             :          *                      broadcast non-IP multicast.
     955             :          *      link0,link1     Drop all multicast.
     956             :          */
     957           0 :         if (m->m_flags & M_MCAST) {
     958           0 :                 if ((sc->sc_if.if_flags &
     959           0 :                     (IFF_LINK0 | IFF_LINK1)) ==
     960             :                     (IFF_LINK0 | IFF_LINK1)) {
     961           0 :                         m_freem(m);
     962           0 :                         return;
     963             :                 }
     964           0 :                 if (sc->sc_if.if_flags & IFF_LINK0 &&
     965           0 :                     ETHERADDR_IS_IP_MCAST(dst)) {
     966           0 :                         m_freem(m);
     967           0 :                         return;
     968             :                 }
     969           0 :                 if (sc->sc_if.if_flags & IFF_LINK1 &&
     970           0 :                     !ETHERADDR_IS_IP_MCAST(dst)) {
     971           0 :                         m_freem(m);
     972           0 :                         return;
     973             :                 }
     974             :         }
     975             : 
     976           0 :         if (ifl->bif_flags & IFBIF_BLOCKNONIP && bridge_blocknonip(&eh, m)) {
     977           0 :                 m_freem(m);
     978           0 :                 return;
     979             :         }
     980             : 
     981           0 :         if (bridge_filterrule(&ifl->bif_brlin, &eh, m) == BRL_ACTION_BLOCK) {
     982           0 :                 m_freem(m);
     983           0 :                 return;
     984             :         }
     985           0 :         m = bridge_ip(sc, BRIDGE_IN, src_if, &eh, m);
     986           0 :         if (m == NULL)
     987           0 :                 return;
     988             :         /*
     989             :          * If the packet is a multicast or broadcast OR if we don't
     990             :          * know any better, forward it to all interfaces.
     991             :          */
     992           0 :         if ((m->m_flags & (M_BCAST | M_MCAST)) || dst_if == NULL) {
     993           0 :                 sc->sc_if.if_imcasts++;
     994           0 :                 bridge_broadcast(sc, src_if, &eh, m);
     995           0 :                 return;
     996             :         }
     997           0 :         protected = ifl->bif_protected;
     998             : 
     999             :         /*
    1000             :          * At this point, we're dealing with a unicast frame going to a
    1001             :          * different interface
    1002             :          */
    1003           0 :         if ((dst_if->if_flags & IFF_RUNNING) == 0) {
    1004           0 :                 m_freem(m);
    1005           0 :                 return;
    1006             :         }
    1007           0 :         ifl = (struct bridge_iflist *)dst_if->if_bridgeport;
    1008           0 :         if ((ifl->bif_flags & IFBIF_STP) &&
    1009           0 :             (ifl->bif_state == BSTP_IFSTATE_DISCARDING)) {
    1010           0 :                 m_freem(m);
    1011           0 :                 return;
    1012             :         }
    1013             :         /*
    1014             :          * Do not transmit if both ports are part of the same protected
    1015             :          * domain.
    1016             :          */
    1017           0 :         if (protected != 0 && (protected & ifl->bif_protected)) {
    1018           0 :                 m_freem(m);
    1019           0 :                 return;
    1020             :         }
    1021           0 :         if (bridge_filterrule(&ifl->bif_brlout, &eh, m) == BRL_ACTION_BLOCK) {
    1022           0 :                 m_freem(m);
    1023           0 :                 return;
    1024             :         }
    1025           0 :         m = bridge_ip(sc, BRIDGE_OUT, dst_if, &eh, m);
    1026           0 :         if (m == NULL)
    1027           0 :                 return;
    1028             : 
    1029           0 :         len = m->m_pkthdr.len;
    1030             : #if NVLAN > 0
    1031           0 :         if ((m->m_flags & M_VLANTAG) &&
    1032           0 :             (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
    1033           0 :                 len += ETHER_VLAN_ENCAP_LEN;
    1034             : #endif
    1035           0 :         if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
    1036           0 :                 bridge_fragment(sc, dst_if, &eh, m);
    1037             :         else {
    1038           0 :                 bridge_ifenqueue(sc, dst_if, m);
    1039             :         }
    1040           0 : }
    1041             : 
    1042             : /*
    1043             :  * Return 1 if `ena' belongs to `ifl', 0 otherwise.
    1044             :  */
    1045             : int
    1046           0 : bridge_ourether(struct bridge_iflist *ifl, uint8_t *ena)
    1047             : {
    1048           0 :         struct arpcom *ac = (struct arpcom *)ifl->ifp;
    1049             : 
    1050           0 :         if (memcmp(ac->ac_enaddr, ena, ETHER_ADDR_LEN) == 0)
    1051           0 :                 return (1);
    1052             : 
    1053             : #if NCARP > 0
    1054           0 :         if (carp_ourether(ifl->ifp, ena))
    1055           0 :                 return (1);
    1056             : #endif
    1057             : 
    1058           0 :         return (0);
    1059           0 : }
    1060             : 
    1061             : /*
    1062             :  * Receive input from an interface.  Queue the packet for bridging if its
    1063             :  * not for us, and schedule an interrupt.
    1064             :  */
    1065             : int
    1066           0 : bridge_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
    1067             : {
    1068           0 :         KASSERT(m->m_flags & M_PKTHDR);
    1069             : 
    1070           0 :         if (m->m_flags & M_PROTO1) {
    1071           0 :                 m->m_flags &= ~M_PROTO1;
    1072           0 :                 return (0);
    1073             :         }
    1074             : 
    1075           0 :         niq_enqueue(&bridgeintrq, m);
    1076             : 
    1077           0 :         return (1);
    1078           0 : }
    1079             : 
    1080             : void
    1081           0 : bridge_process(struct ifnet *ifp, struct mbuf *m)
    1082             : {
    1083             :         struct bridge_softc *sc;
    1084             :         struct bridge_iflist *ifl;
    1085             :         struct bridge_iflist *srcifl;
    1086             :         struct ether_header *eh;
    1087             :         struct mbuf *mc;
    1088             : 
    1089           0 :         ifl = (struct bridge_iflist *)ifp->if_bridgeport;
    1090           0 :         if (ifl == NULL)
    1091             :                 goto reenqueue;
    1092             : 
    1093           0 :         sc = ifl->bridge_sc;
    1094           0 :         if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
    1095             :                 goto reenqueue;
    1096             : 
    1097             : #if NVLAN > 0
    1098             :         /*
    1099             :          * If the underlying interface removed the VLAN header itself,
    1100             :          * add it back.
    1101             :          */
    1102           0 :         if (ISSET(m->m_flags, M_VLANTAG)) {
    1103           0 :                 m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag);
    1104           0 :                 if (m == NULL)
    1105           0 :                         return;
    1106             :         }
    1107             : #endif
    1108             : 
    1109             : #if NBPFILTER > 0
    1110           0 :         if (sc->sc_if.if_bpf)
    1111           0 :                 bpf_mtap_ether(sc->sc_if.if_bpf, m, BPF_DIRECTION_IN);
    1112             : #endif
    1113             : 
    1114           0 :         bridge_span(sc, m);
    1115             : 
    1116           0 :         eh = mtod(m, struct ether_header *);
    1117           0 :         if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
    1118             :                 /*
    1119             :                  * Reserved destination MAC addresses (01:80:C2:00:00:0x)
    1120             :                  * should not be forwarded to bridge members according to
    1121             :                  * section 7.12.6 of the 802.1D-2004 specification.  The
    1122             :                  * STP destination address (as stored in bstp_etheraddr)
    1123             :                  * is the first of these.
    1124             :                  */
    1125           0 :                 if (memcmp(eh->ether_dhost, bstp_etheraddr,
    1126           0 :                     ETHER_ADDR_LEN - 1) == 0) {
    1127           0 :                         if (eh->ether_dhost[ETHER_ADDR_LEN - 1] == 0) {
    1128             :                                 /* STP traffic */
    1129           0 :                                 if ((m = bstp_input(sc->sc_stp, ifl->bif_stp,
    1130           0 :                                     eh, m)) == NULL)
    1131           0 :                                         return;
    1132           0 :                         } else if (eh->ether_dhost[ETHER_ADDR_LEN - 1] <= 0xf) {
    1133           0 :                                 m_freem(m);
    1134           0 :                                 return;
    1135             :                         }
    1136             :                 }
    1137             : 
    1138             :                 /*
    1139             :                  * No need to process frames for ifs in the discarding state
    1140             :                  */
    1141           0 :                 if ((ifl->bif_flags & IFBIF_STP) &&
    1142           0 :                     (ifl->bif_state == BSTP_IFSTATE_DISCARDING))
    1143             :                         goto reenqueue;
    1144             : 
    1145           0 :                 mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
    1146           0 :                 if (mc == NULL)
    1147             :                         goto reenqueue;
    1148             : 
    1149           0 :                 bridge_ifinput(ifp, mc);
    1150             : 
    1151           0 :                 bridgeintr_frame(sc, ifp, m);
    1152           0 :                 return;
    1153             :         }
    1154             : 
    1155             :         /*
    1156             :          * No need to queue frames for ifs in the discarding state
    1157             :          */
    1158           0 :         if ((ifl->bif_flags & IFBIF_STP) &&
    1159           0 :             (ifl->bif_state == BSTP_IFSTATE_DISCARDING))
    1160             :                 goto reenqueue;
    1161             : 
    1162             :         /*
    1163             :          * Unicast, make sure it's not for us.
    1164             :          */
    1165             :         srcifl = ifl;
    1166           0 :         TAILQ_FOREACH(ifl, &sc->sc_iflist, next) {
    1167           0 :                 if (ifl->ifp->if_type != IFT_ETHER)
    1168             :                         continue;
    1169           0 :                 if (bridge_ourether(ifl, eh->ether_dhost)) {
    1170           0 :                         if (srcifl->bif_flags & IFBIF_LEARNING)
    1171           0 :                                 bridge_rtupdate(sc,
    1172           0 :                                     (struct ether_addr *)&eh->ether_shost,
    1173             :                                     ifp, 0, IFBAF_DYNAMIC, m);
    1174           0 :                         if (bridge_filterrule(&srcifl->bif_brlin, eh, m) ==
    1175             :                             BRL_ACTION_BLOCK) {
    1176           0 :                                 m_freem(m);
    1177           0 :                                 return;
    1178             :                         }
    1179             : 
    1180             :                         /* Count for the bridge */
    1181           0 :                         sc->sc_if.if_ipackets++;
    1182           0 :                         sc->sc_if.if_ibytes += m->m_pkthdr.len;
    1183             : 
    1184           0 :                         bridge_ifinput(ifl->ifp, m);
    1185           0 :                         return;
    1186             :                 }
    1187           0 :                 if (bridge_ourether(ifl, eh->ether_shost)) {
    1188           0 :                         m_freem(m);
    1189           0 :                         return;
    1190             :                 }
    1191             :         }
    1192             : 
    1193           0 :         bridgeintr_frame(sc, ifp, m);
    1194           0 :         return;
    1195             : 
    1196             : reenqueue:
    1197           0 :         bridge_ifinput(ifp, m);
    1198           0 : }
    1199             : 
    1200             : /*
    1201             :  * Send a frame to all interfaces that are members of the bridge
    1202             :  * (except the one it came in on).
    1203             :  */
    1204             : void
    1205           0 : bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
    1206             :     struct ether_header *eh, struct mbuf *m)
    1207             : {
    1208             :         struct bridge_iflist *p;
    1209             :         struct mbuf *mc;
    1210             :         struct ifnet *dst_if;
    1211             :         int len, used = 0;
    1212             :         u_int32_t protected;
    1213             : 
    1214           0 :         p = (struct bridge_iflist *)ifp->if_bridgeport;
    1215           0 :         protected = p->bif_protected;
    1216             : 
    1217           0 :         TAILQ_FOREACH(p, &sc->sc_iflist, next) {
    1218           0 :                 dst_if = p->ifp;
    1219             : 
    1220           0 :                 if ((dst_if->if_flags & IFF_RUNNING) == 0)
    1221             :                         continue;
    1222             : 
    1223           0 :                 if ((p->bif_flags & IFBIF_STP) &&
    1224           0 :                     (p->bif_state == BSTP_IFSTATE_DISCARDING))
    1225             :                         continue;
    1226             : 
    1227           0 :                 if ((p->bif_flags & IFBIF_DISCOVER) == 0 &&
    1228           0 :                     (m->m_flags & (M_BCAST | M_MCAST)) == 0)
    1229             :                         continue;
    1230             : 
    1231             :                 /* Drop non-IP frames if the appropriate flag is set. */
    1232           0 :                 if (p->bif_flags & IFBIF_BLOCKNONIP &&
    1233           0 :                     bridge_blocknonip(eh, m))
    1234             :                         continue;
    1235             : 
    1236             :                 /*
    1237             :                  * Do not transmit if both ports are part of the same
    1238             :                  * protected domain.
    1239             :                  */
    1240           0 :                 if (protected != 0 && (protected & p->bif_protected))
    1241             :                         continue;
    1242             : 
    1243           0 :                 if (bridge_filterrule(&p->bif_brlout, eh, m) == BRL_ACTION_BLOCK)
    1244             :                         continue;
    1245             : 
    1246             :                 /*
    1247             :                  * Don't retransmit out of the same interface where
    1248             :                  * the packet was received from.
    1249             :                  */
    1250           0 :                 if (dst_if->if_index == ifp->if_index)
    1251             :                         continue;
    1252             : 
    1253           0 :                 bridge_localbroadcast(sc, dst_if, eh, m);
    1254             : 
    1255             : #if NMPW > 0
    1256             :                 /*
    1257             :                  * Split horizon: avoid broadcasting messages from wire to
    1258             :                  * another wire.
    1259             :                  */
    1260           0 :                 if (ifp->if_type == IFT_MPLSTUNNEL &&
    1261           0 :                     dst_if->if_type == IFT_MPLSTUNNEL)
    1262             :                         continue;
    1263             : #endif /* NMPW */
    1264             : 
    1265             :                 /* If last one, reuse the passed-in mbuf */
    1266           0 :                 if (TAILQ_NEXT(p, next) == NULL) {
    1267             :                         mc = m;
    1268             :                         used = 1;
    1269           0 :                 } else {
    1270           0 :                         mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
    1271           0 :                         if (mc == NULL) {
    1272           0 :                                 sc->sc_if.if_oerrors++;
    1273           0 :                                 continue;
    1274             :                         }
    1275             :                 }
    1276             : 
    1277           0 :                 mc = bridge_ip(sc, BRIDGE_OUT, dst_if, eh, mc);
    1278           0 :                 if (mc == NULL)
    1279             :                         continue;
    1280             : 
    1281           0 :                 len = mc->m_pkthdr.len;
    1282             : #if NVLAN > 0
    1283           0 :                 if ((mc->m_flags & M_VLANTAG) &&
    1284           0 :                     (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
    1285           0 :                         len += ETHER_VLAN_ENCAP_LEN;
    1286             : #endif
    1287           0 :                 if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
    1288           0 :                         bridge_fragment(sc, dst_if, eh, mc);
    1289             :                 else {
    1290           0 :                         bridge_ifenqueue(sc, dst_if, mc);
    1291             :                 }
    1292             :         }
    1293             : 
    1294           0 :         if (!used)
    1295           0 :                 m_freem(m);
    1296           0 : }
    1297             : 
    1298             : void
    1299           0 : bridge_localbroadcast(struct bridge_softc *sc, struct ifnet *ifp,
    1300             :     struct ether_header *eh, struct mbuf *m)
    1301             : {
    1302             :         struct mbuf *m1;
    1303             :         u_int16_t etype;
    1304             : 
    1305             :         /*
    1306             :          * quick optimisation, don't send packets up the stack if no
    1307             :          * corresponding address has been specified.
    1308             :          */
    1309           0 :         etype = ntohs(eh->ether_type);
    1310           0 :         if (!(m->m_flags & M_VLANTAG) && etype == ETHERTYPE_IP) {
    1311             :                 struct ifaddr *ifa;
    1312           0 :                 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
    1313           0 :                         if (ifa->ifa_addr->sa_family == AF_INET)
    1314             :                                 break;
    1315             :                 }
    1316           0 :                 if (ifa == NULL)
    1317           0 :                         return;
    1318           0 :         }
    1319             : 
    1320           0 :         m1 = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
    1321           0 :         if (m1 == NULL) {
    1322           0 :                 sc->sc_if.if_oerrors++;
    1323           0 :                 return;
    1324             :         }
    1325             : 
    1326             : #if NPF > 0
    1327           0 :         pf_pkt_addr_changed(m1);
    1328             : #endif  /* NPF */
    1329             : 
    1330           0 :         bridge_ifinput(ifp, m1);
    1331           0 : }
    1332             : 
    1333             : void
    1334           0 : bridge_span(struct bridge_softc *sc, struct mbuf *m)
    1335             : {
    1336             :         struct bridge_iflist *p;
    1337             :         struct ifnet *ifp;
    1338             :         struct mbuf *mc;
    1339             :         int error;
    1340             : 
    1341           0 :         TAILQ_FOREACH(p, &sc->sc_spanlist, next) {
    1342           0 :                 ifp = p->ifp;
    1343             : 
    1344           0 :                 if ((ifp->if_flags & IFF_RUNNING) == 0)
    1345             :                         continue;
    1346             : 
    1347           0 :                 mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
    1348           0 :                 if (mc == NULL) {
    1349           0 :                         sc->sc_if.if_oerrors++;
    1350           0 :                         continue;
    1351             :                 }
    1352             : 
    1353           0 :                 error = bridge_ifenqueue(sc, ifp, mc);
    1354             :                 if (error)
    1355           0 :                         continue;
    1356             :         }
    1357           0 : }
    1358             : 
    1359             : /*
    1360             :  * Block non-ip frames:
    1361             :  * Returns 0 if frame is ip, and 1 if it should be dropped.
    1362             :  */
    1363             : int
    1364           0 : bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
    1365             : {
    1366           0 :         struct llc llc;
    1367             :         u_int16_t etype;
    1368             : 
    1369           0 :         if (m->m_pkthdr.len < ETHER_HDR_LEN)
    1370           0 :                 return (1);
    1371             : 
    1372             : #if NVLAN > 0
    1373           0 :         if (m->m_flags & M_VLANTAG)
    1374           0 :                 return (1);
    1375             : #endif
    1376             : 
    1377           0 :         etype = ntohs(eh->ether_type);
    1378           0 :         switch (etype) {
    1379             :         case ETHERTYPE_ARP:
    1380             :         case ETHERTYPE_REVARP:
    1381             :         case ETHERTYPE_IP:
    1382             :         case ETHERTYPE_IPV6:
    1383           0 :                 return (0);
    1384             :         }
    1385             : 
    1386           0 :         if (etype > ETHERMTU)
    1387           0 :                 return (1);
    1388             : 
    1389           0 :         if (m->m_pkthdr.len <
    1390             :             (ETHER_HDR_LEN + LLC_SNAPFRAMELEN))
    1391           0 :                 return (1);
    1392             : 
    1393           0 :         m_copydata(m, ETHER_HDR_LEN, LLC_SNAPFRAMELEN,
    1394             :             (caddr_t)&llc);
    1395             : 
    1396           0 :         etype = ntohs(llc.llc_snap.ether_type);
    1397           0 :         if (llc.llc_dsap == LLC_SNAP_LSAP &&
    1398           0 :             llc.llc_ssap == LLC_SNAP_LSAP &&
    1399           0 :             llc.llc_control == LLC_UI &&
    1400           0 :             llc.llc_snap.org_code[0] == 0 &&
    1401           0 :             llc.llc_snap.org_code[1] == 0 &&
    1402           0 :             llc.llc_snap.org_code[2] == 0 &&
    1403           0 :             (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
    1404           0 :             etype == ETHERTYPE_IP || etype == ETHERTYPE_IPV6)) {
    1405           0 :                 return (0);
    1406             :         }
    1407             : 
    1408           0 :         return (1);
    1409           0 : }
    1410             : 
    1411             : #ifdef IPSEC
    1412             : int
    1413           0 : bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
    1414             :     struct ether_header *eh, int hassnap, struct llc *llc,
    1415             :     int dir, int af, int hlen, struct mbuf *m)
    1416             : {
    1417           0 :         union sockaddr_union dst;
    1418             :         struct tdb *tdb;
    1419           0 :         u_int32_t spi;
    1420           0 :         u_int16_t cpi;
    1421           0 :         int error, off;
    1422             :         u_int8_t proto = 0;
    1423             :         struct ip *ip;
    1424             : #ifdef INET6
    1425             :         struct ip6_hdr *ip6;
    1426             : #endif /* INET6 */
    1427             : #if NPF > 0
    1428             :         struct ifnet *encif;
    1429             : #endif
    1430             : 
    1431           0 :         if (dir == BRIDGE_IN) {
    1432           0 :                 switch (af) {
    1433             :                 case AF_INET:
    1434           0 :                         if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
    1435             :                                 goto skiplookup;
    1436             : 
    1437           0 :                         ip = mtod(m, struct ip *);
    1438           0 :                         proto = ip->ip_p;
    1439             :                         off = offsetof(struct ip, ip_p);
    1440             : 
    1441           0 :                         if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
    1442           0 :                             proto != IPPROTO_IPCOMP)
    1443             :                                 goto skiplookup;
    1444             : 
    1445           0 :                         bzero(&dst, sizeof(union sockaddr_union));
    1446           0 :                         dst.sa.sa_family = AF_INET;
    1447           0 :                         dst.sin.sin_len = sizeof(struct sockaddr_in);
    1448           0 :                         m_copydata(m, offsetof(struct ip, ip_dst),
    1449             :                             sizeof(struct in_addr),
    1450           0 :                             (caddr_t)&dst.sin.sin_addr);
    1451             : 
    1452           0 :                         break;
    1453             : #ifdef INET6
    1454             :                 case AF_INET6:
    1455           0 :                         if (m->m_pkthdr.len - hlen < 2 * sizeof(u_int32_t))
    1456             :                                 goto skiplookup;
    1457             : 
    1458           0 :                         ip6 = mtod(m, struct ip6_hdr *);
    1459             : 
    1460             :                         /* XXX We should chase down the header chain */
    1461           0 :                         proto = ip6->ip6_nxt;
    1462             :                         off = offsetof(struct ip6_hdr, ip6_nxt);
    1463             : 
    1464           0 :                         if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
    1465           0 :                             proto != IPPROTO_IPCOMP)
    1466             :                                 goto skiplookup;
    1467             : 
    1468           0 :                         bzero(&dst, sizeof(union sockaddr_union));
    1469           0 :                         dst.sa.sa_family = AF_INET6;
    1470           0 :                         dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
    1471           0 :                         m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
    1472             :                             sizeof(struct in6_addr),
    1473           0 :                             (caddr_t)&dst.sin6.sin6_addr);
    1474             : 
    1475           0 :                         break;
    1476             : #endif /* INET6 */
    1477             :                 default:
    1478           0 :                         return (0);
    1479             :                 }
    1480             : 
    1481           0 :                 switch (proto) {
    1482             :                 case IPPROTO_ESP:
    1483           0 :                         m_copydata(m, hlen, sizeof(u_int32_t), (caddr_t)&spi);
    1484           0 :                         break;
    1485             :                 case IPPROTO_AH:
    1486           0 :                         m_copydata(m, hlen + sizeof(u_int32_t),
    1487             :                             sizeof(u_int32_t), (caddr_t)&spi);
    1488           0 :                         break;
    1489             :                 case IPPROTO_IPCOMP:
    1490           0 :                         m_copydata(m, hlen + sizeof(u_int16_t),
    1491             :                             sizeof(u_int16_t), (caddr_t)&cpi);
    1492           0 :                         spi = ntohl(htons(cpi));
    1493           0 :                         break;
    1494             :                 }
    1495             : 
    1496           0 :                 NET_ASSERT_LOCKED();
    1497             : 
    1498           0 :                 tdb = gettdb(ifp->if_rdomain, spi, &dst, proto);
    1499           0 :                 if (tdb != NULL && (tdb->tdb_flags & TDBF_INVALID) == 0 &&
    1500           0 :                     tdb->tdb_xform != NULL) {
    1501           0 :                         if (tdb->tdb_first_use == 0) {
    1502           0 :                                 tdb->tdb_first_use = time_second;
    1503           0 :                                 if (tdb->tdb_flags & TDBF_FIRSTUSE)
    1504           0 :                                         timeout_add_sec(&tdb->tdb_first_tmo,
    1505           0 :                                             tdb->tdb_exp_first_use);
    1506           0 :                                 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE)
    1507           0 :                                         timeout_add_sec(&tdb->tdb_sfirst_tmo,
    1508           0 :                                             tdb->tdb_soft_first_use);
    1509             :                         }
    1510             : 
    1511           0 :                         (*(tdb->tdb_xform->xf_input))(m, tdb, hlen, off);
    1512           0 :                         return (1);
    1513             :                 } else {
    1514             :  skiplookup:
    1515             :                         /* XXX do an input policy lookup */
    1516           0 :                         return (0);
    1517             :                 }
    1518             :         } else { /* Outgoing from the bridge. */
    1519           0 :                 tdb = ipsp_spd_lookup(m, af, hlen, &error,
    1520             :                     IPSP_DIRECTION_OUT, NULL, NULL, 0);
    1521           0 :                 if (tdb != NULL) {
    1522             :                         /*
    1523             :                          * We don't need to do loop detection, the
    1524             :                          * bridge will do that for us.
    1525             :                          */
    1526             : #if NPF > 0
    1527           0 :                         if ((encif = enc_getif(tdb->tdb_rdomain,
    1528           0 :                             tdb->tdb_tap)) == NULL ||
    1529           0 :                             pf_test(af, dir, encif, &m) != PF_PASS) {
    1530           0 :                                 m_freem(m);
    1531           0 :                                 return (1);
    1532             :                         }
    1533           0 :                         if (m == NULL)
    1534           0 :                                 return (1);
    1535           0 :                         else if (af == AF_INET)
    1536           0 :                                 in_proto_cksum_out(m, encif);
    1537             : #ifdef INET6
    1538           0 :                         else if (af == AF_INET6)
    1539           0 :                                 in6_proto_cksum_out(m, encif);
    1540             : #endif /* INET6 */
    1541             : #endif /* NPF */
    1542             : 
    1543           0 :                         ip = mtod(m, struct ip *);
    1544           0 :                         if ((af == AF_INET) &&
    1545           0 :                             ip_mtudisc && (ip->ip_off & htons(IP_DF)) &&
    1546           0 :                             tdb->tdb_mtu && ntohs(ip->ip_len) > tdb->tdb_mtu &&
    1547           0 :                             tdb->tdb_mtutimeout > time_second)
    1548           0 :                                 bridge_send_icmp_err(sc, ifp, eh, m,
    1549           0 :                                     hassnap, llc, tdb->tdb_mtu,
    1550             :                                     ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
    1551             :                         else
    1552           0 :                                 error = ipsp_process_packet(m, tdb, af, 0);
    1553           0 :                         return (1);
    1554             :                 } else
    1555           0 :                         return (0);
    1556             :         }
    1557             : 
    1558             :         return (0);
    1559           0 : }
    1560             : #endif /* IPSEC */
    1561             : 
    1562             : /*
    1563             :  * Filter IP packets by peeking into the ethernet frame.  This violates
    1564             :  * the ISO model, but allows us to act as a IP filter at the data link
    1565             :  * layer.  As a result, most of this code will look familiar to those
    1566             :  * who've read net/if_ethersubr.c and netinet/ip_input.c
    1567             :  */
    1568             : struct mbuf *
    1569           0 : bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
    1570             :     struct ether_header *eh, struct mbuf *m)
    1571             : {
    1572           0 :         struct llc llc;
    1573             :         int hassnap = 0;
    1574             :         struct ip *ip;
    1575             :         int hlen;
    1576             :         u_int16_t etype;
    1577             : 
    1578             : #if NVLAN > 0
    1579           0 :         if (m->m_flags & M_VLANTAG)
    1580           0 :                 return (m);
    1581             : #endif
    1582             : 
    1583           0 :         etype = ntohs(eh->ether_type);
    1584             : 
    1585           0 :         if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
    1586           0 :                 if (etype > ETHERMTU ||
    1587           0 :                     m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
    1588             :                     ETHER_HDR_LEN))
    1589           0 :                         return (m);
    1590             : 
    1591           0 :                 m_copydata(m, ETHER_HDR_LEN,
    1592             :                     LLC_SNAPFRAMELEN, (caddr_t)&llc);
    1593             : 
    1594           0 :                 if (llc.llc_dsap != LLC_SNAP_LSAP ||
    1595           0 :                     llc.llc_ssap != LLC_SNAP_LSAP ||
    1596           0 :                     llc.llc_control != LLC_UI ||
    1597           0 :                     llc.llc_snap.org_code[0] ||
    1598           0 :                     llc.llc_snap.org_code[1] ||
    1599           0 :                     llc.llc_snap.org_code[2])
    1600           0 :                         return (m);
    1601             : 
    1602           0 :                 etype = ntohs(llc.llc_snap.ether_type);
    1603           0 :                 if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
    1604           0 :                         return (m);
    1605             :                 hassnap = 1;
    1606           0 :         }
    1607             : 
    1608           0 :         m_adj(m, ETHER_HDR_LEN);
    1609           0 :         if (hassnap)
    1610           0 :                 m_adj(m, LLC_SNAPFRAMELEN);
    1611             : 
    1612           0 :         switch (etype) {
    1613             : 
    1614             :         case ETHERTYPE_IP:
    1615           0 :                 if (m->m_pkthdr.len < sizeof(struct ip))
    1616             :                         goto dropit;
    1617             : 
    1618             :                 /* Copy minimal header, and drop invalids */
    1619           0 :                 if (m->m_len < sizeof(struct ip) &&
    1620           0 :                     (m = m_pullup(m, sizeof(struct ip))) == NULL) {
    1621           0 :                         ipstat_inc(ips_toosmall);
    1622           0 :                         return (NULL);
    1623             :                 }
    1624           0 :                 ip = mtod(m, struct ip *);
    1625             : 
    1626           0 :                 if (ip->ip_v != IPVERSION) {
    1627           0 :                         ipstat_inc(ips_badvers);
    1628           0 :                         goto dropit;
    1629             :                 }
    1630             : 
    1631           0 :                 hlen = ip->ip_hl << 2; /* get whole header length */
    1632           0 :                 if (hlen < sizeof(struct ip)) {
    1633           0 :                         ipstat_inc(ips_badhlen);
    1634           0 :                         goto dropit;
    1635             :                 }
    1636             : 
    1637           0 :                 if (hlen > m->m_len) {
    1638           0 :                         if ((m = m_pullup(m, hlen)) == NULL) {
    1639           0 :                                 ipstat_inc(ips_badhlen);
    1640           0 :                                 return (NULL);
    1641             :                         }
    1642           0 :                         ip = mtod(m, struct ip *);
    1643           0 :                 }
    1644             : 
    1645           0 :                 if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
    1646           0 :                         if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
    1647           0 :                                 ipstat_inc(ips_badsum);
    1648           0 :                                 goto dropit;
    1649             :                         }
    1650             : 
    1651           0 :                         ipstat_inc(ips_inswcsum);
    1652           0 :                         if (in_cksum(m, hlen) != 0) {
    1653           0 :                                 ipstat_inc(ips_badsum);
    1654           0 :                                 goto dropit;
    1655             :                         }
    1656             :                 }
    1657             : 
    1658           0 :                 if (ntohs(ip->ip_len) < hlen)
    1659             :                         goto dropit;
    1660             : 
    1661           0 :                 if (m->m_pkthdr.len < ntohs(ip->ip_len))
    1662             :                         goto dropit;
    1663           0 :                 if (m->m_pkthdr.len > ntohs(ip->ip_len)) {
    1664           0 :                         if (m->m_len == m->m_pkthdr.len) {
    1665           0 :                                 m->m_len = ntohs(ip->ip_len);
    1666           0 :                                 m->m_pkthdr.len = ntohs(ip->ip_len);
    1667           0 :                         } else
    1668           0 :                                 m_adj(m, ntohs(ip->ip_len) - m->m_pkthdr.len);
    1669             :                 }
    1670             : 
    1671             : #ifdef IPSEC
    1672           0 :                 if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
    1673           0 :                     bridge_ipsec(sc, ifp, eh, hassnap, &llc,
    1674           0 :                     dir, AF_INET, hlen, m))
    1675           0 :                         return (NULL);
    1676             : #endif /* IPSEC */
    1677             : #if NPF > 0
    1678             :                 /* Finally, we get to filter the packet! */
    1679           0 :                 if (pf_test(AF_INET, dir, ifp, &m) != PF_PASS)
    1680             :                         goto dropit;
    1681           0 :                 if (m == NULL)
    1682             :                         goto dropit;
    1683             : #endif /* NPF > 0 */
    1684             : 
    1685             :                 /* Rebuild the IP header */
    1686           0 :                 if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
    1687           0 :                         return (NULL);
    1688           0 :                 if (m->m_len < sizeof(struct ip))
    1689             :                         goto dropit;
    1690           0 :                 in_proto_cksum_out(m, ifp);
    1691           0 :                 ip = mtod(m, struct ip *);
    1692           0 :                 ip->ip_sum = 0;
    1693             :                 if (0 && (ifp->if_capabilities & IFCAP_CSUM_IPv4))
    1694             :                         m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
    1695             :                 else {
    1696           0 :                         ipstat_inc(ips_outswcsum);
    1697           0 :                         ip->ip_sum = in_cksum(m, hlen);
    1698             :                 }
    1699             : 
    1700           0 :                 break;
    1701             : 
    1702             : #ifdef INET6
    1703             :         case ETHERTYPE_IPV6: {
    1704             :                 struct ip6_hdr *ip6;
    1705             : 
    1706           0 :                 if (m->m_len < sizeof(struct ip6_hdr)) {
    1707           0 :                         if ((m = m_pullup(m, sizeof(struct ip6_hdr)))
    1708           0 :                             == NULL) {
    1709           0 :                                 ip6stat_inc(ip6s_toosmall);
    1710           0 :                                 return (NULL);
    1711             :                         }
    1712             :                 }
    1713             : 
    1714           0 :                 ip6 = mtod(m, struct ip6_hdr *);
    1715             : 
    1716           0 :                 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
    1717           0 :                         ip6stat_inc(ip6s_badvers);
    1718           0 :                         goto dropit;
    1719             :                 }
    1720             : 
    1721             : #ifdef IPSEC
    1722             :                 hlen = sizeof(struct ip6_hdr);
    1723             : 
    1724           0 :                 if ((sc->sc_if.if_flags & IFF_LINK2) == IFF_LINK2 &&
    1725           0 :                     bridge_ipsec(sc, ifp, eh, hassnap, &llc,
    1726             :                     dir, AF_INET6, hlen, m))
    1727           0 :                         return (NULL);
    1728             : #endif /* IPSEC */
    1729             : 
    1730             : #if NPF > 0
    1731           0 :                 if (pf_test(AF_INET6, dir, ifp, &m) != PF_PASS)
    1732           0 :                         goto dropit;
    1733           0 :                 if (m == NULL)
    1734           0 :                         return (NULL);
    1735             : #endif /* NPF > 0 */
    1736           0 :                 in6_proto_cksum_out(m, ifp);
    1737             : 
    1738           0 :                 break;
    1739             :         }
    1740             : #endif /* INET6 */
    1741             : 
    1742             :         default:
    1743             :                 goto dropit;
    1744             :                 break;
    1745             :         }
    1746             : 
    1747             :         /* Reattach SNAP header */
    1748           0 :         if (hassnap) {
    1749           0 :                 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
    1750           0 :                 if (m == NULL)
    1751             :                         goto dropit;
    1752           0 :                 bcopy(&llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
    1753           0 :         }
    1754             : 
    1755             :         /* Reattach ethernet header */
    1756           0 :         M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
    1757           0 :         if (m == NULL)
    1758             :                 goto dropit;
    1759           0 :         bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
    1760             : 
    1761           0 :         return (m);
    1762             : 
    1763             : dropit:
    1764           0 :         m_freem(m);
    1765           0 :         return (NULL);
    1766           0 : }
    1767             : 
    1768             : void
    1769           0 : bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
    1770             :     struct ether_header *eh, struct mbuf *m)
    1771             : {
    1772           0 :         struct llc llc;
    1773             :         struct mbuf *m0;
    1774             :         int error = 0;
    1775             :         int hassnap = 0;
    1776             :         u_int16_t etype;
    1777             :         struct ip *ip;
    1778             : 
    1779           0 :         etype = ntohs(eh->ether_type);
    1780             : #if NVLAN > 0
    1781           0 :         if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN ||
    1782           0 :             etype == ETHERTYPE_QINQ) {
    1783           0 :                 int len = m->m_pkthdr.len;
    1784             : 
    1785           0 :                 if (m->m_flags & M_VLANTAG)
    1786           0 :                         len += ETHER_VLAN_ENCAP_LEN;
    1787           0 :                 if ((ifp->if_capabilities & IFCAP_VLAN_MTU) &&
    1788           0 :                     (len - sizeof(struct ether_vlan_header) <= ifp->if_mtu)) {
    1789           0 :                         bridge_ifenqueue(sc, ifp, m);
    1790           0 :                         return;
    1791             :                 }
    1792           0 :                 goto dropit;
    1793             :         }
    1794             : #endif
    1795           0 :         if (etype != ETHERTYPE_IP) {
    1796           0 :                 if (etype > ETHERMTU ||
    1797           0 :                     m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
    1798             :                     ETHER_HDR_LEN))
    1799             :                         goto dropit;
    1800             : 
    1801           0 :                 m_copydata(m, ETHER_HDR_LEN,
    1802             :                     LLC_SNAPFRAMELEN, (caddr_t)&llc);
    1803             : 
    1804           0 :                 if (llc.llc_dsap != LLC_SNAP_LSAP ||
    1805           0 :                     llc.llc_ssap != LLC_SNAP_LSAP ||
    1806           0 :                     llc.llc_control != LLC_UI ||
    1807           0 :                     llc.llc_snap.org_code[0] ||
    1808           0 :                     llc.llc_snap.org_code[1] ||
    1809           0 :                     llc.llc_snap.org_code[2] ||
    1810           0 :                     llc.llc_snap.ether_type != htons(ETHERTYPE_IP))
    1811             :                         goto dropit;
    1812             : 
    1813             :                 hassnap = 1;
    1814           0 :         }
    1815             : 
    1816           0 :         m_adj(m, ETHER_HDR_LEN);
    1817           0 :         if (hassnap)
    1818           0 :                 m_adj(m, LLC_SNAPFRAMELEN);
    1819             : 
    1820           0 :         if (m->m_len < sizeof(struct ip) &&
    1821           0 :             (m = m_pullup(m, sizeof(struct ip))) == NULL)
    1822             :                 goto dropit;
    1823           0 :         ip = mtod(m, struct ip *);
    1824             : 
    1825             :         /* Respect IP_DF, return a ICMP_UNREACH_NEEDFRAG. */
    1826           0 :         if (ip->ip_off & htons(IP_DF)) {
    1827           0 :                 bridge_send_icmp_err(sc, ifp, eh, m, hassnap, &llc,
    1828           0 :                     ifp->if_mtu, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG);
    1829           0 :                 return;
    1830             :         }
    1831             : 
    1832           0 :         error = ip_fragment(m, ifp, ifp->if_mtu);
    1833           0 :         if (error) {
    1834             :                 m = NULL;
    1835           0 :                 goto dropit;
    1836             :         }
    1837             : 
    1838           0 :         for (; m; m = m0) {
    1839           0 :                 m0 = m->m_nextpkt;
    1840           0 :                 m->m_nextpkt = NULL;
    1841           0 :                 if (error == 0) {
    1842           0 :                         if (hassnap) {
    1843           0 :                                 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
    1844           0 :                                 if (m == NULL) {
    1845             :                                         error = ENOBUFS;
    1846           0 :                                         continue;
    1847             :                                 }
    1848           0 :                                 bcopy(&llc, mtod(m, caddr_t),
    1849             :                                     LLC_SNAPFRAMELEN);
    1850           0 :                         }
    1851           0 :                         M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
    1852           0 :                         if (m == NULL) {
    1853             :                                 error = ENOBUFS;
    1854           0 :                                 continue;
    1855             :                         }
    1856           0 :                         bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
    1857           0 :                         error = bridge_ifenqueue(sc, ifp, m);
    1858           0 :                         if (error) {
    1859             :                                 continue;
    1860             :                         }
    1861             :                 } else
    1862           0 :                         m_freem(m);
    1863             :         }
    1864             : 
    1865           0 :         if (error == 0)
    1866           0 :                 ipstat_inc(ips_fragmented);
    1867             : 
    1868           0 :         return;
    1869             :  dropit:
    1870           0 :         m_freem(m);
    1871           0 : }
    1872             : 
    1873             : int
    1874           0 : bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
    1875             : {
    1876             :         int error, len;
    1877             : 
    1878             :         /* Loop prevention. */
    1879           0 :         m->m_flags |= M_PROTO1;
    1880             : 
    1881           0 :         len = m->m_pkthdr.len;
    1882             : 
    1883           0 :         error = if_enqueue(ifp, m);
    1884           0 :         if (error) {
    1885           0 :                 sc->sc_if.if_oerrors++;
    1886           0 :                 return (error);
    1887             :         }
    1888             : 
    1889           0 :         sc->sc_if.if_opackets++;
    1890           0 :         sc->sc_if.if_obytes += len;
    1891             : 
    1892           0 :         return (0);
    1893           0 : }
    1894             : 
    1895             : void
    1896           0 : bridge_ifinput(struct ifnet *ifp, struct mbuf *m)
    1897             : {
    1898           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1899             : 
    1900           0 :         m->m_flags |= M_PROTO1;
    1901             : 
    1902           0 :         ml_enqueue(&ml, m);
    1903           0 :         if_input(ifp, &ml);
    1904           0 : }
    1905             : 
    1906             : void
    1907           0 : bridge_send_icmp_err(struct bridge_softc *sc, struct ifnet *ifp,
    1908             :     struct ether_header *eh, struct mbuf *n, int hassnap, struct llc *llc,
    1909             :     int mtu, int type, int code)
    1910             : {
    1911             :         struct ip *ip;
    1912             :         struct icmp *icp;
    1913             :         struct in_addr t;
    1914             :         struct mbuf *m, *n2;
    1915             :         int hlen;
    1916           0 :         u_int8_t ether_tmp[ETHER_ADDR_LEN];
    1917             : 
    1918           0 :         n2 = m_copym(n, 0, M_COPYALL, M_DONTWAIT);
    1919           0 :         if (!n2) {
    1920           0 :                 m_freem(n);
    1921           0 :                 return;
    1922             :         }
    1923           0 :         m = icmp_do_error(n, type, code, 0, mtu);
    1924           0 :         if (m == NULL) {
    1925           0 :                 m_freem(n2);
    1926           0 :                 return;
    1927             :         }
    1928             : 
    1929             :         n = n2;
    1930             : 
    1931           0 :         ip = mtod(m, struct ip *);
    1932           0 :         hlen = ip->ip_hl << 2;
    1933           0 :         t = ip->ip_dst;
    1934           0 :         ip->ip_dst = ip->ip_src;
    1935           0 :         ip->ip_src = t;
    1936             : 
    1937           0 :         m->m_data += hlen;
    1938           0 :         m->m_len -= hlen;
    1939           0 :         icp = mtod(m, struct icmp *);
    1940           0 :         icp->icmp_cksum = 0;
    1941           0 :         icp->icmp_cksum = in_cksum(m, ntohs(ip->ip_len) - hlen);
    1942           0 :         m->m_data -= hlen;
    1943           0 :         m->m_len += hlen;
    1944             : 
    1945           0 :         ip->ip_v = IPVERSION;
    1946           0 :         ip->ip_off &= htons(IP_DF);
    1947           0 :         ip->ip_id = htons(ip_randomid());
    1948           0 :         ip->ip_ttl = MAXTTL;
    1949           0 :         ip->ip_sum = 0;
    1950           0 :         ip->ip_sum = in_cksum(m, hlen);
    1951             : 
    1952             :         /* Swap ethernet addresses */
    1953           0 :         bcopy(&eh->ether_dhost, &ether_tmp, sizeof(ether_tmp));
    1954           0 :         bcopy(&eh->ether_shost, &eh->ether_dhost, sizeof(ether_tmp));
    1955           0 :         bcopy(&ether_tmp, &eh->ether_shost, sizeof(ether_tmp));
    1956             : 
    1957             :         /* Reattach SNAP header */
    1958           0 :         if (hassnap) {
    1959           0 :                 M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);
    1960           0 :                 if (m == NULL)
    1961             :                         goto dropit;
    1962           0 :                 bcopy(llc, mtod(m, caddr_t), LLC_SNAPFRAMELEN);
    1963           0 :         }
    1964             : 
    1965             :         /* Reattach ethernet header */
    1966           0 :         M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
    1967           0 :         if (m == NULL)
    1968             :                 goto dropit;
    1969           0 :         bcopy(eh, mtod(m, caddr_t), sizeof(*eh));
    1970             : 
    1971           0 :         bridge_output(ifp, m, NULL, NULL);
    1972           0 :         m_freem(n);
    1973           0 :         return;
    1974             : 
    1975             :  dropit:
    1976           0 :         m_freem(n);
    1977           0 : }
    1978             : 
    1979             : struct bridge_tunneltag *
    1980           0 : bridge_tunnel(struct mbuf *m)
    1981             : {
    1982             :         struct m_tag    *mtag;
    1983             : 
    1984           0 :         if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL)
    1985           0 :                 return (NULL);
    1986             : 
    1987           0 :         return ((struct bridge_tunneltag *)(mtag + 1));
    1988           0 : }
    1989             : 
    1990             : struct bridge_tunneltag *
    1991           0 : bridge_tunneltag(struct mbuf *m)
    1992             : {
    1993             :         struct m_tag    *mtag;
    1994             : 
    1995           0 :         if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) == NULL) {
    1996           0 :                 mtag = m_tag_get(PACKET_TAG_TUNNEL,
    1997             :                     sizeof(struct bridge_tunneltag), M_NOWAIT);
    1998           0 :                 if (mtag == NULL)
    1999           0 :                         return (NULL);
    2000           0 :                 bzero(mtag + 1, sizeof(struct bridge_tunneltag));
    2001           0 :                 m_tag_prepend(m, mtag);
    2002           0 :         }
    2003             : 
    2004           0 :         return ((struct bridge_tunneltag *)(mtag + 1));
    2005           0 : }
    2006             : 
    2007             : void
    2008           0 : bridge_tunneluntag(struct mbuf *m)
    2009             : {
    2010             :         struct m_tag    *mtag;
    2011           0 :         if ((mtag = m_tag_find(m, PACKET_TAG_TUNNEL, NULL)) != NULL)
    2012           0 :                 m_tag_delete(m, mtag);
    2013           0 : }
    2014             : 
    2015             : void
    2016           0 : bridge_copyaddr(struct sockaddr *src, struct sockaddr *dst)
    2017             : {
    2018           0 :         if (src != NULL && src->sa_family != AF_UNSPEC)
    2019           0 :                 memcpy(dst, src, src->sa_len);
    2020             :         else {
    2021           0 :                 dst->sa_family = AF_UNSPEC;
    2022           0 :                 dst->sa_len = 0;
    2023             :         }
    2024           0 : }
    2025             : 
    2026             : void
    2027           0 : bridge_copytag(struct bridge_tunneltag *src, struct bridge_tunneltag *dst)
    2028             : {
    2029           0 :         if (src == NULL) {
    2030           0 :                 memset(dst, 0, sizeof(*dst));
    2031           0 :         } else {
    2032           0 :                 bridge_copyaddr(&src->brtag_peer.sa, &dst->brtag_peer.sa);
    2033           0 :                 bridge_copyaddr(&src->brtag_local.sa, &dst->brtag_local.sa);
    2034           0 :                 dst->brtag_id = src->brtag_id;
    2035             :         }
    2036           0 : }

Generated by: LCOV version 1.13