Index: if.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if.c,v
retrieving revision 1.209
diff -u -r1.209 if.c
--- if.c	22 Sep 2004 12:53:27 -0000	1.209
+++ if.c	16 Oct 2004 20:32:20 -0000
@@ -1122,8 +1122,11 @@
 		} else if (ifp->if_pcount == 0) {
 			ifp->if_flags &= ~IFF_PROMISC;
 		}
-		if (ifp->if_ioctl)
+		if (ifp->if_ioctl) {
+			IFF_LOCKGIANT(ifp);
 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
+			IFF_UNLOCKGIANT(ifp);
+		}
 		getmicrotime(&ifp->if_lastchange);
 		break;
 
@@ -1135,7 +1138,9 @@
 			return (EOPNOTSUPP);
 		if (ifr->ifr_reqcap & ~ifp->if_capabilities)
 			return (EINVAL);
+		IFF_LOCKGIANT(ifp);
 		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		IFF_UNLOCKGIANT(ifp);
 		if (error == 0)
 			getmicrotime(&ifp->if_lastchange);
 		break;
@@ -1207,7 +1212,9 @@
 			return (error);
 		if (ifp->if_ioctl == NULL)
 			return (EOPNOTSUPP);
+		IFF_LOCKGIANT(ifp);
 		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		IFF_UNLOCKGIANT(ifp);
 		if (error == 0)
 			getmicrotime(&ifp->if_lastchange);
 		break;
@@ -1223,7 +1230,9 @@
 			return (EINVAL);
 		if (ifp->if_ioctl == NULL)
 			return (EOPNOTSUPP);
+		IFF_LOCKGIANT(ifp);
 		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		IFF_UNLOCKGIANT(ifp);
 		if (error == 0) {
 			getmicrotime(&ifp->if_lastchange);
 			rt_ifmsg(ifp);
@@ -1276,7 +1285,9 @@
 			return (error);
 		if (ifp->if_ioctl == NULL)
 			return (EOPNOTSUPP);
+		IFF_LOCKGIANT(ifp);
 		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		IFF_UNLOCKGIANT(ifp);
 		if (error == 0)
 			getmicrotime(&ifp->if_lastchange);
 		break;
@@ -1292,7 +1303,9 @@
 	case SIOCGIFGENERIC:
 		if (ifp->if_ioctl == NULL)
 			return (EOPNOTSUPP);
+		IFF_LOCKGIANT(ifp);
 		error = (*ifp->if_ioctl)(ifp, cmd, data);
+		IFF_UNLOCKGIANT(ifp);
 		break;
 
 	case SIOCSIFLLADDR:
@@ -1459,7 +1472,9 @@
 	}
 	ifr.ifr_flags = ifp->if_flags & 0xffff;
 	ifr.ifr_flagshigh = ifp->if_flags >> 16;
+	IFF_LOCKGIANT(ifp);
 	error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+	IFF_UNLOCKGIANT(ifp);
 	if (error == 0) {
 		log(LOG_INFO, "%s: promiscuous mode %s\n",
 		    ifp->if_xname,
@@ -1585,7 +1600,9 @@
 			ifp->if_flags |= IFF_ALLMULTI;
 			ifr.ifr_flags = ifp->if_flags & 0xffff;
 			ifr.ifr_flagshigh = ifp->if_flags >> 16;
+			IFF_LOCKGIANT(ifp);
 			error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+			IFF_UNLOCKGIANT(ifp);
 		}
 	} else {
 		if (ifp->if_amcount > 1) {
@@ -1595,7 +1612,9 @@
 			ifp->if_flags &= ~IFF_ALLMULTI;
 			ifr.ifr_flags = ifp->if_flags & 0xffff;;
 			ifr.ifr_flagshigh = ifp->if_flags >> 16;
+			IFF_LOCKGIANT(ifp);
 			error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+			IFF_UNLOCKGIANT(ifp);
 		}
 	}
 	splx(s);
@@ -1690,7 +1709,9 @@
 	 * interface to let them know about it.
 	 */
 	s = splimp();
+	IFF_LOCKGIANT(ifp);
 	ifp->if_ioctl(ifp, SIOCADDMULTI, 0);
+	IFF_UNLOCKGIANT(ifp);
 	splx(s);
 
 	return 0;
@@ -1725,8 +1746,11 @@
 	 * Make sure the interface driver is notified
 	 * in the case of a link layer mcast group being left.
 	 */
-	if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0)
+	if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0) {
+		IFF_LOCKGIANT(ifp);
 		ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
+		IFF_UNLOCKGIANT(ifp);
+	}
 	splx(s);
 	free(ifma->ifma_addr, M_IFMADDR);
 	free(ifma, M_IFMADDR);
@@ -1757,7 +1781,9 @@
 
 	s = splimp();
 	TAILQ_REMOVE(&ifp->if_multiaddrs, ifma, ifma_link);
+	IFF_LOCKGIANT(ifp);
 	ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
+	IFF_UNLOCKGIANT(ifp);
 	splx(s);
 	free(ifma->ifma_addr, M_IFMADDR);
 	free(sa, M_IFMADDR);
@@ -1812,6 +1838,7 @@
 	 * address filter.
 	 */
 	if ((ifp->if_flags & IFF_UP) != 0) {
+		IFF_LOCKGIANT(ifp);
 		ifp->if_flags &= ~IFF_UP;
 		ifr.ifr_flags = ifp->if_flags & 0xffff;
 		ifr.ifr_flagshigh = ifp->if_flags >> 16;
@@ -1820,6 +1847,7 @@
 		ifr.ifr_flags = ifp->if_flags & 0xffff;
 		ifr.ifr_flagshigh = ifp->if_flags >> 16;
 		(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
+		IFF_UNLOCKGIANT(ifp);
 #ifdef INET
 		/*
 		 * Also send gratuitous ARPs to notify other nodes about
Index: if_stf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_stf.c,v
retrieving revision 1.42
diff -u -r1.42 if_stf.c
--- if_stf.c	15 Jul 2004 08:26:06 -0000	1.42
+++ if_stf.c	2 Aug 2004 00:09:24 -0000
@@ -139,13 +139,11 @@
 #define sc_ro	__sc_ro46.__sc_ro4
 	const struct encaptab *encap_cookie;
 	LIST_ENTRY(stf_softc) sc_list;	/* all stf's are linked */
+	struct mtx	sc_mtx;		/* protect sc_ro */
 };
 
 /*
  * All mutable global variables in if_stf.c are protected by stf_mtx.
- * XXXRW: Note that mutable fields in the softc are not currently locked:
- * in particular, sc_ro needs to be protected from concurrent entrance
- * of stf_output().
  */
 static struct mtx stf_mtx;
 static LIST_HEAD(, stf_softc) stf_softc_list;
@@ -231,6 +229,7 @@
 		ifc_free_unit(ifc, unit);
 		return (ENOMEM);
 	}
+	mtx_init(&sc->sc_mtx, "stf sc_mtx", NULL, MTX_DEF);
 
 	ifp->if_mtu    = IPV6_MMTU;
 	ifp->if_ioctl  = stf_ioctl;
@@ -255,6 +254,7 @@
 	bpfdetach(&sc->sc_if);
 	if_detach(&sc->sc_if);
 
+	mtx_destroy(&sc->sc_mtx);
 	free(sc, M_STF);
 }
 
@@ -430,9 +430,10 @@
 	struct ip *ip;
 	struct ip6_hdr *ip6;
 	struct in6_ifaddr *ia6;
-#ifdef MAC
+	struct route ro;
 	int error;
 
+#ifdef MAC
 	error = mac_check_ifnet_transmit(ifp, m);
 	if (error) {
 		m_freem(m);
@@ -534,9 +535,7 @@
 	else
 		ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
 
-	/*
-	 * XXXRW: Locking of sc_ro required.
-	 */
+	mtx_lock(&sc->sc_mtx);
 	dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
 	if (dst4->sin_family != AF_INET ||
 	    bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) {
@@ -555,12 +554,21 @@
 		if (sc->sc_ro.ro_rt == NULL) {
 			m_freem(m);
 			ifp->if_oerrors++;
+			mtx_unlock(&sc->sc_mtx);
 			return ENETUNREACH;
 		}
 	}
 
+	/*
+	 * XXXRW: Holding mutex over call to ip_output(): potential lock
+	 * order issue?  Hard to resolve cleanly with the current route
+	 * caching model, as we have to synchronize access to shared softc
+	 * state.
+	 */
 	ifp->if_opackets++;
-	return ip_output(m, NULL, &sc->sc_ro, 0, NULL, NULL);
+	error = ip_output(m, NULL, &ro, 0, NULL, NULL);
+	mtx_unlock(&sc->sc_mtx);
+	return (error);
 }
 
 static int
Index: if_var.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_var.h,v
retrieving revision 1.84
diff -u -r1.84 if_var.h
--- if_var.h	15 Aug 2004 06:24:42 -0000	1.84
+++ if_var.h	16 Oct 2004 20:31:54 -0000
@@ -327,6 +327,16 @@
 #define	IF_AFDATA_UNLOCK(ifp)	mtx_unlock(&(ifp)->if_afdata_mtx)
 #define	IF_AFDATA_DESTROY(ifp)	mtx_destroy(&(ifp)->if_afdata_mtx)
 
+#define	IFF_LOCKGIANT(ifp) do {						\
+	if ((ifp)->if_flags & IFF_NEEDSGIANT)				\
+		mtx_lock(&Giant);					\
+} while (0)
+
+#define	IFF_UNLOCKGIANT(ifp) do {					\
+	if ((ifp)->if_flags & IFF_NEEDSGIANT)				\
+		mtx_unlock(&Giant);					\
+} while (0)
+
 #define	IF_HANDOFF(ifq, m, ifp)			\
 	if_handoff((struct ifqueue *)ifq, m, ifp, 0)
 #define	IF_HANDOFF_ADJ(ifq, m, ifp, adj)	\
