if_bridge.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,353 行 · 第 1/4 页
C
2,353 行
//==========================================================================//// sys/net/if_bridge.c//// ////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): Jason L. Wright (jason@thought.net) // Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt, manu.sharma@ascom.com// Date: 2000-07-18// Purpose: Ethernet bridge// Description: // ////####DESCRIPTIONEND####////==========================================================================/* $OpenBSD: if_bridge.c,v 1.33 2000/06/20 05:50:16 jason Exp $ *//* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Jason L. Wright * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#ifdef __ECOS#include <pkgconf/net.h>#else#include "bridge.h"#include "bpfilter.h"#include "enc.h"#endif#include <sys/param.h>#ifndef __ECOS#include <sys/proc.h>#include <sys/systm.h>#endif#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/errno.h>#ifndef __ECOS#include <sys/device.h>#endif#include <sys/kernel.h>#include <machine/cpu.h>#include <net/if.h>#include <net/if_types.h>#include <net/if_llc.h>#include <net/route.h>#include <net/netisr.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#include <netinet/ip_ipsp.h>#ifndef __ECOS#include <net/if_enc.h>#endif#ifdef IPFILTER#include <netinet/ip_fil_compat.h>#include <netinet/ip_fil.h>#endif#endif#if NBPFILTER > 0#include <net/bpf.h>#endif#include <net/if_bridge.h>#ifdef __ECOS#include <stdio.h> /* for sprintf */#endif #ifndef BRIDGE_RTABLE_SIZE#define BRIDGE_RTABLE_SIZE 1024#endif#define BRIDGE_RTABLE_MASK (BRIDGE_RTABLE_SIZE - 1)/* * Maximum number of addresses to cache */#ifndef BRIDGE_RTABLE_MAX#define BRIDGE_RTABLE_MAX 100#endif/* * Timeout (in seconds) for entries learned dynamically */#ifndef BRIDGE_RTABLE_TIMEOUT#define BRIDGE_RTABLE_TIMEOUT 300#endif/* Spanning tree defaults */#define BSTP_DEFAULT_MAX_AGE (20 * 256)#define BSTP_DEFAULT_HELLO_TIME (2 * 256)#define BSTP_DEFAULT_FORWARD_DELAY (15 * 256)#define BSTP_DEFAULT_HOLD_TIME (1 * 256)#define BSTP_DEFAULT_BRIDGE_PRIORITY 0x8000#define BSTP_DEFAULT_PORT_PRIORITY 0x80#define BSTP_DEFAULT_PATH_COST 55extern int ifqmaxlen;/* SNAP LLC header */struct snap { u_int8_t dsap; u_int8_t ssap; u_int8_t control; u_int8_t org[3]; u_int16_t type;};struct bridge_softc bridgectl[CYGNUM_NET_BRIDGES];void bridgeattach __P((int));int bridge_ioctl __P((struct ifnet *, u_long, caddr_t));void bridge_start __P((struct ifnet *));void bridgeintr_frame __P((struct bridge_softc *, struct mbuf *));void bridge_broadcast __P((struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *)) __attribute ((weak));void bridge_stop __P((struct bridge_softc *));void bridge_init __P((struct bridge_softc *));int bridge_bifconf __P((struct bridge_softc *, struct ifbifconf *));int bridge_rtfind __P((struct bridge_softc *, struct ifbaconf *));void bridge_rtage __P((void *));void bridge_rttrim __P((struct bridge_softc *));int bridge_rtdaddr __P((struct bridge_softc *, struct ether_addr *));int bridge_rtflush __P((struct bridge_softc *, int));struct ifnet * bridge_rtupdate __P((struct bridge_softc *, struct ether_addr *, struct ifnet *ifp, int, u_int8_t));struct ifnet * bridge_rtlookup __P((struct bridge_softc *, struct ether_addr *));u_int32_t bridge_hash __P((struct ether_addr *));int bridge_blocknonip __P((struct ether_header *, struct mbuf *));int bridge_addrule __P((struct bridge_iflist *, struct ifbrlreq *, int out));int bridge_flushrule __P((struct bridge_iflist *));int bridge_brlconf __P((struct bridge_softc *, struct ifbrlconf *));u_int8_t bridge_filterrule __P((struct brl_node *, struct ether_header *));int bridge_ifenqueue __P((struct bridge_softc *, struct ifnet *, struct mbuf *));#ifdef CYGPKG_NET_BRIDGE_STP_CODEvoid bridge_span (struct bridge_softc *, struct ether_header *, struct mbuf *);#endif#define ETHERADDR_IS_IP_MCAST(a) \ /* struct etheraddr *a; */ \ ((a)->ether_addr_octet[0] == 0x01 && \ (a)->ether_addr_octet[1] == 0x00 && \ (a)->ether_addr_octet[2] == 0x5e)#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))/* * Filter hooks */struct mbuf *bridge_filter __P((struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *m));#endifvoidbridgeattach(unused) int unused;{ int i; struct ifnet *ifp; for (i = 0; i < CYGNUM_NET_BRIDGES; i++) { bridgectl[i].sc_brtmax = BRIDGE_RTABLE_MAX; bridgectl[i].sc_brttimeout = (BRIDGE_RTABLE_TIMEOUT * hz) / 2; bridgectl[i].sc_bridge_max_age = BSTP_DEFAULT_MAX_AGE; bridgectl[i].sc_bridge_hello_time = BSTP_DEFAULT_HELLO_TIME; bridgectl[i].sc_bridge_forward_delay= BSTP_DEFAULT_FORWARD_DELAY; bridgectl[i].sc_bridge_priority = BSTP_DEFAULT_BRIDGE_PRIORITY; bridgectl[i].sc_hold_time = BSTP_DEFAULT_HOLD_TIME; LIST_INIT(&bridgectl[i].sc_iflist); LIST_INIT(&bridgectl[i].sc_spanlist); ifp = &bridgectl[i].sc_if; sprintf(ifp->if_xname, "bridge%d", i); ifp->if_softc = &bridgectl[i]; ifp->if_mtu = ETHERMTU; ifp->if_ioctl = bridge_ioctl; ifp->if_output = bridge_output; ifp->if_start = bridge_start; ifp->if_type = IFT_PROPVIRTUAL; ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_hdrlen = sizeof(struct ether_header); if_attach(ifp);#if NBPFILTER > 0 bpfattach(&bridgectl[i].sc_if.if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#endif }}intbridge_ioctl(ifp, cmd, data) struct ifnet *ifp; u_long cmd; caddr_t data;{#ifndef __ECOS struct proc *prc = curproc; /* XXX */#endif struct ifnet *ifs; struct bridge_softc *sc = (struct bridge_softc *)ifp->if_softc; struct ifbreq *req = (struct ifbreq *)data; struct ifbaconf *baconf = (struct ifbaconf *)data; struct ifbareq *bareq = (struct ifbareq *)data; struct ifbcachereq *bcachereq = (struct ifbcachereq *)data; struct ifbifconf *bifconf = (struct ifbifconf *)data; struct ifbcachetoreq *bcacheto = (struct ifbcachetoreq *)data; struct ifbrlreq *brlreq = (struct ifbrlreq *)data; struct ifbrlconf *brlconf = (struct ifbrlconf *)data; struct ifreq ifreq; int error = 0, s; struct bridge_iflist *p; s = splimp(); switch (cmd) { case SIOCBRDGADD:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) { /* no such interface */ error = ENOENT; break; } if (ifs->if_bridge == (caddr_t)sc) { error = EEXIST; break; } if (ifs->if_bridge != NULL) { error = EBUSY; break; }#ifdef CYGPKG_NET_BRIDGE_STP_CODE /* If it's in the span list, it can't be a member. */ LIST_FOREACH(p, &sc->sc_spanlist, next) { if (p->ifp == ifs) break; } if (p != LIST_END(&sc->sc_spanlist)) { error = EBUSY; break; }#endif if (ifs->if_type == IFT_ETHER) { if ((ifs->if_flags & IFF_UP) == 0) { /* * Bring interface up long enough to set * promiscuous flag, then shut it down again. */ strncpy(ifreq.ifr_name, req->ifbr_ifsname, sizeof(ifreq.ifr_name) - 1); ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0'; ifs->if_flags |= IFF_UP; ifreq.ifr_flags = ifs->if_flags; error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq); if (error != 0) break; error = ifpromisc(ifs, 1); if (error != 0) break; strncpy(ifreq.ifr_name, req->ifbr_ifsname, sizeof(ifreq.ifr_name) - 1); ifreq.ifr_name[sizeof(ifreq.ifr_name) - 1] = '\0'; ifs->if_flags &= ~IFF_UP; ifreq.ifr_flags = ifs->if_flags; error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq); if (error != 0) { ifpromisc(ifs, 0); break; } } else { error = ifpromisc(ifs, 1); if (error != 0) break; } }#ifndef __ECOS#if NENC > 0 else if (ifs->if_type == IFT_ENC) { /* Can't bind enc0 to a bridge */ if (ifs->if_softc == &encif[0]) { error = EINVAL; break; } }#endif /* NENC */#endif else { error = EINVAL; break; } p = (struct bridge_iflist *) malloc( sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT); if (p == NULL && ifs->if_type == IFT_ETHER) { error = ENOMEM; ifpromisc(ifs, 0); break; } p->ifp = ifs; p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; p->bif_priority = BSTP_DEFAULT_PORT_PRIORITY; p->bif_path_cost = BSTP_DEFAULT_PATH_COST; SIMPLEQ_INIT(&p->bif_brlin); SIMPLEQ_INIT(&p->bif_brlout); LIST_INSERT_HEAD(&sc->sc_iflist, p, next); ifs->if_bridge = (caddr_t)sc; break; case SIOCBRDGDEL:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif p = LIST_FIRST(&sc->sc_iflist); while (p != NULL) { if (strncmp(p->ifp->if_xname, req->ifbr_ifsname, sizeof(p->ifp->if_xname)) == 0) { p->ifp->if_bridge = NULL; error = ifpromisc(p->ifp, 0); LIST_REMOVE(p, next); bridge_rtdelete(sc, p->ifp, 0); bridge_flushrule(p); free(p, M_DEVBUF); break; } p = LIST_NEXT(p, next); } if (p == NULL) { error = ENOENT; break; } break; case SIOCBRDGIFS: error = bridge_bifconf(sc, bifconf); break;#ifdef CYGPKG_NET_BRIDGE_STP_CODE case SIOCBRDGADDS:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) { /* no such interface */ error = ENOENT; break; } if (ifs->if_bridge == (caddr_t)sc) { error = EEXIST; break; } if (ifs->if_bridge != NULL) { error = EBUSY; break; } LIST_FOREACH(p, &sc->sc_spanlist, next) { if (p->ifp == ifs) break; } if (p != LIST_END(&sc->sc_spanlist)) { error = EBUSY; break; } p = (struct bridge_iflist *)malloc( sizeof(struct bridge_iflist), M_DEVBUF, M_NOWAIT); if (p == NULL) { error = ENOMEM; break; } bzero(p, sizeof(struct bridge_iflist)); p->ifp = ifs; SIMPLEQ_INIT(&p->bif_brlin); SIMPLEQ_INIT(&p->bif_brlout); LIST_INSERT_HEAD(&sc->sc_spanlist, p, next); break; case SIOCBRDGDELS:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif LIST_FOREACH(p, &sc->sc_spanlist, next) { if (strncmp(p->ifp->if_xname, req->ifbr_ifsname, sizeof(p->ifp->if_xname)) == 0) { LIST_REMOVE(p, next); free(p, M_DEVBUF); break; } } if (p == LIST_END(&sc->sc_spanlist)) { error = ENOENT; break; } break;#endif case SIOCBRDGGIFFLGS: ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) { error = ENOENT; break; } if ((caddr_t)sc != ifs->if_bridge) { error = ESRCH; break; } p = LIST_FIRST(&sc->sc_iflist); while (p != NULL && p->ifp != ifs) { p = LIST_NEXT(p, next); } if (p == NULL) { error = ESRCH; break; } req->ifbr_ifsflags = p->bif_flags; req->ifbr_state = p->bif_state; req->ifbr_priority = p->bif_priority; req->ifbr_path_cost = p->bif_path_cost; req->ifbr_portno = p->ifp->if_index & 0xff; break; case SIOCBRDGSIFFLGS:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) { error = ENOENT; break; } if ((caddr_t)sc != ifs->if_bridge) { error = ESRCH; break; } p = LIST_FIRST(&sc->sc_iflist); while (p != NULL && p->ifp != ifs) { p = LIST_NEXT(p, next); } if (p == NULL) { error = ESRCH; break; } p->bif_flags = req->ifbr_ifsflags; break; case SIOCBRDGSIFPRIO: case SIOCBRDGSIFCOST:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif ifs = ifunit(req->ifbr_ifsname); if (ifs == NULL) { error = ENOENT; break; } if ((caddr_t)sc != ifs->if_bridge) { error = ESRCH; break; } LIST_FOREACH(p, &sc->sc_iflist, next) { if (p->ifp == ifs) break; } if (p == LIST_END(&sc->sc_iflist)) { error = ESRCH; break; } if (cmd == SIOCBRDGSIFPRIO) p->bif_priority = req->ifbr_priority; else { if (req->ifbr_path_cost < 1) error = EINVAL; else p->bif_path_cost = req->ifbr_path_cost; } break; case SIOCBRDGRTS: error = bridge_rtfind(sc, baconf); break; case SIOCBRDGFLUSH:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif error = bridge_rtflush(sc, req->ifbr_ifsflags); break; case SIOCBRDGSADDR:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif ifs = ifunit(bareq->ifba_ifsname); if (ifs == NULL) { /* no such interface */ error = ENOENT; break; } if (ifs->if_bridge == NULL || ifs->if_bridge != (caddr_t)sc) { error = ESRCH; break; } ifs = bridge_rtupdate(sc, &bareq->ifba_dst, ifs, 1, bareq->ifba_flags); if (ifs == NULL) error = ENOMEM; break; case SIOCBRDGDADDR:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif error = bridge_rtdaddr(sc, &bareq->ifba_dst); break; case SIOCBRDGGCACHE: bcachereq->ifbc_size = sc->sc_brtmax; break; case SIOCBRDGSCACHE:#ifndef __ECOS if ((error = suser(prc->p_ucred, &prc->p_acflag)) != 0) break;#endif sc->sc_brtmax = bcachereq->ifbc_size; bridge_rttrim(sc);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?