Add a new global rwlock, in_ifaddr_lock, which will synchronize use of the
in_ifaddrhead and INADDR_HASH address lists.  Previously, these lists were
used unsynchronized as they were effectively never changed in steady state,
but we've seen increasing reports of writer-writer races on very busy VPN
servers (and similar configurations.

For the time being, use rwlocks rather than rmlocks in order to take
advantage of their better lock debugging support.  As a result, don't
enable ip_input()'s read-locking of INADDR_HASH until the rmlock conversion
is complete and performance analysis has been done.

MFC after:	6 weeks

Index: nfsclient/nfs_vnops.c
===================================================================
--- nfsclient/nfs_vnops.c	(revision 194940)
+++ nfsclient/nfs_vnops.c	(working copy)
@@ -1553,11 +1553,15 @@
 			tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF);
 #ifdef INET
 			INIT_VNET_INET(curvnet);
+			IN_IFADDR_RLOCK();
 			if (!TAILQ_EMPTY(&V_in_ifaddrhead))
 				*tl++ = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
 			else
 #endif
 				*tl++ = create_verf;
+#ifdef INET
+			IN_IFADDR_RUNLOCK();
+#endif
 			*tl = ++create_verf;
 		} else {
 			*tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
Index: netinet/in.c
===================================================================
--- netinet/in.c	(revision 194940)
+++ netinet/in.c	(working copy)
@@ -100,15 +100,23 @@
 	register u_long i = ntohl(in.s_addr);
 	register struct in_ifaddr *ia;
 
+	IN_IFADDR_RLOCK();
 	if (V_subnetsarelocal) {
-		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
-			if ((i & ia->ia_netmask) == ia->ia_net)
+		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+			if ((i & ia->ia_netmask) == ia->ia_net) {
+				IN_IFADDR_RUNLOCK();
 				return (1);
+			}
+		}
 	} else {
-		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
-			if ((i & ia->ia_subnetmask) == ia->ia_subnet)
+		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
+			if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
+				IN_IFADDR_RUNLOCK();
 				return (1);
+			}
+		}
 	}
+	IN_IFADDR_RUNLOCK();
 	return (0);
 }
 
@@ -122,10 +130,14 @@
 	INIT_VNET_INET(curvnet);
 	struct in_ifaddr *ia;
 
+	IN_IFADDR_RLOCK();
 	LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
-		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr)
+		if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
+			IN_IFADDR_RUNLOCK();
 			return (1);
+		}
 	}
+	IN_IFADDR_RUNLOCK();
 	return (0);
 }
 
@@ -222,7 +234,7 @@
 	struct in_ifinfo *ii;
 	struct in_aliasreq *ifra = (struct in_aliasreq *)data;
 	struct sockaddr_in oldaddr;
-	int error, hostIsNew, iaIsNew, maskIsNew, s;
+	int error, hostIsNew, iaIsNew, maskIsNew;
 	int iaIsFirst;
 
 	ia = NULL;
@@ -313,6 +325,7 @@
 	 * first one on the interface, if possible.
 	 */
 	dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+	IN_IFADDR_RLOCK();
 	LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) {
 		if (iap->ia_ifp == ifp &&
 		    iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
@@ -324,6 +337,7 @@
 	}
 	if (ia != NULL)
 		ifa_ref(&ia->ia_ifa);
+	IN_IFADDR_RUNLOCK();
 	if (ia == NULL) {
 		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
@@ -351,6 +365,7 @@
 		if (ifra->ifra_addr.sin_family == AF_INET) {
 			struct in_ifaddr *oia;
 
+			IN_IFADDR_RLOCK();
 			for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) {
 				if (ia->ia_ifp == ifp  &&
 				    ia->ia_addr.sin_addr.s_addr ==
@@ -361,6 +376,7 @@
 				ifa_ref(&ia->ia_ifa);
 			if (oia != NULL && ia != oia)
 				ifa_free(&oia->ia_ifa);
+			IN_IFADDR_RUNLOCK();
 			if ((ifp->if_flags & IFF_POINTOPOINT)
 			    && (cmd == SIOCAIFADDR)
 			    && (ifra->ifra_dstaddr.sin_addr.s_addr
@@ -405,9 +421,9 @@
 			TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
 			IF_ADDR_UNLOCK(ifp);
 			ifa_ref(ifa);			/* in_ifaddrhead */
-			s = splnet();
+			IN_IFADDR_WLOCK();
 			TAILQ_INSERT_TAIL(&V_in_ifaddrhead, ia, ia_link);
-			splx(s);
+			IN_IFADDR_WUNLOCK();
 			iaIsNew = 1;
 		}
 		break;
@@ -578,13 +594,14 @@
 	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
 	IF_ADDR_UNLOCK(ifp);
 	ifa_free(&ia->ia_ifa);				/* if_addrhead */
-	s = splnet();
+
+	IN_IFADDR_WLOCK();
 	TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
-	ifa_free(&ia->ia_ifa);				/* in_ifaddrhead */
 	if (ia->ia_addr.sin_family == AF_INET) {
 		struct in_ifaddr *if_ia;
 
 		LIST_REMOVE(ia, ia_hash);
+		IN_IFADDR_WUNLOCK();
 		/*
 		 * If this is the last IPv4 address configured on this
 		 * interface, leave the all-hosts group.
@@ -603,8 +620,9 @@
 			IN_MULTI_UNLOCK();
 		} else
 			ifa_free(&if_ia->ia_ifa);
-	}
-	splx(s);
+	} else
+		IN_IFADDR_WUNLOCK();
+	ifa_free(&ia->ia_ifa);				/* in_ifaddrhead */
 out:
 	if (ia != NULL)
 		ifa_free(&ia->ia_ifa);
@@ -811,9 +829,12 @@
 	if (oldaddr.sin_family == AF_INET)
 		LIST_REMOVE(ia, ia_hash);
 	ia->ia_addr = *sin;
-	if (ia->ia_addr.sin_family == AF_INET)
+	if (ia->ia_addr.sin_family == AF_INET) {
+		IN_IFADDR_WLOCK();
 		LIST_INSERT_HEAD(INADDR_HASH(ia->ia_addr.sin_addr.s_addr),
 		    ia, ia_hash);
+		IN_IFADDR_WUNLOCK();
+	}
 	/*
 	 * Give the interface a chance to initialize
 	 * if this is its first address,
@@ -825,6 +846,7 @@
 			splx(s);
 			/* LIST_REMOVE(ia, ia_hash) is done in in_control */
 			ia->ia_addr = oldaddr;
+			IN_IFADDR_WLOCK();
 			if (ia->ia_addr.sin_family == AF_INET)
 				LIST_INSERT_HEAD(INADDR_HASH(
 				    ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
@@ -836,6 +858,7 @@
 				 * with bogus ia entries in hash
 				 */
 				LIST_REMOVE(ia, ia_hash);
+			IN_IFADDR_WUNLOCK();
 			return (error);
 		}
 	}
@@ -943,6 +966,7 @@
 		prefix.s_addr &= mask.s_addr;
 	}
 
+	IN_IFADDR_RLOCK();
 	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 		if (rtinitflags(ia)) {
 			p = ia->ia_addr.sin_addr;
@@ -966,12 +990,16 @@
 		if (ia->ia_flags & IFA_ROUTE) {
 			if (V_sameprefixcarponly &&
 			    target->ia_ifp->if_type != IFT_CARP &&
-			    ia->ia_ifp->if_type != IFT_CARP)
+			    ia->ia_ifp->if_type != IFT_CARP) {
+				IN_IFADDR_RUNLOCK();
 				return (EEXIST);
-			else
+			} else {
+				IN_IFADDR_RUNLOCK();
 				return (0);
+			}
 		}
 	}
+	IN_IFADDR_RUNLOCK();
 
 	/*
 	 * No-one seem to have this prefix route, so we try to insert it.
@@ -1031,6 +1059,7 @@
 		arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
 	}
 
+	IN_IFADDR_RLOCK();
 	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 		if (rtinitflags(ia))
 			p = ia->ia_dstaddr.sin_addr;
@@ -1054,6 +1083,7 @@
 		    && (ia->ia_ifp->if_type != IFT_CARP)
 #endif
 							) {
+			IN_IFADDR_RUNLOCK();
 			rtinit(&(target->ia_ifa), (int)RTM_DELETE,
 			    rtinitflags(target));
 			target->ia_flags &= ~IFA_ROUTE;
@@ -1065,6 +1095,7 @@
 			return (error);
 		}
 	}
+	IN_IFADDR_RUNLOCK();
 
 	/*
 	 * remove all L2 entries on the given prefix
Index: netinet/ip_carp.c
===================================================================
--- netinet/ip_carp.c	(revision 194940)
+++ netinet/ip_carp.c	(working copy)
@@ -1500,6 +1500,7 @@
 
 	/* we have to do it by hands to check we won't match on us */
 	ia_if = NULL; own = 0;
+	IN_IFADDR_RLOCK();
 	TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 		/* and, yeah, we need a multicast-capable iface too */
 		if (ia->ia_ifp != SC2IFP(sc) &&
@@ -1513,20 +1514,30 @@
 		}
 	}
 
-	if (!ia_if)
+	if (!ia_if) {
+		IN_IFADDR_RUNLOCK();
 		return (EADDRNOTAVAIL);
+	}
 
 	ia = ia_if;
+	ifa_ref(&ia->ia_ifa);
+	IN_IFADDR_RUNLOCK();
+
 	ifp = ia->ia_ifp;
 
 	if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0 ||
-	    (imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp))
+	    (imo->imo_multicast_ifp && imo->imo_multicast_ifp != ifp)) {
+		ifa_free(&ia->ia_ifa);
 		return (EADDRNOTAVAIL);
+	}
 
 	if (imo->imo_num_memberships == 0) {
 		addr.s_addr = htonl(INADDR_CARP_GROUP);
-		if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) == NULL)
+		if ((imo->imo_membership[0] = in_addmulti(&addr, ifp)) ==
+		    NULL) {
+			ifa_free(&ia->ia_ifa);
 			return (ENOBUFS);
+		}
 		imo->imo_num_memberships++;
 		imo->imo_multicast_ifp = ifp;
 		imo->imo_multicast_ttl = CARP_DFLTTL;
@@ -1601,11 +1612,13 @@
 	carp_setrun(sc, 0);
 
 	CARP_UNLOCK(cif);
+	ifa_free(&ia->ia_ifa);	/* XXXRW: should hold reference for softc. */
 
 	return (0);
 
 cleanup:
 	in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
+	ifa_free(&ia->ia_ifa);
 	return (error);
 }
 
Index: netinet/raw_ip.c
===================================================================
--- netinet/raw_ip.c	(revision 194940)
+++ netinet/raw_ip.c	(working copy)
@@ -678,9 +678,12 @@
 
 	switch (cmd) {
 	case PRC_IFDOWN:
+		IN_IFADDR_RLOCK();
 		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 			if (ia->ia_ifa.ifa_addr == sa
 			    && (ia->ia_flags & IFA_ROUTE)) {
+				ifa_ref(&ia->ia_ifa);
+				IN_IFADDR_RUNLOCK();
 				/*
 				 * in_ifscrub kills the interface route.
 				 */
@@ -692,18 +695,26 @@
 				 * routing process they will come back.
 				 */
 				in_ifadown(&ia->ia_ifa, 0);
+				ifa_free(&ia->ia_ifa);
 				break;
 			}
 		}
+		if (ia == NULL)		/* If ia matched, already unlocked. */
+			IN_IFADDR_RUNLOCK();
 		break;
 
 	case PRC_IFUP:
+		IN_IFADDR_RLOCK();
 		TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 			if (ia->ia_ifa.ifa_addr == sa)
 				break;
 		}
-		if (ia == 0 || (ia->ia_flags & IFA_ROUTE))
+		if (ia == 0 || (ia->ia_flags & IFA_ROUTE)) {
+			IN_IFADDR_RUNLOCK();
 			return;
+		}
+		ifa_ref(&ia->ia_ifa);
+		IN_IFADDR_RUNLOCK();
 		flags = RTF_UP;
 		ifp = ia->ia_ifa.ifa_ifp;
 
@@ -714,6 +725,7 @@
 		err = rtinit(&ia->ia_ifa, RTM_ADD, flags);
 		if (err == 0)
 			ia->ia_flags |= IFA_ROUTE;
+		ifa_free(&ia->ia_ifa);
 		break;
 	}
 }
Index: netinet/in_pcb.c
===================================================================
--- netinet/in_pcb.c	(revision 194940)
+++ netinet/in_pcb.c	(working copy)
@@ -813,16 +813,21 @@
 		 * choose the broadcast address for that interface.
 		 */
 		if (faddr.s_addr == INADDR_ANY) {
+			IN_IFADDR_RLOCK();
 			faddr =
 			    IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
+			IN_IFADDR_RUNLOCK();
 			if (cred != NULL &&
 			    (error = prison_get_ip4(cred, &faddr)) != 0)
 				return (error);
-		} else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
-		    (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
-		    IFF_BROADCAST))
-			faddr = satosin(&TAILQ_FIRST(
-			    &V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
+		} else if (faddr.s_addr == (u_long)INADDR_BROADCAST) {
+			IN_IFADDR_RLOCK();
+			if (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
+			    IFF_BROADCAST)
+				faddr = satosin(&TAILQ_FIRST(
+				    &V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
+			IN_IFADDR_RUNLOCK();
+		}
 	}
 	if (laddr.s_addr == INADDR_ANY) {
 		error = in_pcbladdr(inp, &faddr, &laddr, cred);
@@ -842,12 +847,16 @@
 			imo = inp->inp_moptions;
 			if (imo->imo_multicast_ifp != NULL) {
 				ifp = imo->imo_multicast_ifp;
+				IN_IFADDR_RLOCK();
 				TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link)
 					if (ia->ia_ifp == ifp)
 						break;
-				if (ia == NULL)
+				if (ia == NULL) {
+					IN_IFADDR_RUNLOCK();
 					return (EADDRNOTAVAIL);
+				}
 				laddr = ia->ia_addr.sin_addr;
+				IN_IFADDR_RUNLOCK();
 			}
 		}
 	}
Index: netinet/in_mcast.c
===================================================================
--- netinet/in_mcast.c	(revision 194940)
+++ netinet/in_mcast.c	(working copy)
@@ -1834,6 +1834,7 @@
 			struct ifnet *mifp;
 
 			mifp = NULL;
+			IN_IFADDR_RLOCK();
 			TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
 				mifp = ia->ia_ifp;
 				if (!(mifp->if_flags & IFF_LOOPBACK) &&
@@ -1842,6 +1843,7 @@
 					break;
 				}
 			}
+			IN_IFADDR_RUNLOCK();
 		}
 	}
 
Index: netinet/ip_input.c
===================================================================
--- netinet/ip_input.c	(revision 194940)
+++ netinet/ip_input.c	(working copy)
@@ -117,6 +117,7 @@
 int	ipstealth;
 static int	nipq;	/* Total # of reass queues */
 #endif
+struct	rwlock in_ifaddr_lock;
 
 SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_ip, IPCTL_FORWARDING,
     forwarding, CTLFLAG_RW, ipforwarding, 0,
@@ -325,6 +326,7 @@
 
 	TAILQ_INIT(&V_in_ifaddrhead);
 	V_in_ifaddrhashtbl = hashinit(INADDR_NHASH, M_IFADDR, &V_in_ifaddrhmask);
+	IN_IFADDR_LOCK_INIT();
 
 	/* Initialize IP reassembly queue. */
 	for (i = 0; i < IPREASS_NHASH; i++)
@@ -615,6 +617,7 @@
 	/*
 	 * Check for exact addresses in the hash bucket.
 	 */
+	/* IN_IFADDR_RLOCK(); */
 	LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
 		/*
 		 * If the address matches, verify that the packet
@@ -624,9 +627,12 @@
 		if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr && 
 		    (!checkif || ia->ia_ifp == ifp)) {
 			ifa_ref(&ia->ia_ifa);
+			/* IN_IFADDR_RUNLOCK(); */
 			goto ours;
 		}
 	}
+	/* IN_IFADDR_RUNLOCK(); */
+
 	/*
 	 * Check for broadcast addresses.
 	 *
Index: netinet/in_gif.c
===================================================================
--- netinet/in_gif.c	(revision 194940)
+++ netinet/in_gif.c	(working copy)
@@ -387,13 +387,19 @@
 	case 0: case 127: case 255:
 		return 0;
 	}
+
 	/* reject packets with broadcast on source */
+	/* XXXRW: should use hash lists? */
+	IN_IFADDR_RLOCK();
 	TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) {
 		if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
 			continue;
-		if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
+		if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
+			IN_IFADDR_RUNLOCK();
 			return 0;
+		}
 	}
+	IN_IFADDR_RUNLOCK();
 
 	/* ingress filters on outer source */
 	if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
Index: netinet/ip_icmp.c
===================================================================
--- netinet/ip_icmp.c	(revision 194940)
+++ netinet/ip_icmp.c	(working copy)
@@ -675,12 +675,16 @@
 	 * If the incoming packet was addressed directly to one of our
 	 * own addresses, use dst as the src for the reply.
 	 */
+	IN_IFADDR_RLOCK();
 	LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) {
 		if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) {
 			t = IA_SIN(ia)->sin_addr;
+			IN_IFADDR_RUNLOCK();
 			goto match;
 		}
 	}
+	IN_IFADDR_RUNLOCK();
+
 	/*
 	 * If the incoming packet was addressed to one of our broadcast
 	 * addresses, use the first non-broadcast address which corresponds
Index: netinet/in_var.h
===================================================================
--- netinet/in_var.h	(revision 194940)
+++ netinet/in_var.h	(working copy)
@@ -114,6 +114,17 @@
 #define INADDR_HASH(x) \
 	(&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask])
 
+extern	struct rwlock in_ifaddr_lock;
+
+#define	IN_IFADDR_LOCK_INIT()	rw_init(&in_ifaddr_lock, "in_ifaddr_lock")
+#define	IN_IFADDR_LOCK_ASSERT()	rw_assert(&in_ifaddr_lock, RA_LOCKED)
+#define	IN_IFADDR_RLOCK()	rw_rlock(&in_ifaddr_lock)
+#define	IN_IFADDR_RLOCK_ASSERT()	rw_assert(&in_ifaddr_lock, RA_RLOCKED)
+#define	IN_IFADDR_RUNLOCK()	rw_runlock(&in_ifaddr_lock)
+#define	IN_IFADDR_WLOCK()	rw_wlock(&in_ifaddr_lock)
+#define	IN_IFADDR_WLOCK_ASSERT()	rw_assert(&in_ifaddr_lock, RA_WLOCKED)
+#define	IN_IFADDR_WUNLOCK()	rw_wunlock(&in_ifaddr_lock)
+
 /*
  * Macro for finding the internet address structure (in_ifaddr)
  * corresponding to one of our IP addresses (in_addr).
Index: netinet/if_ether.c
===================================================================
--- netinet/if_ether.c	(revision 194940)
+++ netinet/if_ether.c	(working copy)
@@ -509,11 +509,13 @@
 	 * request for the virtual host ip.
 	 * XXX: This is really ugly!
 	 */
+	IN_IFADDR_RLOCK();
 	LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
 		if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
 		    ia->ia_ifp == ifp) &&
 		    itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
 			ifa_ref(&ia->ia_ifa);
+			IN_IFADDR_RUNLOCK();
 			goto match;
 		}
 #ifdef DEV_CARP
@@ -522,6 +524,7 @@
 		    itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
 			carp_match = 1;
 			ifa_ref(&ia->ia_ifa);
+			IN_IFADDR_RUNLOCK();
 			goto match;
 		}
 #endif
@@ -531,6 +534,7 @@
 		    ia->ia_ifp == ifp) &&
 		    isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
 			ifa_ref(&ia->ia_ifa);
+			IN_IFADDR_RUNLOCK();
 			goto match;
 		}
 
@@ -549,11 +553,13 @@
 			if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
 				ifa_ref(&ia->ia_ifa);
 				ifp = ia->ia_ifp;
+				IN_IFADDR_RUNLOCK();
 				goto match;
 			}
 		}
 	}
 #undef BDG_MEMBER_MATCHES_ARP
+	IN_IFADDR_RUNLOCK();
 
 	/*
 	 * No match, use the first inet address on the receive interface
@@ -572,9 +578,13 @@
 	/*
 	 * If bridging, fall back to using any inet address.
 	 */
-	if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL)
+	IN_IFADDR_RLOCK();
+	if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) {
+		IN_IFADDR_RUNLOCK();
 		goto drop;
+	}
 	ifa_ref(&ia->ia_ifa);
+	IN_IFADDR_RUNLOCK();
 match:
 	if (!enaddr)
 		enaddr = (u_int8_t *)IF_LLADDR(ifp);
Index: fs/nfsclient/nfs_clvnops.c
===================================================================
--- fs/nfsclient/nfs_clvnops.c	(revision 194940)
+++ fs/nfsclient/nfs_clvnops.c	(working copy)
@@ -1400,11 +1400,15 @@
 	CURVNET_SET(P_TO_VNET(&proc0));
 #ifdef INET
 	INIT_VNET_INET(curvnet);
+	IN_IFADDR_RLOCK();
 	if (!TAILQ_EMPTY(&V_in_ifaddrhead))
 		cverf.lval[0] = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr.s_addr;
 	else
 #endif
 		cverf.lval[0] = create_verf;
+#ifdef INET
+	IN_IFADDR_RUNLOCK();
+#endif
 	cverf.lval[1] = ++create_verf;
 	CURVNET_RESTORE();
 	error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen,
Index: net/if_stf.c
===================================================================
--- net/if_stf.c	(revision 194940)
+++ net/if_stf.c	(working copy)
@@ -620,15 +620,19 @@
 	/*
 	 * reject packets with broadcast
 	 */
+	IN_IFADDR_RLOCK();
 	for (ia4 = TAILQ_FIRST(&V_in_ifaddrhead);
 	     ia4;
 	     ia4 = TAILQ_NEXT(ia4, ia_link))
 	{
 		if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
 			continue;
-		if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
+		if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
+			IN_IFADDR_RUNLOCK();
 			return -1;
+		}
 	}
+	IN_IFADDR_RUNLOCK();
 
 	/*
 	 * perform ingress filter
Index: net/if_spppsubr.c
===================================================================
--- net/if_spppsubr.c	(revision 194940)
+++ net/if_spppsubr.c	(working copy)
@@ -4973,8 +4973,10 @@
 		/* set new address */
 		si->sin_addr.s_addr = htonl(src);
 		ia = ifatoia(ifa);
+		IN_IFADDR_WLOCK();
 		LIST_REMOVE(ia, ia_hash);
 		LIST_INSERT_HEAD(INADDR_HASH(si->sin_addr.s_addr), ia, ia_hash);
+		IN_IFADDR_WUNLOCK();
 
 		/* add new route */
 		error = rtinit(ifa, (int)RTM_ADD, RTF_HOST);
Index: netipsec/key.c
===================================================================
--- netipsec/key.c	(revision 194940)
+++ netipsec/key.c	(working copy)
@@ -3939,6 +3939,7 @@
 #ifdef INET
 	case AF_INET:
 		sin = (struct sockaddr_in *)sa;
+		IN_IFADDR_RLOCK();
 		for (ia = V_in_ifaddrhead.tqh_first; ia;
 		     ia = ia->ia_link.tqe_next)
 		{
@@ -3946,9 +3947,11 @@
 			    sin->sin_len == ia->ia_addr.sin_len &&
 			    sin->sin_addr.s_addr == ia->ia_addr.sin_addr.s_addr)
 			{
+				IN_IFADDR_RUNLOCK();
 				return 1;
 			}
 		}
+		IN_IFADDR_RUNLOCK();
 		break;
 #endif
 #ifdef INET6
