diff options
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 190 |
1 files changed, 64 insertions, 126 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 54503a16dc6..72e244b9f48 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.196 2012/09/20 14:10:18 mpf Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.197 2012/10/05 17:17:04 camield Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -273,7 +273,7 @@ bridge_delete(struct bridge_softc *sc, struct bridge_iflist *p) if (p->bif_flags & IFBIF_STP) bstp_delete(p->bif_stp); - p->ifp->if_bridge = NULL; + p->ifp->if_bridgeport = NULL; error = ifpromisc(p->ifp, 0); LIST_REMOVE(p, next); @@ -310,11 +310,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ENOENT; break; } - if (ifs->if_bridge == (caddr_t)sc) { - error = EEXIST; - break; - } - if (ifs->if_bridge != NULL) { + if (ifs->if_bridgeport != NULL) { error = EBUSY; break; } @@ -384,28 +380,28 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; } + p->bridge_sc = sc; p->ifp = ifs; p->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; SIMPLEQ_INIT(&p->bif_brlin); SIMPLEQ_INIT(&p->bif_brlout); - ifs->if_bridge = (caddr_t)sc; + ifs->if_bridgeport = (caddr_t)p; LIST_INSERT_HEAD(&sc->sc_iflist, p, next); break; case SIOCBRDGDEL: if ((error = suser(curproc, 0)) != 0) break; - - LIST_FOREACH(p, &sc->sc_iflist, next) { - if (strncmp(p->ifp->if_xname, req->ifbr_ifsname, - sizeof(p->ifp->if_xname)) == 0) { - error = bridge_delete(sc, p); - break; - } - } - if (p == LIST_END(&sc->sc_iflist)) { + ifs = ifunit(req->ifbr_ifsname); + if (ifs == NULL) { error = ENOENT; break; } + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { + error = ESRCH; + break; + } + error = bridge_delete(sc, p); break; case SIOCBRDGIFS: error = bridge_bifconf(sc, (struct ifbifconf *)data); @@ -418,11 +414,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ENOENT; break; } - if (ifs->if_bridge == (caddr_t)sc) { - error = EEXIST; - break; - } - if (ifs->if_bridge != NULL) { + if (ifs->if_bridgeport != NULL) { error = EBUSY; break; } @@ -467,15 +459,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 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)) { + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { error = ESRCH; break; } @@ -515,15 +500,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 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)) { + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { error = ESRCH; break; } @@ -561,15 +539,13 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCBRDGSADDR: if ((error = suser(curproc, 0)) != 0) break; - 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) { + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { error = ESRCH; break; } @@ -626,16 +602,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ENOENT; break; } - if (ifs->if_bridge == NULL || - ifs->if_bridge != (caddr_t)sc) { - error = ESRCH; - break; - } - LIST_FOREACH(p, &sc->sc_iflist, next) { - if (p->ifp == ifs) - break; - } - if (p == LIST_END(&sc->sc_iflist)) { + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { error = ESRCH; break; } @@ -664,16 +632,8 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ENOENT; break; } - if (ifs->if_bridge == NULL || - ifs->if_bridge != (caddr_t)sc) { - error = ESRCH; - break; - } - LIST_FOREACH(p, &sc->sc_iflist, next) { - if (p->ifp == ifs) - break; - } - if (p == LIST_END(&sc->sc_iflist)) { + p = (struct bridge_iflist *)ifs->if_bridgeport; + if (p == NULL || p->bridge_sc != sc) { error = ESRCH; break; } @@ -731,51 +691,49 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) void bridge_ifdetach(struct ifnet *ifp) { - struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge; + struct bridge_softc *sc; struct bridge_iflist *bif; - LIST_FOREACH(bif, &sc->sc_iflist, next) - if (bif->ifp == ifp) { - bridge_delete(sc, bif); - break; - } + bif = (struct bridge_iflist *)ifp->if_bridgeport; + sc = bif->bridge_sc; + + bridge_delete(sc, bif); } void bridge_update(struct ifnet *ifp, struct ether_addr *ea, int delete) { - struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge; + struct bridge_softc *sc; struct bridge_iflist *bif; u_int8_t *addr; addr = (u_int8_t *)ea; - LIST_FOREACH(bif, &sc->sc_iflist, next) - if (bif->ifp == ifp) { - /* - * Update the bridge interface if it is in - * the learning state. - */ - if ((bif->bif_flags & IFBIF_LEARNING) && - (ETHER_IS_MULTICAST(addr) == 0) && - !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && - addr[3] == 0 && addr[4] == 0 && addr[5] == 0)) { - /* Care must be taken with spanning tree */ - if ((bif->bif_flags & IFBIF_STP) && - (bif->bif_state == BSTP_IFSTATE_DISCARDING)) - return; + bif = (struct bridge_iflist *)ifp->if_bridgeport; + sc = bif->bridge_sc; - /* Delete the address from the bridge */ - bridge_rtdaddr(sc, ea); - - if (!delete) { - /* Update the bridge table */ - bridge_rtupdate(sc, ea, ifp, 0, - IFBAF_DYNAMIC); - } - } + /* + * Update the bridge interface if it is in + * the learning state. + */ + if ((bif->bif_flags & IFBIF_LEARNING) && + (ETHER_IS_MULTICAST(addr) == 0) && + !(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && + addr[3] == 0 && addr[4] == 0 && addr[5] == 0)) { + /* Care must be taken with spanning tree */ + if ((bif->bif_flags & IFBIF_STP) && + (bif->bif_state == BSTP_IFSTATE_DISCARDING)) return; + + /* Delete the address from the bridge */ + bridge_rtdaddr(sc, ea); + + if (!delete) { + /* Update the bridge table */ + bridge_rtupdate(sc, ea, ifp, 0, IFBAF_DYNAMIC); } + } + return; } int @@ -879,13 +837,8 @@ bridge_brlconf(struct bridge_softc *sc, struct ifbrlconf *bc) ifp = ifunit(bc->ifbrl_ifsname); if (ifp == NULL) return (ENOENT); - if (ifp->if_bridge == NULL || ifp->if_bridge != (caddr_t)sc) - return (ESRCH); - LIST_FOREACH(ifl, &sc->sc_iflist, next) { - if (ifl->ifp == ifp) - break; - } - if (ifl == LIST_END(&sc->sc_iflist)) + ifl = (struct bridge_iflist *)ifp->if_bridgeport; + if (ifl == NULL || ifl->bridge_sc != sc) return (ESRCH); SIMPLEQ_FOREACH(n, &ifl->bif_brlin, brl_next) { @@ -1005,11 +958,11 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, #endif /* IPSEC */ /* ifp must be a member interface of the bridge. */ - sc = (struct bridge_softc *)ifp->if_bridge; - if (sc == NULL) { + if (ifp->if_bridgeport == NULL) { m_freem(m); return (EINVAL); } + sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc; if (m->m_len < sizeof(*eh)) { m = m_pullup(m, sizeof(*eh)); @@ -1207,11 +1160,8 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m) sc->sc_if.if_ipackets++; sc->sc_if.if_ibytes += m->m_pkthdr.len; - LIST_FOREACH(ifl, &sc->sc_iflist, next) - if (ifl->ifp == src_if) - break; - - if (ifl == LIST_END(&sc->sc_iflist)) { + ifl = (struct bridge_iflist *)src_if->if_bridgeport; + if (ifl == NULL) { m_freem(m); return; } @@ -1327,14 +1277,7 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m) m_freem(m); return; } - LIST_FOREACH(ifl, &sc->sc_iflist, next) { - if (ifl->ifp == dst_if) - break; - } - if (ifl == LIST_END(&sc->sc_iflist)) { - m_freem(m); - return; - } + ifl = (struct bridge_iflist *)dst_if->if_bridgeport; if ((ifl->bif_flags & IFBIF_STP) && (ifl->bif_state == BSTP_IFSTATE_DISCARDING)) { m_freem(m); @@ -1379,7 +1322,7 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) /* * Make sure this interface is a bridge member. */ - if (ifp == NULL || ifp->if_bridge == NULL || m == NULL) + if (ifp == NULL || ifp->if_bridgeport == NULL || m == NULL) return (m); if ((m->m_flags & M_PKTHDR) == 0) @@ -1387,17 +1330,11 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) m->m_flags &= ~M_PROTO1; /* Loop prevention */ - sc = (struct bridge_softc *)ifp->if_bridge; + ifl = (struct bridge_iflist *)ifp->if_bridgeport; + sc = ifl->bridge_sc; if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return (m); - LIST_FOREACH(ifl, &sc->sc_iflist, next) { - if (ifl->ifp == ifp) - break; - } - if (ifl == LIST_END(&sc->sc_iflist)) - return (m); - #if NBPFILTER > 0 if (sc->sc_if.if_bpf) bpf_mtap_hdr(sc->sc_if.if_bpf, (caddr_t)eh, @@ -2000,10 +1937,11 @@ bridge_rtage(struct bridge_softc *sc) void bridge_rtagenode(struct ifnet *ifp, int age) { - struct bridge_softc *sc = (struct bridge_softc *)ifp->if_bridge; + struct bridge_softc *sc; struct bridge_rtnode *n; int i; + sc = ((struct bridge_iflist *)ifp->if_bridgeport)->bridge_sc; if (sc == NULL) return; |