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