svn commit: r237104 - in stable/8/sys: net netinet
Andrew Thompson
thompsa at FreeBSD.org
Thu Jun 14 21:36:17 UTC 2012
Author: thompsa
Date: Thu Jun 14 21:36:16 2012
New Revision: 237104
URL: http://svn.freebsd.org/changeset/base/237104
Log:
MFC r236916
Fix a panic I introduced in r234487, the bridge softc pointer is set to null
early in the detach so rearrange things not to explode.
Reported by: David Roffiaen, Gustau Perez Querol
Modified:
stable/8/sys/net/if_bridge.c
stable/8/sys/netinet/ip_carp.c
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/boot/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/e1000/ (props changed)
Modified: stable/8/sys/net/if_bridge.c
==============================================================================
--- stable/8/sys/net/if_bridge.c Thu Jun 14 21:35:20 2012 (r237103)
+++ stable/8/sys/net/if_bridge.c Thu Jun 14 21:36:16 2012 (r237104)
@@ -334,6 +334,7 @@ static int bridge_ip6_checkbasic(struct
static int bridge_fragment(struct ifnet *, struct mbuf *,
struct ether_header *, int, struct llc *);
static void bridge_linkstate(struct ifnet *ifp);
+static void bridge_linkcheck(struct bridge_softc *sc);
extern void (*bridge_linkstate_p)(struct ifnet *ifp);
@@ -964,6 +965,7 @@ bridge_delete_member(struct bridge_softc
EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp);
}
+ bridge_linkcheck(sc);
bridge_mutecaps(sc); /* recalcuate now this interface is removed */
bridge_rtdelete(sc, ifs, IFBF_FLUSHALL);
KASSERT(bif->bif_addrcnt == 0,
@@ -993,7 +995,6 @@ bridge_delete_member(struct bridge_softc
bridge_set_ifcap(sc, bif, bif->bif_savedcaps);
}
bstp_destroy(&bif->bif_stp); /* prepare to free */
- bridge_linkstate(ifs);
BRIDGE_LOCK(sc);
free(bif, M_DEVBUF);
}
@@ -1092,18 +1093,17 @@ bridge_ioctl_add(struct bridge_softc *sc
/* Set interface capabilities to the intersection set of all members */
bridge_mutecaps(sc);
+ bridge_linkcheck(sc);
- BRIDGE_UNLOCK(sc);
- /* Update the linkstate for the bridge */
- bridge_linkstate(ifs);
/* Place the interface into promiscuous mode */
switch (ifs->if_type) {
case IFT_ETHER:
case IFT_L2VLAN:
+ BRIDGE_UNLOCK(sc);
error = ifpromisc(ifs, 1);
+ BRIDGE_LOCK(sc);
break;
}
- BRIDGE_LOCK(sc);
if (error)
bridge_delete_member(sc, bif, 0);
out:
@@ -3485,8 +3485,7 @@ static void
bridge_linkstate(struct ifnet *ifp)
{
struct bridge_softc *sc = ifp->if_bridge;
- struct bridge_iflist *bif, *bif2;
- int new_link, hasls;
+ struct bridge_iflist *bif;
BRIDGE_LOCK(sc);
bif = bridge_lookup_member_if(sc, ifp);
@@ -3494,13 +3493,26 @@ bridge_linkstate(struct ifnet *ifp)
BRIDGE_UNLOCK(sc);
return;
}
+ bridge_linkcheck(sc);
+ BRIDGE_UNLOCK(sc);
+
+ bstp_linkstate(&bif->bif_stp);
+}
+
+static void
+bridge_linkcheck(struct bridge_softc *sc)
+{
+ struct bridge_iflist *bif;
+ int new_link, hasls;
+
+ BRIDGE_LOCK_ASSERT(sc);
new_link = LINK_STATE_DOWN;
hasls = 0;
/* Our link is considered up if at least one of our ports is active */
- LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) {
- if (bif2->bif_ifp->if_capabilities & IFCAP_LINKSTATE)
+ LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
+ if (bif->bif_ifp->if_capabilities & IFCAP_LINKSTATE)
hasls++;
- if (bif2->bif_ifp->if_link_state == LINK_STATE_UP) {
+ if (bif->bif_ifp->if_link_state == LINK_STATE_UP) {
new_link = LINK_STATE_UP;
break;
}
@@ -3510,8 +3522,4 @@ bridge_linkstate(struct ifnet *ifp)
new_link = LINK_STATE_UP;
}
if_link_state_change(sc->sc_ifp, new_link);
- BRIDGE_UNLOCK(sc);
-
- bstp_linkstate(&bif->bif_stp);
}
-
Modified: stable/8/sys/netinet/ip_carp.c
==============================================================================
--- stable/8/sys/netinet/ip_carp.c Thu Jun 14 21:35:20 2012 (r237103)
+++ stable/8/sys/netinet/ip_carp.c Thu Jun 14 21:36:16 2012 (r237104)
@@ -100,6 +100,7 @@ struct carp_softc {
#ifdef INET6
struct in6_ifaddr *sc_ia6; /* primary iface address v6 */
struct ip6_moptions sc_im6o;
+ struct in6_ifaddr *sc_llia;
#endif /* INET6 */
TAILQ_ENTRY(carp_softc) sc_list;
@@ -1239,6 +1240,16 @@ carp_iamatch6(struct ifnet *ifp, struct
cif = ifp->if_carp;
CARP_LOCK(cif);
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
+ if (IN6_ARE_ADDR_EQUAL(taddr,
+ &vh->sc_llia->ia_addr.sin6_addr) &&
+ (SC2IFP(vh)->if_flags & IFF_UP) &&
+ (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING) &&
+ vh->sc_state == MASTER) {
+ ifa = &vh->sc_llia->ia_addr;
+ ifa_ref(ifa);
+ CARP_UNLOCK(cif);
+ return (ifa);
+ }
IF_ADDR_RLOCK(SC2IFP(vh));
TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
@@ -1270,6 +1281,28 @@ carp_macmatch6(struct ifnet *ifp, struct
cif = ifp->if_carp;
CARP_LOCK(cif);
TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) {
+ if (IN6_ARE_ADDR_EQUAL(taddr,
+ sc->sc_llia->ia_addr.sin6_addr) &&
+ (SC2IFP(sc)->if_flags & IFF_UP) &&
+ (SC2IFP(sc)->if_drv_flags & IFF_DRV_RUNNING) &&
+ sc->sc_state == MASTER) {
+ struct ifnet *ifp = SC2IFP(sc);
+ mtag = m_tag_get(PACKET_TAG_CARP,
+ sizeof(struct ifnet *), M_NOWAIT);
+ if (mtag == NULL) {
+ /* better a bit than nothing */
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
+ CARP_UNLOCK(cif);
+ return (IF_LLADDR(sc->sc_ifp));
+ }
+ bcopy(&ifp, (caddr_t)(mtag + 1),
+ sizeof(struct ifnet *));
+ m_tag_prepend(m, mtag);
+
+ IF_ADDR_RUNLOCK(SC2IFP(sc));
+ CARP_UNLOCK(cif);
+ return (IF_LLADDR(sc->sc_ifp));
+ }
IF_ADDR_RLOCK(SC2IFP(sc));
TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) {
if (IN6_ARE_ADDR_EQUAL(taddr,
@@ -1749,6 +1782,33 @@ carp_set_addr6(struct carp_softc *sc, st
goto cleanup;
im6o->im6o_membership[1] = in6m;
im6o->im6o_num_memberships++;
+
+ /* Add link local */
+ bzero(&ifra, sizeof(ifra));
+ ifra.ifra_addr.sin6_family = AF_INET6;
+ ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
+ ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
+ ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
+ if ((error = in6_get_hw_ifid(sc->sc_ifp, NULL, &ifra.ifra_addr.sin6_addr)) != 0)
+ goto cleanup;
+ if ((error = in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL)))
+ goto cleanup;
+ ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
+ ifra.ifra_prefixmask.sin6_family = AF_INET6;
+ ifra.ifra_prefixmask.sin6_addr = in6mask64;
+ /* link-local addresses should NEVER expire. */
+ ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+ ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+
+ if ((error = in6_update_ifa(ifp, &ifra, NULL,
+ IN6_IFAUPDATE_DADDELAY)) != 0)
+ goto cleanup;
+ sc->sc_llia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
+ if (sc->sc_llia == NULL) {
+ error = ESRCH;
+ goto cleanup;
+ }
+ ifa_free(&sc->sc_llia->ia_ifa);
}
if (!ifp->if_carp) {
More information about the svn-src-all
mailing list