--- //depot/vendor/freebsd/src/sys/dev/ath/if_ath.c	2005/07/22 18:00:59
+++ //depot/projects/netsmp/src/sys/dev/ath/if_ath.c	2005/07/23 00:06:01
@@ -1661,6 +1661,7 @@
 	/* calculate and install multicast filter */
 	if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
 		mfilt[0] = mfilt[1] = 0;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			caddr_t dl;
 
@@ -1673,6 +1674,7 @@
 			pos &= 0x3f;
 			mfilt[pos / 32] |= (1 << (pos % 32));
 		}
+		IF_ADDR_UNLOCK(ifp);
 	} else {
 		mfilt[0] = mfilt[1] = ~0;
 	}
--- //depot/vendor/freebsd/src/sys/dev/awi/awi.c	2005/07/22 16:50:36
+++ //depot/projects/netsmp/src/sys/dev/awi/awi.c	2005/07/23 00:06:01
@@ -1146,15 +1146,19 @@
 #ifdef __FreeBSD__
 	if (ifp->if_flags & IFF_ALLMULTI)
 		goto set_mib;
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
-		if (n == AWI_GROUP_ADDR_SIZE)
+		if (n == AWI_GROUP_ADDR_SIZE) {
+			IF_ADDR_UNLOCK(ifp);
 			goto set_mib;
+		}
 		IEEE80211_ADDR_COPY(sc->sc_mib_addr.aGroup_Addresses[n],
 		    LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 		n++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 #else
 	ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ec, enm);
 	while (enm != NULL) {
--- //depot/vendor/freebsd/src/sys/dev/bfe/if_bfe.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/bfe/if_bfe.c	2005/07/19 21:29:46
@@ -883,12 +883,14 @@
 		val |= BFE_RXCONF_ALLMULTI;
 	else {
 		val &= ~BFE_RXCONF_ALLMULTI;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
 			bfe_cam_write(sc,
 			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr), i++);
 		}
+		IF_ADDR_UNLOCK(ifp);
 	}
 
 	CSR_WRITE_4(sc, BFE_RXCONF, val);
--- //depot/vendor/freebsd/src/sys/dev/bge/if_bge.c	2005/06/24 21:45:25
+++ //depot/projects/netsmp/src/sys/dev/bge/if_bge.c	2005/07/19 21:29:46
@@ -1171,6 +1171,7 @@
 		CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), 0);
 
 	/* Now program new ones. */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1178,6 +1179,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) & 0x7F;
 		hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	for (i = 0; i < 4; i++)
 		CSR_WRITE_4(sc, BGE_MAR0 + (i * 4), hashes[i]);
--- //depot/vendor/freebsd/src/sys/dev/ed/if_ed.c	2005/06/15 20:25:30
+++ //depot/projects/netsmp/src/sys/dev/ed/if_ed.c	2005/07/19 21:29:46
@@ -1778,6 +1778,7 @@
 	mcaf[0] = 0;
 	mcaf[1] = 0;
 
+	IF_ADDR_LOCK(sc->ifp);
 	TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1785,6 +1786,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 		af[index >> 3] |= 1 << (index & 7);
 	}
+	IF_ADDR_UNLOCK(sc->ifp);
 }
 
 int
--- //depot/vendor/freebsd/src/sys/dev/em/if_em.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/em/if_em.c	2005/07/19 21:29:46
@@ -1596,7 +1596,8 @@
                 E1000_WRITE_REG(&adapter->hw, RCTL, reg_rctl);
                 msec_delay(5);
         }
-        
+
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
         LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -1611,6 +1612,7 @@
                       &mta[mcnt*ETH_LENGTH_OF_ADDRESS], ETH_LENGTH_OF_ADDRESS);
                 mcnt++;
         }
+	IF_ADDR_UNLOCK(ifp);
 
         if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) {
                 reg_rctl = E1000_READ_REG(&adapter->hw, RCTL);
--- //depot/vendor/freebsd/src/sys/dev/ex/if_ex.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/ex/if_ex.c	2005/07/19 21:29:46
@@ -840,11 +840,13 @@
 	ifp = sc->ifp;
 
 	count = 0;
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) {
 		if (maddr->ifma_addr->sa_family != AF_LINK)
 			continue;
 		count++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI)
 			|| count > 63) {
@@ -871,7 +873,8 @@
 		CSR_WRITE_2(sc, IO_PORT_REG, 0);
 		CSR_WRITE_2(sc, IO_PORT_REG, 0);
 		CSR_WRITE_2(sc, IO_PORT_REG, (count + 1) * 6);
-		
+
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) {
 			if (maddr->ifma_addr->sa_family != AF_LINK)
 				continue;
@@ -882,6 +885,7 @@
 			CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
 			CSR_WRITE_2(sc, IO_PORT_REG, *addr++);
 		}
+		IF_ADDR_UNLOCK(ifp);
 
 		/* Program our MAC address as well */
 		/* XXX: Is this necessary?  The Linux driver does this
--- //depot/vendor/freebsd/src/sys/dev/fe/if_fe.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/fe/if_fe.c	2005/07/19 21:29:46
@@ -2060,6 +2060,7 @@
 	struct ifmultiaddr *ifma;
 
 	filter = fe_filter_nothing;
+	IF_ADDR_LOCK(sc->ifp);
 	TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -2072,6 +2073,7 @@
 
 		filter.data[index >> 3] |= 1 << (index & 7);
 	}
+	IF_ADDR_UNLOCK(sc->ifp);
 	return ( filter );
 }
 
--- //depot/vendor/freebsd/src/sys/dev/fxp/if_fxp.c	2005/06/11 00:50:21
+++ //depot/projects/netsmp/src/sys/dev/fxp/if_fxp.c	2005/07/19 21:29:46
@@ -2484,6 +2484,7 @@
 
 	nmcasts = 0;
 	if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
+		IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
 		LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -2500,6 +2501,7 @@
 			    &sc->mcsp->mc_addr[nmcasts][0], ETHER_ADDR_LEN);
 			nmcasts++;
 		}
+		IF_ADDR_UNLOCK(ifp);
 	}
 	mcsp->mc_cnt = htole16(nmcasts * ETHER_ADDR_LEN);
 	return (nmcasts);
--- //depot/vendor/freebsd/src/sys/dev/gem/if_gem.c	2005/06/12 15:35:17
+++ //depot/projects/netsmp/src/sys/dev/gem/if_gem.c	2005/07/19 21:29:46
@@ -1894,6 +1894,7 @@
 	/* Clear hash table */
 	memset(hash, 0, sizeof(hash));
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) {
 		if (inm->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1906,6 +1907,7 @@
 		/* Set the corresponding bit in the filter. */
 		hash[crc >> 4] |= 1 << (15 - (crc & 15));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	v |= GEM_MAC_RX_HASH_FILTER;
 	ifp->if_flags &= ~IFF_ALLMULTI;
--- //depot/vendor/freebsd/src/sys/dev/hme/if_hme.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/hme/if_hme.c	2005/07/19 21:29:46
@@ -1679,6 +1679,7 @@
 	 * the word.
 	 */
 
+	IF_ADDR_LOCK(sc->sc_ifp);
 	TAILQ_FOREACH(inm, &sc->sc_ifp->if_multiaddrs, ifma_link) {
 		if (inm->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1691,6 +1692,7 @@
 		/* Set the corresponding bit in the filter. */
 		hash[crc >> 4] |= 1 << (crc & 0xf);
 	}
+	IF_ADDR_UNLOCK(sc->sc_ifp);
 
 	ifp->if_flags &= ~IFF_ALLMULTI;
 
--- //depot/vendor/freebsd/src/sys/dev/ie/if_ie.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/ie/if_ie.c	2005/07/19 21:29:46
@@ -1676,6 +1676,7 @@
 	 * Step through the list of addresses.
 	 */
 	sc->mcast_count = 0;
+	IF_ADDR_LOCK(sc->ifp);
 	TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1690,6 +1691,7 @@
 		      &(sc->mcast_addrs[sc->mcast_count]), 6);
 		sc->mcast_count++;
 	}
+	IF_ADDR_UNLOCK(sc->ifp);
 
 setflag:
 	sc->want_mcsetup = 1;
--- //depot/vendor/freebsd/src/sys/dev/if_ndis/if_ndis.c	2005/06/14 17:50:27
+++ //depot/projects/netsmp/src/sys/dev/if_ndis/if_ndis.c	2005/07/19 21:29:46
@@ -265,6 +265,7 @@
 	sc->ndis_filter |= NDIS_PACKET_TYPE_MULTICAST;
 
 	len = 0;
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -272,11 +273,13 @@
 		    mclist + (ETHER_ADDR_LEN * len), ETHER_ADDR_LEN);
 		len++;
 		if (len > mclistsz) {
+			IF_ADDR_UNLOCK(ifp);
 			sc->ndis_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
 			sc->ndis_filter &= ~NDIS_PACKET_TYPE_MULTICAST;
 			goto out;
 		}
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	len = len * ETHER_ADDR_LEN;
 	error = ndis_set_info(sc, OID_802_3_MULTICAST_LIST, mclist, &len);
--- //depot/vendor/freebsd/src/sys/dev/ixgb/if_ixgb.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/ixgb/if_ixgb.c	2005/07/19 21:29:46
@@ -1065,6 +1065,7 @@
 
 	IOCTL_DEBUGOUT("ixgb_set_multi: begin");
 
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
 	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -1077,6 +1078,7 @@
 		      &mta[mcnt * IXGB_ETH_LENGTH_OF_ADDRESS], IXGB_ETH_LENGTH_OF_ADDRESS);
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt > MAX_NUM_MULTICAST_ADDRESSES) {
 		reg_rctl = IXGB_READ_REG(&adapter->hw, RCTL);
--- //depot/vendor/freebsd/src/sys/dev/lge/if_lge.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/lge/if_lge.c	2005/07/19 21:29:46
@@ -390,6 +390,7 @@
 	CSR_WRITE_4(sc, LGE_MAR1, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -400,6 +401,7 @@
 		else
 			hashes[1] |= (1 << (h - 32));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, LGE_MAR0, hashes[0]);
 	CSR_WRITE_4(sc, LGE_MAR1, hashes[1]);
--- //depot/vendor/freebsd/src/sys/dev/lnc/if_lnc.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/lnc/if_lnc.c	2005/07/19 21:29:46
@@ -239,6 +239,7 @@
 	 */
 
 	bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN);
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -247,6 +248,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 		sc->init_block->ladrf[index >> 3] |= 1 << (index & 7);
 	}
+	IF_ADDR_UNLOCK(ifp);
 }
 
 void
--- //depot/vendor/freebsd/src/sys/dev/my/if_my.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/my/if_my.c	2005/07/19 21:29:46
@@ -346,6 +346,7 @@
 	CSR_WRITE_4(sc, MY_MAR1, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -357,6 +358,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= MY_AM;
--- //depot/vendor/freebsd/src/sys/dev/nge/if_nge.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/nge/if_nge.c	2005/07/19 21:29:46
@@ -705,6 +705,7 @@
 	 * that needs to be updated, and the lower 4 bits represent
 	 * which bit within that byte needs to be set.
 	 */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -716,6 +717,7 @@
 		    NGE_FILTADDR_MCAST_LO + (index * 2));
 		NGE_SETBIT(sc, NGE_RXFILT_DATA, (1 << bit));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, NGE_RXFILT_CTL, filtsave);
 
--- //depot/vendor/freebsd/src/sys/dev/nve/if_nve.c	2005/06/11 01:40:36
+++ //depot/projects/netsmp/src/sys/dev/nve/if_nve.c	2005/07/19 21:29:46
@@ -1074,6 +1074,7 @@
 		return;
 	}
 	/* Setup multicast filter */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		u_char *addrp;
 
@@ -1087,6 +1088,7 @@
 			oraddr[i] |= mcaddr;
 		}
 	}
+	IF_ADDR_UNLOCK(ifp);
 	for (i = 0; i < 6; i++) {
 		hwfilter.acMulticastAddress[i] = andaddr[i] & oraddr[i];
 		hwfilter.acMulticastMask[i] = andaddr[i] | (~oraddr[i]);
--- //depot/vendor/freebsd/src/sys/dev/owi/if_owi.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/owi/if_owi.c	2005/07/19 21:29:46
@@ -1213,6 +1213,7 @@
 		return;
 	}
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1225,6 +1226,7 @@
 			break;
 		}
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	mcast.wi_len = (i * 3) + 1;
 	wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
--- //depot/vendor/freebsd/src/sys/dev/pdq/pdq_ifsubr.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/pdq/pdq_ifsubr.c	2005/07/19 21:29:46
@@ -273,6 +273,7 @@
     PDQ_IFNET(sc)->if_flags &= ~IFF_ALLMULTI;
 #endif
 
+    IF_ADDR_LOCK(PDQ_IFNET(sc));
     for (ifma = TAILQ_FIRST(&PDQ_IFNET(sc)->if_multiaddrs); ifma && num_addrs > 0;
 	 ifma = TAILQ_NEXT(ifma, ifma_link)) {
 	    char *mcaddr;
@@ -285,6 +286,7 @@
 	    addr++;
 	    num_addrs--;
     }
+    IF_ADDR_UNLOCK(PDQ_IFNET(sc));
     /*
      * If not all the address fit into the CAM, turn on all-multicast mode.
      */
--- //depot/vendor/freebsd/src/sys/dev/ray/if_ray.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/ray/if_ray.c	2005/07/19 21:29:46
@@ -2704,6 +2704,7 @@
 	 * The multicast list is only 16 items long so use promiscuous
 	 * mode and don't bother updating the multicast list.
 	 */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 		count++;
 	if (count == 0) {
@@ -2711,6 +2712,7 @@
 		return;
 	} else if (count > 16) {
 		ifp->if_flags |= IFF_ALLMULTI;
+		IF_ADDR_UNLOCK(ifp);
 		ray_com_runq_done(sc);
 		return;
 	} else if (ifp->if_flags & IFF_ALLMULTI)
@@ -2732,6 +2734,7 @@
 		);
 		bufp += ETHER_ADDR_LEN;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	ray_com_ecf(sc, com);
 }
--- //depot/vendor/freebsd/src/sys/dev/re/if_re.c	2005/07/01 04:16:05
+++ //depot/projects/netsmp/src/sys/dev/re/if_re.c	2005/07/19 21:29:46
@@ -601,6 +601,7 @@
 	CSR_WRITE_4(sc, RL_MAR4, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -612,6 +613,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= RL_RXCFG_RX_MULTI;
--- //depot/vendor/freebsd/src/sys/dev/sn/if_sn.c	2005/07/18 23:45:24
+++ //depot/projects/netsmp/src/sys/dev/sn/if_sn.c	2005/07/19 21:29:46
@@ -1410,6 +1410,7 @@
 
 	bzero(mcf, MCFSZ);
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 	    if (ifma->ifma_addr->sa_family != AF_LINK)
 		return 0;
@@ -1423,5 +1424,6 @@
 	    }
 	    af[index2 >> 3] |= 1 << (index2 & 7);
 	}
+	IF_ADDR_UNLOCK(ifp);
 	return 1;  /* use multicast filter */
 }
--- //depot/vendor/freebsd/src/sys/dev/snc/dp83932.c	2005/06/12 15:25:25
+++ //depot/projects/netsmp/src/sys/dev/snc/dp83932.c	2005/07/19 21:29:46
@@ -675,6 +675,7 @@
 	ifp->if_flags &= ~IFF_ALLMULTI;
 
 	/* Loop through multicast addresses */
+	IF_ADDR_LOCK(ifp);
         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
                 if (ifma->ifma_addr->sa_family != AF_LINK)
                         continue;
@@ -688,6 +689,7 @@
 			 LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 		mcount++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda));
 	NIC_PUT(sc, SNCR_CDC, MAXCAM);
--- //depot/vendor/freebsd/src/sys/dev/tx/if_tx.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/tx/if_tx.c	2005/07/19 21:29:46
@@ -1409,6 +1409,7 @@
 	filter[2] = 0;
 	filter[3] = 0;
 
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
 	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -1420,6 +1421,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 		filter[h >> 4] |= 1 << (h & 0xF);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, MC0, filter[0]);
 	CSR_WRITE_4(sc, MC1, filter[1]);
--- //depot/vendor/freebsd/src/sys/dev/txp/if_txp.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/txp/if_txp.c	2005/07/19 21:29:46
@@ -1774,6 +1774,7 @@
 	else {
 		hash[0] = hash[1] = 0;
 
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
@@ -1797,6 +1798,7 @@
 			hashbit = (u_int16_t)(crc & (64 - 1));
 			hash[hashbit / 32] |= (1 << hashbit % 32);
 		}
+		IF_ADDR_UNLOCK(ifp);
 
 		if (mcnt > 0) {
 			filter |= TXP_RXFILT_HASHMULTI;
--- //depot/vendor/freebsd/src/sys/dev/usb/if_aue.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_aue.c	2005/07/19 21:29:46
@@ -539,6 +539,7 @@
 		aue_csr_write_1(sc, AUE_MAR0 + i, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -551,6 +552,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1);
 		AUE_SETBIT(sc, AUE_MAR + (h >> 3), 1 << (h & 0x7));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	return;
 }
--- //depot/vendor/freebsd/src/sys/dev/usb/if_axe.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_axe.c	2005/07/19 21:29:46
@@ -338,6 +338,7 @@
 	} else
 		rxmode &= ~AXE_RXCMD_ALLMULTI;
 
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -350,6 +351,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 		hashtbl[h / 8] |= 1 << (h % 8);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	axe_cmd(sc, AXE_CMD_WRITE_MCAST, 0, 0, (void *)&hashtbl);
 	axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, rxmode, NULL);
--- //depot/vendor/freebsd/src/sys/dev/usb/if_cue.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_cue.c	2005/07/19 21:29:46
@@ -356,6 +356,7 @@
 		sc->cue_mctab[i] = 0;
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -367,6 +368,7 @@
 		h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 		sc->cue_mctab[h >> 3] |= 1 << (h & 0x7);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	/*
 	 * Also include the broadcast address in the filter
--- //depot/vendor/freebsd/src/sys/dev/usb/if_kue.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_kue.c	2005/07/19 21:29:46
@@ -327,6 +327,7 @@
 
 	sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI;
 
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -345,6 +346,7 @@
 		    KUE_MCFILT(sc, i), ETHER_ADDR_LEN);
 		i++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (i == KUE_MCFILTCNT(sc))
 		sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI;
--- //depot/vendor/freebsd/src/sys/dev/usb/if_rue.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_rue.c	2005/07/19 22:53:09
@@ -500,6 +500,7 @@
 	rue_csr_write_4(sc, RUE_MAR4, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH (ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -516,6 +517,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxcfg |= RUE_RCR_AM;
--- //depot/vendor/freebsd/src/sys/dev/usb/if_udav.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/usb/if_udav.c	2005/07/19 21:29:46
@@ -1044,6 +1044,7 @@
 		ETHER_NEXT_MULTI(step, enm);
 	}
 #elif defined(__FreeBSD__)
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 #else
@@ -1056,6 +1057,7 @@
 		    ifma->ifma_addr));
 		hashes[h>>3] |= 1 << (h & 0x7);
 	}
+	IF_ADDR_UNLOCK(ifp);
 #endif
 
 	/* disable all multicast */
--- //depot/vendor/freebsd/src/sys/dev/vge/if_vge.c	2005/06/11 01:40:36
+++ //depot/projects/netsmp/src/sys/dev/vge/if_vge.c	2005/07/19 21:29:46
@@ -594,6 +594,7 @@
 	}
 
 	/* Now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -626,6 +627,7 @@
 		CSR_WRITE_4(sc, VGE_MAR0, hashes[0]);
 		CSR_WRITE_4(sc, VGE_MAR1, hashes[1]);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	return;
 }
--- //depot/vendor/freebsd/src/sys/dev/wi/if_wi.c	2005/07/22 16:50:36
+++ //depot/projects/netsmp/src/sys/dev/wi/if_wi.c	2005/07/23 00:06:01
@@ -1739,6 +1739,7 @@
 	}
 
 	n = 0;
+	IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
 	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -1752,6 +1753,7 @@
 		    (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
 		n++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 	return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
 	    IEEE80211_ADDR_LEN * n);
 }
--- //depot/vendor/freebsd/src/sys/dev/wl/if_wl.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/dev/wl/if_wl.c	2005/07/19 21:29:46
@@ -2121,6 +2121,7 @@
     outw(PIOP1(base), 0);				/* ac_status */
     outw(PIOP1(base), AC_MCSETUP|AC_CW_EL);		/* ac_command */
     outw(PIOR1(base), OFFSET_CU + 8);
+    IF_ADDR_LOCK(sc->ifp);
     TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
 	if (ifma->ifma_addr->sa_family != AF_LINK)
 	    continue;
@@ -2131,6 +2132,7 @@
         outw(PIOP1(base), addrp[4] + (addrp[5] << 8));
         ++cnt;
     }
+    IF_ADDR_UNLOCK(sc->ifp);
     outw(PIOR1(base), OFFSET_CU + 6);		/* mc-cnt */
     outw(PIOP1(base), cnt * WAVELAN_ADDR_SIZE);
     if (wlcmd(sc, "config()-mcaddress") == 0)
--- //depot/vendor/freebsd/src/sys/dev/xe/if_xe.c	2005/07/15 06:11:01
+++ //depot/projects/netsmp/src/sys/dev/xe/if_xe.c	2005/07/19 21:29:46
@@ -1274,6 +1274,7 @@
 
   /* Iterate over multicast address list */
   count = 0;
+  IF_ADDR_LOCK(ifp);
 #if __FreeBSD_version < 500000
   LIST_FOREACH(maddr, &ifp->if_multiaddrs, ifma_link) {
 #else
@@ -1295,6 +1296,7 @@
 	/* Nowhere else to put them on CE2 */
 	break;
   }
+  IF_ADDR_UNLOCK(ifp);
 
   DEVPRINTF(2, (scp->dev, "set_multicast: count = %u\n", count));
 
--- //depot/vendor/freebsd/src/sys/kern/subr_witness.c	2005/06/04 23:25:18
+++ //depot/projects/netsmp/src/sys/kern/subr_witness.c	2005/07/23 00:36:47
@@ -286,6 +286,13 @@
 	{ "ifaddr", &lock_class_mtx_sleep },
 	{ NULL, NULL },
 	/*
+	 * Multicast - protocol locks before interface locks.
+	 */
+	{ "in_multi_mtx", &lock_class_mtx_sleep },
+	{ "igmp_mtx", &lock_class_mtx_sleep },
+	{ "if_addr_mtx", &lock_class_mtx_sleep },
+	{ NULL, NULL },
+	/*
 	 * UNIX Domain Sockets
 	 */
 	{ "unp", &lock_class_mtx_sleep },
--- //depot/vendor/freebsd/src/sys/net/if.c	2005/07/19 10:16:50
+++ //depot/projects/netsmp/src/sys/net/if.c	2005/07/22 23:59:30
@@ -417,6 +417,8 @@
 {
 
 	if_free_type(ifp, ifp->if_type);
+
+	IF_ADDR_LOCK_DESTROY(ifp);
 }
 
 void
@@ -460,6 +462,7 @@
 	TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp);
 	TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
 	IF_AFDATA_LOCK_INIT(ifp);
+	IF_ADDR_LOCK_INIT(ifp);
 	ifp->if_afdata_initialized = 0;
 	IFNET_WLOCK();
 	TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
@@ -1824,99 +1827,229 @@
 	return (if_setflag(ifp, IFF_ALLMULTI, 0, &ifp->if_amcount, onswitch));
 }
 
+struct ifmultiaddr *
+ifmaof_ifpforaddr(struct sockaddr *sa, struct ifnet *ifp)
+{
+	struct ifmultiaddr *ifma;
+
+	IF_ADDR_LOCK_ASSERT(ifp);
+
+	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+		if (sa_equal(ifma->ifma_addr, sa))
+			break;
+	}
+
+	return ifma;
+}
+
+/*
+ * XXXRW: ifmaof_ifpforaddr() is an unsensible name, and appears not to be
+ * used, so use my more sensibly named version here.
+ */
+static struct ifmultiaddr *
+if_findmulti(struct ifnet *ifp, struct sockaddr *sa)
+{
+
+	IF_ADDR_LOCK_ASSERT(ifp);
+
+	return (ifmaof_ifpforaddr(sa, ifp));
+}
+
+/*
+ * Allocate a new ifmultiaddr and initialize based on passed arguments.  We
+ * make copies of passed sockaddrs.  The ifmultiaddr will not be added to
+ * the ifnet multicast address list here, so the caller must do that and
+ * other setup work (such as notifying the device driver).  The reference
+ * count is initialized to 1.
+ */
+static struct ifmultiaddr *
+if_allocmulti(struct ifnet *ifp, struct sockaddr *sa, struct sockaddr *llsa,
+    int mflags)
+{
+	struct ifmultiaddr *ifma;
+	struct sockaddr *dupsa;
+
+	MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, mflags |
+	    M_ZERO);
+	if (ifma == NULL)
+		return (NULL);
+
+	MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, mflags);
+	if (dupsa == NULL) {
+		FREE(ifma, M_IFMADDR);
+		return (NULL);
+	}
+	bcopy(sa, dupsa, sa->sa_len);
+	ifma->ifma_addr = dupsa;
+
+	ifma->ifma_ifp = ifp;
+	ifma->ifma_refcount = 1;
+	ifma->ifma_protospec = NULL;
+
+	if (llsa == NULL) {
+		ifma->ifma_lladdr = NULL;
+		return (ifma);
+	}
+
+	MALLOC(dupsa, struct sockaddr *, llsa->sa_len, M_IFMADDR, mflags);
+	if (dupsa == NULL) {
+		FREE(ifma->ifma_addr, M_IFMADDR);
+		FREE(ifma, M_IFMADDR);
+		return (NULL);
+	}
+	bcopy(llsa, dupsa, llsa->sa_len);
+	ifma->ifma_lladdr = dupsa;
+
+	return (ifma);
+}
+
+/*
+ * if_freemulti: free ifmultiaddr structure and possibly attached related
+ * addresses.  The caller is responsible for implementing reference
+ * counting, notifying the driver, handling routing messages, and releasing
+ * any dependent link layer state.
+ */
+static void
+if_freemulti(struct ifmultiaddr *ifma)
+{
+
+	KASSERT(ifma->ifma_refcount == 1, ("if_freemulti: refcount %d",
+	    ifma->ifma_refcount));
+	KASSERT(ifma->ifma_protospec == NULL,
+	    ("if_freemulti: protospec not NULL"));
+
+	if (ifma->ifma_lladdr != NULL)
+		FREE(ifma->ifma_lladdr, M_IFMADDR);
+	FREE(ifma->ifma_addr, M_IFMADDR);
+	FREE(ifma, M_IFMADDR);
+}
+
 /*
- * Add a multicast listenership to the interface in question.
- * The link layer provides a routine which converts
+ * Register an additional multicast address with a network interface.
+ *
+ * - If the address is already present, bump the reference count on the
+ *   address and return.
+ * - If the address is not link-layer, look up a link layer address.
+ * - Allocate address structures for one or both addresses, and attach to the
+ *   multicast address list on the interface.  If automatically adding a link
+ *   layer address, the protocol address will own a reference to the link
+ *   layer address, to be freed when it is freed.
+ * - Notify the network device driver of an addition to the multicast address
+ *   list.
+ *
+ * 'sa' points to caller-owned memory with the desired multicast address.
+ *
+ * 'retifma' will be used to return a pointer to the resulting multicast
+ * address reference, if desired.
  */
 int
-if_addmulti(struct ifnet *ifp, struct sockaddr *sa, struct ifmultiaddr **retifma)
+if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
+    struct ifmultiaddr **retifma)
 {
-	struct sockaddr *llsa, *dupsa;
-	int error, s;
-	struct ifmultiaddr *ifma;
+	struct ifmultiaddr *ifma, *ll_ifma;
+	struct sockaddr *llsa;
+	int error;
 
 	/*
-	 * If the matching multicast address already exists
-	 * then don't add a new one, just add a reference
+	 * If the address is already present, return a new reference to it;
+	 * otherwise, allocate storage and set up a new address.
 	 */
-	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-		if (sa_equal(sa, ifma->ifma_addr)) {
-			ifma->ifma_refcount++;
-			if (retifma)
-				*retifma = ifma;
-			return 0;
-		}
+	IF_ADDR_LOCK(ifp);
+	ifma = if_findmulti(ifp, sa);
+	if (ifma != NULL) {
+		ifma->ifma_refcount++;
+		if (retifma != NULL)
+			*retifma = ifma;
+		IF_ADDR_UNLOCK(ifp);
+		return (0);
 	}
 
 	/*
-	 * Give the link layer a chance to accept/reject it, and also
-	 * find out which AF_LINK address this maps to, if it isn't one
-	 * already.
+	 * The address isn't already present; resolve the protocol address
+	 * into a link layer address, and then look that up, bump its
+	 * refcount or allocate an ifma for that also.  If 'llsa' was
+	 * returned, we will need to free it later.
 	 */
+	llsa = NULL;
+	ll_ifma = NULL;
 	if (ifp->if_resolvemulti != NULL) {
 		error = ifp->if_resolvemulti(ifp, &llsa, sa);
-		if (error) return error;
-	} else {
-		llsa = NULL;
+		if (error)
+			goto unlock_out;
 	}
 
-	MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
-	MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
-	bcopy(sa, dupsa, sa->sa_len);
+	/*
+	 * Allocate the new address.  Don't hook it up yet, as we may also
+	 * need to allocate a link layer multicast address.
+	 */
+	ifma = if_allocmulti(ifp, sa, llsa, M_NOWAIT);
+	if (ifma == NULL) {
+		error = ENOMEM;
+		goto free_llsa_out;
+	}
 
-	ifma->ifma_addr = dupsa;
-	ifma->ifma_lladdr = llsa;
-	ifma->ifma_ifp = ifp;
-	ifma->ifma_refcount = 1;
-	ifma->ifma_protospec = NULL;
-	rt_newmaddrmsg(RTM_NEWMADDR, ifma);
+	/*
+	 * If a link layer address is found, we'll need to see if it's
+	 * already present in the address list, or allocate is as well.
+	 * When this block finishes, the link layer address will be on the
+	 * list.
+	 */
+	if (llsa != NULL) {
+		ll_ifma = if_findmulti(ifp, llsa);
+		if (ll_ifma == NULL) {
+			ll_ifma = if_allocmulti(ifp, llsa, NULL, M_NOWAIT);
+			if (ll_ifma == NULL) {
+				if_freemulti(ifma);
+				error = ENOMEM;
+				goto free_llsa_out;
+			}
+			TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ll_ifma,
+			    ifma_link);
+		} else
+			ll_ifma->ifma_refcount++;
+	}
 
 	/*
-	 * Some network interfaces can scan the address list at
-	 * interrupt time; lock them out.
+	 * We now have a new multicast address, ifma, and possibly a new or
+	 * referenced link layer address.  Add the primary address to the
+	 * ifnet address list.
 	 */
-	s = splimp();
 	TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
-	splx(s);
+
 	if (retifma != NULL)
 		*retifma = ifma;
 
-	if (llsa != NULL) {
-		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-			if (sa_equal(ifma->ifma_addr, llsa))
-				break;
-		}
-		if (ifma) {
-			ifma->ifma_refcount++;
-		} else {
-			MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
-			       M_IFMADDR, M_WAITOK);
-			MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
-			       M_IFMADDR, M_WAITOK);
-			bcopy(llsa, dupsa, llsa->sa_len);
-			ifma->ifma_addr = dupsa;
-			ifma->ifma_lladdr = NULL;
-			ifma->ifma_ifp = ifp;
-			ifma->ifma_refcount = 1;
-			ifma->ifma_protospec = NULL;
-			s = splimp();
-			TAILQ_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
-			splx(s);
-		}
-	}
+	/*
+	 * Must generate the message while holding the lock so that 'ifma'
+	 * pointer is still valid.
+	 *
+	 * XXXRW: How come we don't announce ll_ifma?
+	 */
+	rt_newmaddrmsg(RTM_NEWMADDR, ifma);
+	IF_ADDR_UNLOCK(ifp);
+
 	/*
 	 * We are certain we have added something, so call down to the
 	 * interface to let them know about it.
 	 */
 	if (ifp->if_ioctl != NULL) {
-		s = splimp();
 		IFF_LOCKGIANT(ifp);
 		(void) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, 0);
 		IFF_UNLOCKGIANT(ifp);
-		splx(s);
 	}
 
-	return 0;
+	if (llsa != NULL)
+		FREE(llsa, M_IFMADDR);
+
+	return (0);
+
+free_llsa_out:
+	if (llsa != NULL)
+		FREE(llsa, M_IFMADDR);
+
+unlock_out:
+	IF_ADDR_UNLOCK(ifp);
+	return (error);
 }
 
 /*
@@ -1926,72 +2059,53 @@
 int
 if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
 {
-	struct ifmultiaddr *ifma;
-	int s;
+	struct ifmultiaddr *ifma, *ll_ifma;
 
-	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-		if (sa_equal(sa, ifma->ifma_addr))
-			break;
-	if (ifma == NULL)
+	IF_ADDR_LOCK(ifp);
+	ifma = if_findmulti(ifp, sa);
+	if (ifma == NULL) {
+		IF_ADDR_UNLOCK(ifp);
 		return ENOENT;
+	}
 
 	if (ifma->ifma_refcount > 1) {
 		ifma->ifma_refcount--;
+		IF_ADDR_UNLOCK(ifp);
 		return 0;
 	}
 
-	rt_newmaddrmsg(RTM_DELMADDR, ifma);
 	sa = ifma->ifma_lladdr;
-	s = splimp();
-	TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
+	if (sa != NULL)
+		ll_ifma = if_findmulti(ifp, sa);
+	else
+		ll_ifma = NULL;
+
 	/*
-	 * Make sure the interface driver is notified
-	 * in the case of a link layer mcast group being left.
+	 * XXXRW: How come we don't announce ll_ifma?
 	 */
-	if (ifp->if_ioctl && ifma->ifma_addr->sa_family == AF_LINK && sa == 0) {
-		IFF_LOCKGIANT(ifp);
-		(void) (*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
-		IFF_UNLOCKGIANT(ifp);
+	rt_newmaddrmsg(RTM_DELMADDR, ifma);
+
+	TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
+	if_freemulti(ifma);
+
+	if (ll_ifma != NULL) {
+		if (ll_ifma->ifma_refcount == 1) {
+			TAILQ_REMOVE(&ifp->if_multiaddrs, ll_ifma, ifma_link);
+			if_freemulti(ll_ifma);
+		} else
+			ll_ifma->ifma_refcount--;
 	}
-	splx(s);
-	free(ifma->ifma_addr, M_IFMADDR);
-	free(ifma, M_IFMADDR);
-	if (sa == NULL)
-		return 0;
+	IF_ADDR_UNLOCK(ifp);
 
 	/*
-	 * Now look for the link-layer address which corresponds to
-	 * this network address.  It had been squirreled away in
-	 * ifma->ifma_lladdr for this purpose (so we don't have
-	 * to call ifp->if_resolvemulti() again), and we saved that
-	 * value in sa above.  If some nasty deleted the
-	 * link-layer address out from underneath us, we can deal because
-	 * the address we stored was is not the same as the one which was
-	 * in the record for the link-layer address.  (So we don't complain
-	 * in that case.)
+	 * Make sure the interface driver is notified
+	 * in the case of a link layer mcast group being left.
 	 */
-	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-		if (sa_equal(sa, ifma->ifma_addr))
-			break;
-	if (ifma == NULL)
-		return 0;
-
-	if (ifma->ifma_refcount > 1) {
-		ifma->ifma_refcount--;
-		return 0;
-	}
-
-	s = splimp();
-	TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
-	if (ifp->if_ioctl != NULL) {
+	if (ifp->if_ioctl) {
 		IFF_LOCKGIANT(ifp);
 		(void) (*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
 		IFF_UNLOCKGIANT(ifp);
 	}
-	splx(s);
-	free(ifma->ifma_addr, M_IFMADDR);
-	free(sa, M_IFMADDR);
-	free(ifma, M_IFMADDR);
 
 	return 0;
 }
@@ -2070,18 +2184,6 @@
 	return (0);
 }
 
-struct ifmultiaddr *
-ifmaof_ifpforaddr(struct sockaddr *sa, struct ifnet *ifp)
-{
-	struct ifmultiaddr *ifma;
-
-	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-		if (sa_equal(ifma->ifma_addr, sa))
-			break;
-
-	return ifma;
-}
-
 /*
  * The name argument must be a pointer to storage which will last as
  * long as the interface does.  For physical devices, the result of
--- //depot/vendor/freebsd/src/sys/net/if_arcsubr.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/net/if_arcsubr.c	2005/07/22 02:45:35
@@ -798,7 +798,9 @@
 		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
 			return EADDRNOTAVAIL;
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_ZERO);
+		       M_NOWAIT | M_ZERO);
+		if (sdl == NULL)
+			return ENOMEM;
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
@@ -824,7 +826,9 @@
 		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
 			return EADDRNOTAVAIL;
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_ZERO);
+		       M_NOWAIT | M_ZERO);
+		if (sdl == NULL)
+			return ENOMEM;
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
--- //depot/vendor/freebsd/src/sys/net/if_ethersubr.c	2005/07/21 09:02:12
+++ //depot/projects/netsmp/src/sys/net/if_ethersubr.c	2005/07/23 00:06:01
@@ -1144,7 +1144,9 @@
 		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
 			return EADDRNOTAVAIL;
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK|M_ZERO);
+		       M_NOWAIT|M_ZERO);
+		if (sdl == NULL)
+			return ENOMEM;
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
@@ -1171,7 +1173,9 @@
 		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
 			return EADDRNOTAVAIL;
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK|M_ZERO);
+		       M_NOWAIT|M_ZERO);
+		if (sdl == NULL)
+			return (ENOMEM);
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
--- //depot/vendor/freebsd/src/sys/net/if_fddisubr.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/net/if_fddisubr.c	2005/07/22 02:45:35
@@ -720,7 +720,9 @@
 		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
 			return (EADDRNOTAVAIL);
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK);
+		       M_NOWAIT | M_ZERO);
+		if (sdl == NULL)
+			return (ENOMEM);
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
@@ -749,7 +751,9 @@
 		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
 			return (EADDRNOTAVAIL);
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK);
+		       M_NOWAIT | M_ZERO);
+		if (sdl == NULL)
+			return (ENOMEM);
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
--- //depot/vendor/freebsd/src/sys/net/if_iso88025subr.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/net/if_iso88025subr.c	2005/07/22 02:45:35
@@ -720,7 +720,9 @@
 			return (EADDRNOTAVAIL);
 		}
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK|M_ZERO);
+		       M_NOWAIT|M_ZERO);
+		if (sdl == NULL)
+			return (ENOMEM);
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
@@ -748,7 +750,9 @@
 			return (EADDRNOTAVAIL);
 		}
 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
-		       M_WAITOK|M_ZERO);
+		       M_NOWAIT|M_ZERO);
+		if (sdl == NULL)
+			return (ENOMEM);
 		sdl->sdl_len = sizeof *sdl;
 		sdl->sdl_family = AF_LINK;
 		sdl->sdl_index = ifp->if_index;
--- //depot/vendor/freebsd/src/sys/net/if_var.h	2005/07/21 22:05:31
+++ //depot/projects/netsmp/src/sys/net/if_var.h	2005/07/23 00:06:01
@@ -177,6 +177,7 @@
 	void	*if_afdata[AF_MAX];
 	int	if_afdata_initialized;
 	struct	mtx if_afdata_mtx;
+	struct	mtx if_addr_mtx;	/* mutex to protect address lists */
 	struct	task if_starttask;	/* task for IFF_NEEDSGIANT */
 	struct	task if_linktask;	/* task for link change events */
 };
@@ -217,6 +218,16 @@
 #define	if_list		if_link
 
 /*
+ * Locks for address lists on the network interface.
+ */
+#define	IF_ADDR_LOCK_INIT(if)	mtx_init(&(if)->if_addr_mtx,		\
+				    "if_addr_mtx", NULL, MTX_DEF)
+#define	IF_ADDR_LOCK_DESTROY(if)	mtx_destroy(&(if)->if_addr_mtx)
+#define	IF_ADDR_LOCK(if)	mtx_lock(&(if)->if_addr_mtx)
+#define	IF_ADDR_UNLOCK(if)	mtx_unlock(&(if)->if_addr_mtx)
+#define	IF_ADDR_LOCK_ASSERT(if)	mtx_assert(&(if)->if_addr_mtx, MA_OWNED)
+
+/*
  * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
  * are queues of messages stored on ifqueue structures
  * (defined above).  Entries are added to and deleted from these structures
--- //depot/vendor/freebsd/src/sys/net/if_vlan.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/net/if_vlan.c	2005/07/19 21:29:46
@@ -188,21 +188,27 @@
 	}
 
 	/* Now program new ones. */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
 		mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT);
-		if (mc == NULL)
+		if (mc == NULL) {
+			IF_ADDR_UNLOCK(ifp);
 			return (ENOMEM);
+		}
 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
 		    (char *)&mc->mc_addr, ETHER_ADDR_LEN);
 		SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries);
 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
 		    LLADDR(&sdl), ETHER_ADDR_LEN);
 		error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma);
-		if (error)
+		if (error) {
+			IF_ADDR_UNLOCK(ifp);
 			return (error);
+		}
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	return (0);
 }
--- //depot/vendor/freebsd/src/sys/net/rtsock.c	2005/07/15 09:51:31
+++ //depot/projects/netsmp/src/sys/net/rtsock.c	2005/07/19 21:29:46
@@ -1178,6 +1178,11 @@
 			continue;
 		ifa = ifaddr_byindex(ifp->if_index);
 		info.rti_info[RTAX_IFP] = ifa ? ifa->ifa_addr : NULL;
+
+		/*
+		 * XXXRW: Can't acquire IF_ADDR_LOCK() due to call
+	 	 * to SYSCTL_OUT().
+		 */
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (af && af != ifma->ifma_addr->sa_family)
 				continue;
--- //depot/vendor/freebsd/src/sys/netinet/igmp.c	2005/03/26 22:25:15
+++ //depot/projects/netsmp/src/sys/netinet/igmp.c	2005/07/23 00:32:37
@@ -286,6 +286,7 @@
 		 * - Use the value specified in the query message as
 		 *   the maximum timeout.
 		 */
+		IN_MULTI_LOCK();
 		IN_FIRST_MULTI(step, inm);
 		while (inm != NULL) {
 			if (inm->inm_ifp == ifp &&
@@ -301,6 +302,7 @@
 			}
 			IN_NEXT_MULTI(step, inm);
 		}
+		IN_MULTI_UNLOCK();
 
 		break;
 
@@ -343,14 +345,15 @@
 		 * If we belong to the group being reported, stop
 		 * our timer for that group.
 		 */
+		IN_MULTI_LOCK();
 		IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
-
 		if (inm != NULL) {
 			inm->inm_timer = 0;
 			++igmpstat.igps_rcv_ourreports;
 
 			inm->inm_state = IGMP_OTHERMEMBER;
 		}
+		IN_MULTI_UNLOCK();
 
 		break;
 	}
@@ -365,7 +368,8 @@
 void
 igmp_joingroup(struct in_multi *inm)
 {
-	int s = splnet();
+
+	IN_MULTI_LOCK_ASSERT();
 
 	if (inm->inm_addr.s_addr == igmp_all_hosts_group
 	    || inm->inm_ifp->if_flags & IFF_LOOPBACK) {
@@ -384,13 +388,14 @@
 		}
 		/* XXX handling of failure case? */
 	}
-	splx(s);
 }
 
 void
 igmp_leavegroup(struct in_multi *inm)
 {
 
+	IN_MULTI_LOCK_ASSERT();
+
 	if (inm->inm_state == IGMP_IREPORTEDLAST &&
 	    inm->inm_addr.s_addr != igmp_all_hosts_group &&
 	    !(inm->inm_ifp->if_flags & IFF_LOOPBACK) &&
@@ -403,7 +408,6 @@
 {
 	register struct in_multi *inm;
 	struct in_multistep step;
-	int s;
 
 	/*
 	 * Quick check to see if any work needs to be done, in order
@@ -413,7 +417,7 @@
 	if (!igmp_timers_are_running)
 		return;
 
-	s = splnet();
+	IN_MULTI_LOCK();
 	igmp_timers_are_running = 0;
 	IN_FIRST_MULTI(step, inm);
 	while (inm != NULL) {
@@ -427,13 +431,12 @@
 		}
 		IN_NEXT_MULTI(step, inm);
 	}
-	splx(s);
+	IN_MULTI_UNLOCK();
 }
 
 void
 igmp_slowtimo(void)
 {
-	int s = splnet();
 	struct router_info *rti;
 
 	IGMP_PRINTF("[igmp.c,_slowtimo] -- > entering \n");
@@ -447,7 +450,6 @@
 	}
 	mtx_unlock(&igmp_mtx);
 	IGMP_PRINTF("[igmp.c,_slowtimo] -- > exiting \n");
-	splx(s);
 }
 
 static void
@@ -458,6 +460,8 @@
 	struct ip *ip;
 	struct ip_moptions imo;
 
+	IN_MULTI_LOCK_ASSERT();
+
 	MGETHDR(m, M_DONTWAIT, MT_HEADER);
 	if (m == NULL)
 		return;
--- //depot/vendor/freebsd/src/sys/netinet/in.c	2005/06/02 00:07:10
+++ //depot/projects/netsmp/src/sys/netinet/in.c	2005/07/23 00:17:48
@@ -68,7 +68,14 @@
 SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
 	&subnetsarelocal, 0, "Treat all subnets as directly connected");
 
+/*
+ * The IPv4 multicast list (in_multihead and associated structures)
+ * are protected by the global in_multi_mtx.  See in_var.h for
+ * more details.
+ */
 struct in_multihead in_multihead; /* XXX BSS initialization */
+struct mtx in_multi_mtx;
+MTX_SYSINIT(in_multi_mtx, &in_multi_mtx, "in_multi_mtx", MTX_DEF);
 
 extern struct inpcbinfo ripcbinfo;
 extern struct inpcbinfo udbinfo;
@@ -949,8 +956,8 @@
 	int error;
 	struct sockaddr_in sin;
 	struct ifmultiaddr *ifma;
-	int s = splnet();
 
+	IN_MULTI_LOCK();
 	/*
 	 * Call generic routine to add membership or increment
 	 * refcount.  It wants addresses in the form of a sockaddr,
@@ -962,7 +969,7 @@
 	sin.sin_addr = *ap;
 	error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
 	if (error) {
-		splx(s);
+		IN_MULTI_UNLOCK();
 		return 0;
 	}
 
@@ -971,16 +978,14 @@
 	 * a new record.  Otherwise, we are done.
 	 */
 	if (ifma->ifma_protospec != NULL) {
-		splx(s);
+		IN_MULTI_UNLOCK();
 		return ifma->ifma_protospec;
 	}
 
-	/* XXX - if_addmulti uses M_WAITOK.  Can this really be called
-	   at interrupt time?  If so, need to fix if_addmulti. XXX */
 	inm = (struct in_multi *)malloc(sizeof(*inm), M_IPMADDR,
 	    M_NOWAIT | M_ZERO);
 	if (inm == NULL) {
-		splx(s);
+		IN_MULTI_UNLOCK();
 		return (NULL);
 	}
 
@@ -994,7 +999,7 @@
 	 * Let IGMP know that we have joined a new IP multicast group.
 	 */
 	igmp_joingroup(inm);
-	splx(s);
+	IN_MULTI_UNLOCK();
 	return (inm);
 }
 
@@ -1005,10 +1010,11 @@
 in_delmulti(inm)
 	register struct in_multi *inm;
 {
-	struct ifmultiaddr *ifma = inm->inm_ifma;
+	struct ifmultiaddr *ifma;
 	struct in_multi my_inm;
-	int s = splnet();
 
+	IN_MULTI_LOCK();
+	ifma = inm->inm_ifma;
 	my_inm.inm_ifp = NULL ; /* don't send the leave msg */
 	if (ifma->ifma_refcount == 1) {
 		/*
@@ -1026,5 +1032,5 @@
 	if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
 	if (my_inm.inm_ifp != NULL)
 		igmp_leavegroup(&my_inm);
-	splx(s);
+	IN_MULTI_UNLOCK();
 }
--- //depot/vendor/freebsd/src/sys/netinet/in_var.h	2005/01/07 01:52:23
+++ //depot/projects/netsmp/src/sys/netinet/in_var.h	2005/07/22 02:48:12
@@ -167,6 +167,17 @@
 extern LIST_HEAD(in_multihead, in_multi) in_multihead;
 
 /*
+ * Lock macros for IPv4 layer multicast address lists.  IPv4 lock goes
+ * before link layer multicast locks in the lock order.  In most cases,
+ * consumers of IN_*_MULTI() macros should acquire the locks before
+ * calling them; users of the in_{add,del}multi() functions should not.
+ */
+extern struct mtx in_multi_mtx;
+#define	IN_MULTI_LOCK()		mtx_lock(&in_multi_mtx)
+#define	IN_MULTI_UNLOCK()	mtx_unlock(&in_multi_mtx)
+#define	IN_MULTI_LOCK_ASSERT()	mtx_assert(&in_multi_mtx, MA_OWNED)
+
+/*
  * Structure used by macros below to remember position when stepping through
  * all of the in_multi records.
  */
@@ -177,6 +188,8 @@
 /*
  * Macro for looking up the in_multi record for a given IP multicast address
  * on a given interface.  If no matching record is found, "inm" is set null.
+ *
+ * Caller must hold IF_ADDR_LOCK().
  */
 #define IN_LOOKUP_MULTI(addr, ifp, inm) \
 	/* struct in_addr addr; */ \
@@ -185,6 +198,8 @@
 do { \
 	struct ifmultiaddr *ifma; \
 \
+	IN_MULTI_LOCK_ASSERT(); \
+	IF_ADDR_LOCK(ifp); \
 	TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) { \
 		if (ifma->ifma_addr->sa_family == AF_INET \
 		    && ((struct sockaddr_in *)ifma->ifma_addr)->sin_addr.s_addr == \
@@ -192,6 +207,7 @@
 			break; \
 	} \
 	(inm) = ifma ? ifma->ifma_protospec : 0; \
+	IF_ADDR_UNLOCK(ifp); \
 } while(0)
 
 /*
@@ -205,6 +221,7 @@
 	/* struct in_multistep  step; */ \
 	/* struct in_multi *inm; */ \
 do { \
+	IN_MULTI_LOCK_ASSERT(); \
 	if (((inm) = (step).i_inm) != NULL) \
 		(step).i_inm = LIST_NEXT((step).i_inm, inm_link); \
 } while(0)
@@ -213,6 +230,7 @@
 	/* struct in_multistep step; */ \
 	/* struct in_multi *inm; */ \
 do { \
+	IN_MULTI_LOCK_ASSERT(); \
 	(step).i_inm = LIST_FIRST(&in_multihead); \
 	IN_NEXT_MULTI((step), (inm)); \
 } while(0)
--- //depot/vendor/freebsd/src/sys/netinet/ip_input.c	2005/07/19 12:16:03
+++ //depot/projects/netsmp/src/sys/netinet/ip_input.c	2005/07/22 02:49:24
@@ -607,7 +607,9 @@
 		 * See if we belong to the destination multicast group on the
 		 * arrival interface.
 		 */
+		IN_MULTI_LOCK();
 		IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
+		IN_MULTI_UNLOCK();
 		if (inm == NULL) {
 			ipstat.ips_notmember++;
 			m_freem(m);
--- //depot/vendor/freebsd/src/sys/netinet/ip_output.c	2005/07/05 23:40:38
+++ //depot/projects/netsmp/src/sys/netinet/ip_output.c	2005/07/22 02:49:24
@@ -291,9 +291,15 @@
 				ip->ip_src = IA_SIN(ia)->sin_addr;
 		}
 
+		/*
+		 * XXXRW: Should the in_multi_mtx be held over
+		 * ip_mloopback() or ip_mforward()?
+		 */
+		IN_MULTI_LOCK();
 		IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
 		if (inm != NULL &&
 		   (imo == NULL || imo->imo_multicast_loop)) {
+			IN_MULTI_UNLOCK();
 			/*
 			 * If we belong to the destination multicast group
 			 * on the outgoing interface, and the caller did not
@@ -302,6 +308,7 @@
 			ip_mloopback(ifp, m, dst, hlen);
 		}
 		else {
+			IN_MULTI_UNLOCK();
 			/*
 			 * If we are acting as a multicast router, perform
 			 * multicast forwarding as if the packet had just
--- //depot/vendor/freebsd/src/sys/netinet6/in6_var.h	2005/02/22 13:06:15
+++ //depot/projects/netsmp/src/sys/netinet6/in6_var.h	2005/07/23 00:13:17
@@ -543,6 +543,7 @@
 /* struct in6_multi *in6m; */					\
 do { \
 	struct ifmultiaddr *ifma; \
+	IF_ADDR_LOCK(ifp); \
 	TAILQ_FOREACH(ifma, &(ifp)->if_multiaddrs, ifma_link) { \
 		if (ifma->ifma_addr->sa_family == AF_INET6 \
 		    && IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)ifma->ifma_addr)->sin6_addr, \
@@ -550,6 +551,7 @@
 			break; \
 	} \
 	(in6m) = (struct in6_multi *)(ifma ? ifma->ifma_protospec : 0); \
+	IF_ADDR_UNLOCK(ifp); \
 } while(0)
 
 /*
--- //depot/vendor/freebsd/src/sys/netinet6/mld6.c	2005/07/21 15:10:30
+++ //depot/projects/netsmp/src/sys/netinet6/mld6.c	2005/07/23 00:06:01
@@ -266,6 +266,7 @@
 		mld6_all_nodes_linklocal.s6_addr16[1] =
 			htons(ifp->if_index); /* XXX */
 
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_INET6)
 				continue;
@@ -296,6 +297,7 @@
 				}
 			}
 		}
+		IF_ADDR_UNLOCK(ifp);
 
 		if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld_addr))
 			mldh->mld_addr.s6_addr16[1] = 0; /* XXX */
--- //depot/vendor/freebsd/src/sys/pci/if_dc.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_dc.c	2005/07/19 21:29:46
@@ -1110,6 +1110,7 @@
 	else
 		DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1117,6 +1118,7 @@
 		    LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 		sp[h >> 4] |= htole32(1 << (h & 0xF));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (ifp->if_flags & IFF_BROADCAST) {
 		h = dc_mchash_le(sc, ifp->if_broadcastaddr);
@@ -1179,6 +1181,7 @@
 		return;
 
 	/* Now program new ones. */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1193,6 +1196,7 @@
 		else
 			hashes[1] |= (1 << (h - 32));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]);
 	CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]);
@@ -1250,6 +1254,7 @@
 		return;
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1259,6 +1264,7 @@
 		else
 			hashes[1] |= (1 << (h - 32));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
 	CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]);
@@ -1302,6 +1308,7 @@
 	else
 		DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1309,6 +1316,7 @@
 		    LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
 		sp[h >> 4] |= htole32(1 << (h & 0xF));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (ifp->if_flags & IFF_BROADCAST) {
 		h = dc_mchash_le(sc, ifp->if_broadcastaddr);
--- //depot/vendor/freebsd/src/sys/pci/if_de.c	2005/07/21 16:45:20
+++ //depot/projects/netsmp/src/sys/pci/if_de.c	2005/07/23 00:06:01
@@ -2968,6 +2968,7 @@
 #endif
 
     multicnt = 0;
+    IF_ADDR_LOCK(sc->tulip_ifp);
     TAILQ_FOREACH(ifma, &sc->tulip_ifp->if_multiaddrs, ifma_link) {
 
 	    if (ifma->ifma_addr->sa_family == AF_LINK)
@@ -3089,6 +3090,7 @@
 #endif
 	}
     }
+    IF_ADDR_UNLOCK(sc->tulip_ifp);
 #if defined(IFF_ALLMULTI)
     if (sc->tulip_flags & TULIP_ALLMULTI)
 	sc->tulip_ifp->if_flags |= IFF_ALLMULTI;
--- //depot/vendor/freebsd/src/sys/pci/if_pcn.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_pcn.c	2005/07/19 21:29:46
@@ -351,6 +351,7 @@
 		pcn_csr_write(sc, PCN_CSR_MAR0 + i, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -358,6 +359,7 @@
 		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
 		hashes[h >> 4] |= 1 << (h & 0xF);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	for (i = 0; i < 4; i++)
 		pcn_csr_write(sc, PCN_CSR_MAR0 + i, hashes[i]);
--- //depot/vendor/freebsd/src/sys/pci/if_rl.c	2005/06/11 01:40:36
+++ //depot/projects/netsmp/src/sys/pci/if_rl.c	2005/07/19 21:29:46
@@ -685,6 +685,7 @@
 	CSR_WRITE_4(sc, RL_MAR4, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -696,6 +697,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= RL_RXCFG_RX_MULTI;
--- //depot/vendor/freebsd/src/sys/pci/if_sf.c	2005/06/11 01:40:36
+++ //depot/projects/netsmp/src/sys/pci/if_sf.c	2005/07/19 21:29:46
@@ -431,6 +431,7 @@
 		SF_SETBIT(sc, SF_RXFILT, SF_RXFILT_ALLMULTI);
 	} else {
 		i = 1;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
@@ -449,6 +450,7 @@
 			sf_sethash(sc,
 			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr), 0);
 		}
+		IF_ADDR_UNLOCK(ifp);
 	}
 }
 
--- //depot/vendor/freebsd/src/sys/pci/if_sis.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_sis.c	2005/07/19 21:29:46
@@ -763,6 +763,7 @@
 		CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
 	}
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -775,6 +776,7 @@
 			bit -= 0x10;
 		SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave);
 
@@ -813,6 +815,7 @@
 		for (i = 0; i < n; i++)
 			hashes[i] = 0;
 		i = 0;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -821,6 +824,7 @@
 			hashes[h >> 4] |= 1 << (h & 0xf);
 			i++;
 		}
+		IF_ADDR_UNLOCK(ifp);
 		if (i > n) {
 			ctl |= SIS_RXFILTCTL_ALLMULTI;
 			for (i = 0; i < n; i++)
--- //depot/vendor/freebsd/src/sys/pci/if_sk.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_sk.c	2005/07/19 21:29:46
@@ -823,6 +823,7 @@
 		hashes[1] = 0xFFFFFFFF;
 	} else {
 		i = 1;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
@@ -855,6 +856,7 @@
 			else
 				hashes[1] |= (1 << (h - 32));
 		}
+		IF_ADDR_UNLOCK(ifp);
 	}
 
 	switch(sc->sk_type) {
--- //depot/vendor/freebsd/src/sys/pci/if_ste.c	2005/07/08 13:11:56
+++ //depot/projects/netsmp/src/sys/pci/if_ste.c	2005/07/19 21:29:46
@@ -579,6 +579,7 @@
 	CSR_WRITE_2(sc, STE_MAR3, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -589,6 +590,7 @@
 		else
 			hashes[1] |= (1 << (h - 32));
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF);
 	CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF);
--- //depot/vendor/freebsd/src/sys/pci/if_ti.c	2005/07/07 01:10:31
+++ //depot/projects/netsmp/src/sys/pci/if_ti.c	2005/07/19 21:29:46
@@ -1621,6 +1621,7 @@
 	}
 
 	/* Now program new ones. */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -1634,6 +1635,7 @@
 		SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
 		ti_add_mcast(sc, &mc->mc_addr);
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	/* Re-enable interrupts. */
 	CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
--- //depot/vendor/freebsd/src/sys/pci/if_tl.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_tl.c	2005/07/19 21:29:46
@@ -960,6 +960,7 @@
 		hashes[1] = 0xFFFFFFFF;
 	} else {
 		i = 1;
+		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH_REVERSE(ifma, &ifp->if_multiaddrs, ifmultihead, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
@@ -982,6 +983,7 @@
 			else
 				hashes[1] |= (1 << (h - 32));
 		}
+		IF_ADDR_UNLOCK(ifp);
 	}
 
 	tl_dio_write32(sc, TL_HASH1, hashes[0]);
--- //depot/vendor/freebsd/src/sys/pci/if_vr.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_vr.c	2005/07/19 21:29:46
@@ -533,6 +533,7 @@
 	CSR_WRITE_4(sc, VR_MAR1, 0);
 
 	/* Now program new ones. */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -544,6 +545,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= VR_RXCFG_RX_MULTI;
--- //depot/vendor/freebsd/src/sys/pci/if_wb.c	2005/06/10 16:51:34
+++ //depot/projects/netsmp/src/sys/pci/if_wb.c	2005/07/19 21:29:46
@@ -614,6 +614,7 @@
 	CSR_WRITE_4(sc, WB_MAR1, 0);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -625,6 +626,7 @@
 			hashes[1] |= (1 << (h - 32));
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= WB_NETCFG_RX_MULTI;
--- //depot/vendor/freebsd/src/sys/pci/if_xl.c	2005/07/13 14:10:33
+++ //depot/projects/netsmp/src/sys/pci/if_xl.c	2005/07/19 21:29:46
@@ -777,8 +777,10 @@
 		return;
 	}
 
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
 		mcnt++;
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= XL_RXFILTER_ALLMULTI;
@@ -817,6 +819,7 @@
 		CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
 
 	/* now program new ones */
+	IF_ADDR_LOCK(ifp);
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
@@ -838,6 +841,7 @@
 		    h | XL_CMD_RX_SET_HASH | XL_HASH_SET);
 		mcnt++;
 	}
+	IF_ADDR_UNLOCK(ifp);
 
 	if (mcnt)
 		rxfilt |= XL_RXFILTER_MULTIHASH;
