Module Name: src Committed By: ozaki-r Date: Thu May 12 02:24:17 UTC 2016
Modified Files: src/sys/altq: altq_subr.c src/sys/arch/x86/x86: vmt.c src/sys/compat/common: uipc_syscalls_40.c src/sys/compat/linux/common: linux_socket.c src/sys/compat/linux32/common: linux32_socket.c src/sys/compat/svr4: svr4_sockio.c src/sys/compat/svr4_32: svr4_32_sockio.c src/sys/dev/pci: if_bge.c src/sys/dist/pf/net: pf_if.c src/sys/kern: kern_subr.c subr_tftproot.c uipc_mbuf.c src/sys/net: if.c if.h rtsock.c src/sys/net/npf: npf_if.c src/sys/netinet: ip_carp.c raw_ip.c sctp_asconf.c sctp_output.c sctp_pcb.c sctp_usrreq.c sctputil.c src/sys/netinet6: icmp6.c in6.c in6_ifattach.c nd6.c raw_ip6.c src/sys/netipsec: xform_ipip.c src/sys/rump/librump/rumpnet: net_stub.c Log Message: Protect ifnet list with psz and psref The change ensures that ifnet objects in the ifnet list aren't freed during list iterations by using pserialize(9) and psref(9). Note that the change adds a pslist(9) for ifnet but doesn't remove the original ifnet list (ifnet_list) to avoid breaking kvm(3) users. We shouldn't use the original list in the kernel anymore. To generate a diff of this commit: cvs rdiff -u -r1.30 -r1.31 src/sys/altq/altq_subr.c cvs rdiff -u -r1.11 -r1.12 src/sys/arch/x86/x86/vmt.c cvs rdiff -u -r1.8 -r1.9 src/sys/compat/common/uipc_syscalls_40.c cvs rdiff -u -r1.126 -r1.127 src/sys/compat/linux/common/linux_socket.c cvs rdiff -u -r1.20 -r1.21 src/sys/compat/linux32/common/linux32_socket.c cvs rdiff -u -r1.36 -r1.37 src/sys/compat/svr4/svr4_sockio.c cvs rdiff -u -r1.21 -r1.22 src/sys/compat/svr4_32/svr4_32_sockio.c cvs rdiff -u -r1.295 -r1.296 src/sys/dev/pci/if_bge.c cvs rdiff -u -r1.26 -r1.27 src/sys/dist/pf/net/pf_if.c cvs rdiff -u -r1.216 -r1.217 src/sys/kern/kern_subr.c cvs rdiff -u -r1.16 -r1.17 src/sys/kern/subr_tftproot.c cvs rdiff -u -r1.164 -r1.165 src/sys/kern/uipc_mbuf.c cvs rdiff -u -r1.333 -r1.334 src/sys/net/if.c cvs rdiff -u -r1.203 -r1.204 src/sys/net/if.h cvs rdiff -u -r1.185 -r1.186 src/sys/net/rtsock.c cvs rdiff -u -r1.5 -r1.6 src/sys/net/npf/npf_if.c cvs rdiff -u -r1.64 -r1.65 src/sys/netinet/ip_carp.c cvs rdiff -u -r1.157 -r1.158 src/sys/netinet/raw_ip.c cvs rdiff -u -r1.2 -r1.3 src/sys/netinet/sctp_asconf.c cvs rdiff -u -r1.3 -r1.4 src/sys/netinet/sctp_output.c cvs rdiff -u -r1.4 -r1.5 src/sys/netinet/sctp_pcb.c \ src/sys/netinet/sctp_usrreq.c cvs rdiff -u -r1.6 -r1.7 src/sys/netinet/sctputil.c cvs rdiff -u -r1.182 -r1.183 src/sys/netinet6/icmp6.c cvs rdiff -u -r1.198 -r1.199 src/sys/netinet6/in6.c cvs rdiff -u -r1.97 -r1.98 src/sys/netinet6/in6_ifattach.c cvs rdiff -u -r1.193 -r1.194 src/sys/netinet6/nd6.c cvs rdiff -u -r1.142 -r1.143 src/sys/netinet6/raw_ip6.c cvs rdiff -u -r1.37 -r1.38 src/sys/netipsec/xform_ipip.c cvs rdiff -u -r1.22 -r1.23 src/sys/rump/librump/rumpnet/net_stub.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/altq/altq_subr.c diff -u src/sys/altq/altq_subr.c:1.30 src/sys/altq/altq_subr.c:1.31 --- src/sys/altq/altq_subr.c:1.30 Wed Apr 20 08:58:48 2016 +++ src/sys/altq/altq_subr.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: altq_subr.c,v 1.30 2016/04/20 08:58:48 knakahara Exp $ */ +/* $NetBSD: altq_subr.c,v 1.31 2016/05/12 02:24:16 ozaki-r Exp $ */ /* $KAME: altq_subr.c,v 1.24 2005/04/13 03:44:25 suz Exp $ */ /* @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.30 2016/04/20 08:58:48 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.31 2016/05/12 02:24:16 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_altq.h" @@ -355,15 +355,26 @@ tbr_timeout(void *arg) int active, s; active = 0; - s = splnet(); - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + struct psref psref; if (!TBR_IS_ENABLED(&ifp->if_snd)) continue; + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + active++; - if (!IFQ_IS_EMPTY(&ifp->if_snd) && ifp->if_start != NULL) + if (!IFQ_IS_EMPTY(&ifp->if_snd) && ifp->if_start != NULL) { + int _s = splnet(); (*ifp->if_start)(ifp); + splx(_s); + } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } - splx(s); + pserialize_read_exit(s); + if (active > 0) CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0); else Index: src/sys/arch/x86/x86/vmt.c diff -u src/sys/arch/x86/x86/vmt.c:1.11 src/sys/arch/x86/x86/vmt.c:1.12 --- src/sys/arch/x86/x86/vmt.c:1.11 Thu Apr 23 23:23:00 2015 +++ src/sys/arch/x86/x86/vmt.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: vmt.c,v 1.11 2015/04/23 23:23:00 pgoyette Exp $ */ +/* $NetBSD: vmt.c,v 1.12 2016/05/12 02:24:16 ozaki-r Exp $ */ /* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */ /* @@ -803,10 +803,12 @@ vmt_tclo_tick(void *xarg) } else if (strcmp(sc->sc_rpc_buf, "Set_Option broadcastIP 1") == 0) { struct ifnet *iface; struct sockaddr_in *guest_ip; + int s; /* find first available ipv4 address */ guest_ip = NULL; - IFNET_FOREACH(iface) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(iface) { struct ifaddr *iface_addr; /* skip loopback */ @@ -824,6 +826,7 @@ vmt_tclo_tick(void *xarg) break; } } + pserialize_read_exit(s); if (guest_ip != NULL) { if (vm_rpc_send_rpci_tx(sc, "info-set guestinfo.ip %s", Index: src/sys/compat/common/uipc_syscalls_40.c diff -u src/sys/compat/common/uipc_syscalls_40.c:1.8 src/sys/compat/common/uipc_syscalls_40.c:1.9 --- src/sys/compat/common/uipc_syscalls_40.c:1.8 Wed Nov 26 09:53:53 2014 +++ src/sys/compat/common/uipc_syscalls_40.c Thu May 12 02:24:16 2016 @@ -1,9 +1,9 @@ -/* $NetBSD: uipc_syscalls_40.c,v 1.8 2014/11/26 09:53:53 ozaki-r Exp $ */ +/* $NetBSD: uipc_syscalls_40.c,v 1.9 2016/05/12 02:24:16 ozaki-r Exp $ */ /* written by Pavel Cahyna, 2006. Public domain. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.8 2014/11/26 09:53:53 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.9 2016/05/12 02:24:16 ozaki-r Exp $"); /* * System call interface to the socket abstraction. @@ -39,23 +39,33 @@ compat_ifconf(u_long cmd, void *data) int space = 0, error = 0; const int sz = (int)sizeof(ifr); const bool docopy = ifc->ifc_req != NULL; + int s; + int bound = curlwp->l_pflag & LP_BOUND; + struct psref psref; if (docopy) { space = ifc->ifc_len; ifrp = ifc->ifc_req; } - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); - if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') - return ENAMETOOLONG; + if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { + error = ENAMETOOLONG; + goto release_exit; + } if (IFADDR_EMPTY(ifp)) { memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) - return (error); + goto release_exit; ifrp++; } space -= sizeof(ifr); @@ -103,14 +113,25 @@ compat_ifconf(u_long cmd, void *data) } } if (error != 0) - return (error); + goto release_exit; space -= sz; } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; + if (docopy) ifc->ifc_len -= space; else ifc->ifc_len = -space; return (0); + +release_exit: + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return error; } #endif Index: src/sys/compat/linux/common/linux_socket.c diff -u src/sys/compat/linux/common/linux_socket.c:1.126 src/sys/compat/linux/common/linux_socket.c:1.127 --- src/sys/compat/linux/common/linux_socket.c:1.126 Fri Jul 24 13:02:52 2015 +++ src/sys/compat/linux/common/linux_socket.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.c,v 1.126 2015/07/24 13:02:52 maxv Exp $ */ +/* $NetBSD: linux_socket.c,v 1.127 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.126 2015/07/24 13:02:52 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.127 2016/05/12 02:24:16 ozaki-r Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -1118,6 +1118,9 @@ linux_getifconf(struct lwp *l, register_ int space = 0, error; const int sz = (int)sizeof(ifr); bool docopy; + int s; + int bound = curlwp->l_pflag & LP_BOUND; + struct psref psref; error = copyin(data, &ifc, sizeof(ifc)); if (error) @@ -1129,11 +1132,18 @@ linux_getifconf(struct lwp *l, register_ ifrp = ifc.ifc_req; } - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); - if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') - return ENAMETOOLONG; + if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { + error = ENAMETOOLONG; + goto release_exit; + } if (IFADDR_EMPTY(ifp)) continue; IFADDR_FOREACH(ifa, ifp) { @@ -1147,12 +1157,17 @@ linux_getifconf(struct lwp *l, register_ if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) - return error; + goto release_exit; ifrp++; } space -= sz; } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; if (docopy) ifc.ifc_len -= space; @@ -1160,6 +1175,11 @@ linux_getifconf(struct lwp *l, register_ ifc.ifc_len = -space; return copyout(&ifc, data, sizeof(ifc)); + +release_exit: + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return error; } int @@ -1174,6 +1194,7 @@ linux_getifhwaddr(struct lwp *l, registe struct sockaddr_dl *sadl; int error, found; int index, ifnum; + int s; /* * We can't emulate this ioctl by calling sys_ioctl() to run @@ -1205,14 +1226,17 @@ linux_getifhwaddr(struct lwp *l, registe * Try real interface name first, then fake "ethX" */ found = 0; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (found) break; if (strcmp(lreq.ifr_name, ifp->if_xname)) /* not this interface */ continue; + found=1; if (IFADDR_EMPTY(ifp)) { + pserialize_read_exit(s); error = ENODEV; goto out; } @@ -1228,10 +1252,13 @@ linux_getifhwaddr(struct lwp *l, registe sizeof(lreq.ifr_hwaddr.sa_data))); lreq.ifr_hwaddr.sa_family = sadl->sdl_family; + pserialize_read_exit(s); + error = copyout(&lreq, data, sizeof(lreq)); goto out; } } + pserialize_read_exit(s); if (strncmp(lreq.ifr_name, "eth", 3) != 0) { /* unknown interface, not even an "eth*" name */ @@ -1247,10 +1274,8 @@ linux_getifhwaddr(struct lwp *l, registe } error = EINVAL; /* in case we don't find one */ - found = 0; - IFNET_FOREACH(ifp) { - if (found) - break; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { memcpy(lreq.ifr_name, ifp->if_xname, MIN(LINUX_IFNAMSIZ, IFNAMSIZ)); IFADDR_FOREACH(ifa, ifp) { @@ -1269,11 +1294,13 @@ linux_getifhwaddr(struct lwp *l, registe sizeof(lreq.ifr_hwaddr.sa_data))); lreq.ifr_hwaddr.sa_family = sadl->sdl_family; + pserialize_read_exit(s); + error = copyout(&lreq, data, sizeof(lreq)); - found = 1; - break; + goto out; } } + pserialize_read_exit(s); out: KERNEL_UNLOCK_ONE(NULL); Index: src/sys/compat/linux32/common/linux32_socket.c diff -u src/sys/compat/linux32/common/linux32_socket.c:1.20 src/sys/compat/linux32/common/linux32_socket.c:1.21 --- src/sys/compat/linux32/common/linux32_socket.c:1.20 Fri Jul 24 13:02:52 2015 +++ src/sys/compat/linux32/common/linux32_socket.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_socket.c,v 1.20 2015/07/24 13:02:52 maxv Exp $ */ +/* $NetBSD: linux32_socket.c,v 1.21 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.20 2015/07/24 13:02:52 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.21 2016/05/12 02:24:16 ozaki-r Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -419,6 +419,9 @@ linux32_getifconf(struct lwp *l, registe int space = 0, error; const int sz = (int)sizeof(ifr); bool docopy; + int s; + int bound = curlwp->l_pflag & LP_BOUND; + struct psref psref; error = copyin(data, &ifc, sizeof(ifc)); if (error) @@ -430,11 +433,18 @@ linux32_getifconf(struct lwp *l, registe ifrp = NETBSD32PTR64(ifc.ifc_req); } - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); - if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') - return ENAMETOOLONG; + if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { + error = ENAMETOOLONG; + goto release_exit; + } if (IFADDR_EMPTY(ifp)) continue; IFADDR_FOREACH(ifa, ifp) { @@ -448,12 +458,17 @@ linux32_getifconf(struct lwp *l, registe if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) - return error; + goto release_exit; ifrp++; } space -= sz; } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; if (docopy) ifc.ifc_len -= space; @@ -461,6 +476,11 @@ linux32_getifconf(struct lwp *l, registe ifc.ifc_len = -space; return copyout(&ifc, data, sizeof(ifc)); + +release_exit: + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return error; } int @@ -474,6 +494,7 @@ linux32_getifhwaddr(struct lwp *l, regis struct sockaddr_dl *sadl; int error, found; int index, ifnum; + int s; /* * We can't emulate this ioctl by calling sys_ioctl() to run @@ -505,7 +526,8 @@ linux32_getifhwaddr(struct lwp *l, regis * Try real interface name first, then fake "ethX" */ found = 0; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (found) break; if (strcmp(lreq.ifr_name, ifp->if_xname)) @@ -528,10 +550,13 @@ linux32_getifhwaddr(struct lwp *l, regis sizeof(lreq.ifr_hwaddr.sa_data))); lreq.ifr_hwaddr.sa_family = sadl->sdl_family; + pserialize_read_exit(s); + error = copyout(&lreq, data, sizeof(lreq)); goto out; } } + pserialize_read_exit(s); if (strncmp(lreq.ifr_name, "eth", 3) == 0) { for (ifnum = 0, index = 3; @@ -542,10 +567,8 @@ linux32_getifhwaddr(struct lwp *l, regis } error = EINVAL; /* in case we don't find one */ - found = 0; - IFNET_FOREACH(ifp) { - if (found) - break; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { memcpy(lreq.ifr_name, ifp->if_xname, MIN(LINUX32_IFNAMSIZ, IFNAMSIZ)); IFADDR_FOREACH(ifa, ifp) { @@ -564,11 +587,13 @@ linux32_getifhwaddr(struct lwp *l, regis sizeof(lreq.ifr_hwaddr.sa_data))); lreq.ifr_hwaddr.sa_family = sadl->sdl_family; + pserialize_read_exit(s); + error = copyout(&lreq, data, sizeof(lreq)); - found = 1; - break; + goto out; } } + pserialize_read_exit(s); } else { /* unknown interface, not even an "eth*" name */ error = ENODEV; Index: src/sys/compat/svr4/svr4_sockio.c diff -u src/sys/compat/svr4/svr4_sockio.c:1.36 src/sys/compat/svr4/svr4_sockio.c:1.37 --- src/sys/compat/svr4/svr4_sockio.c:1.36 Sun Nov 9 18:16:55 2014 +++ src/sys/compat/svr4/svr4_sockio.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_sockio.c,v 1.36 2014/11/09 18:16:55 maxv Exp $ */ +/* $NetBSD: svr4_sockio.c,v 1.37 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1995, 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svr4_sockio.c,v 1.36 2014/11/09 18:16:55 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_sockio.c,v 1.37 2016/05/12 02:24:16 ozaki-r Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -108,6 +108,7 @@ svr4_sock_ioctl(file_t *fp, struct lwp * { struct ifnet *ifp; struct svr4_lifnum lifnum; + int s; error = copyin(data, &lifnum, sizeof(lifnum)); if (error) @@ -115,8 +116,10 @@ svr4_sock_ioctl(file_t *fp, struct lwp * lifnum.lifn_count = 0; /* XXX: We don't pay attention to family or flags */ - IFNET_FOREACH(ifp) + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) lifnum.lifn_count += svr4_count_ifnum(ifp); + pserialize_read_exit(s); DPRINTF(("SIOCGLIFNUM [family=%d,flags=%d,count=%d]\n", lifnum.lifn_family, lifnum.lifn_flags, @@ -128,6 +131,7 @@ svr4_sock_ioctl(file_t *fp, struct lwp * { struct ifnet *ifp; int ifnum = 0; + int s; /* * This does not return the number of physical @@ -141,8 +145,10 @@ svr4_sock_ioctl(file_t *fp, struct lwp * * entry per physical interface? */ - IFNET_FOREACH(ifp) + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) ifnum += svr4_count_ifnum(ifp); + pserialize_read_exit(s); DPRINTF(("SIOCGIFNUM %d\n", ifnum)); return copyout(&ifnum, data, sizeof(ifnum)); Index: src/sys/compat/svr4_32/svr4_32_sockio.c diff -u src/sys/compat/svr4_32/svr4_32_sockio.c:1.21 src/sys/compat/svr4_32/svr4_32_sockio.c:1.22 --- src/sys/compat/svr4_32/svr4_32_sockio.c:1.21 Mon Apr 28 20:23:46 2008 +++ src/sys/compat/svr4_32/svr4_32_sockio.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_32_sockio.c,v 1.21 2008/04/28 20:23:46 martin Exp $ */ +/* $NetBSD: svr4_32_sockio.c,v 1.22 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1995, 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svr4_32_sockio.c,v 1.21 2008/04/28 20:23:46 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_32_sockio.c,v 1.22 2016/05/12 02:24:16 ozaki-r Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -96,6 +96,7 @@ svr4_32_sock_ioctl(file_t *fp, struct lw { struct ifnet *ifp; int ifnum = 0; + int s; /* * This does not return the number of physical @@ -109,8 +110,10 @@ svr4_32_sock_ioctl(file_t *fp, struct lw * entry per physical interface? */ - IFNET_FOREACH(ifp) + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) ifnum += svr4_count_ifnum(ifp) + pserialize_read_exit(s); DPRINTF(("SIOCGIFNUM %d\n", ifnum)); return copyout(&ifnum, data, sizeof(ifnum)); Index: src/sys/dev/pci/if_bge.c diff -u src/sys/dev/pci/if_bge.c:1.295 src/sys/dev/pci/if_bge.c:1.296 --- src/sys/dev/pci/if_bge.c:1.295 Tue Feb 9 08:32:11 2016 +++ src/sys/dev/pci/if_bge.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bge.c,v 1.295 2016/02/09 08:32:11 ozaki-r Exp $ */ +/* $NetBSD: if_bge.c,v 1.296 2016/05/12 02:24:16 ozaki-r Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.295 2016/02/09 08:32:11 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.296 2016/05/12 02:24:16 ozaki-r Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1516,6 +1516,7 @@ bge_update_all_threshes(int lvl) struct ifnet *ifp; const char * const namebuf = "bge"; int namelen; + int s; if (lvl < 0) lvl = 0; @@ -1526,13 +1527,15 @@ bge_update_all_threshes(int lvl) /* * Now search all the interfaces for this name/number */ - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (strncmp(ifp->if_xname, namebuf, namelen) != 0) continue; /* We got a match: update if doing auto-threshold-tuning */ if (bge_auto_thresh) bge_set_thresh(ifp, lvl); } + pserialize_read_exit(s); } /* Index: src/sys/dist/pf/net/pf_if.c diff -u src/sys/dist/pf/net/pf_if.c:1.26 src/sys/dist/pf/net/pf_if.c:1.27 --- src/sys/dist/pf/net/pf_if.c:1.26 Sat May 17 21:00:33 2014 +++ src/sys/dist/pf/net/pf_if.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: pf_if.c,v 1.26 2014/05/17 21:00:33 rmind Exp $ */ +/* $NetBSD: pf_if.c,v 1.27 2016/05/12 02:24:16 ozaki-r Exp $ */ /* $OpenBSD: pf_if.c,v 1.47 2007/07/13 09:17:48 markus Exp $ */ /* @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pf_if.c,v 1.26 2014/05/17 21:00:33 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pf_if.c,v 1.27 2016/05/12 02:24:16 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -100,6 +100,9 @@ RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tr void pfi_initialize(void) { + int s; + int bound = curlwp->l_pflag & LP_BOUND; + if (pfi_all != NULL) /* already initialized */ return; @@ -119,10 +122,21 @@ pfi_initialize(void) #ifdef __NetBSD__ ifnet_t *ifp; - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + struct psref psref; + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + pfi_init_groups(ifp); pfi_attach_ifnet(ifp); + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; pfil_add_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); pfil_add_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); @@ -135,14 +149,27 @@ pfi_destroy(void) { struct pfi_kif *p; ifnet_t *ifp; + int s; + int bound = curlwp->l_pflag & LP_BOUND; pfil_remove_hook(pfil_ifaddr_wrapper, NULL, PFIL_IFADDR, if_pfil); pfil_remove_hook(pfil_ifnet_wrapper, NULL, PFIL_IFNET, if_pfil); - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + struct psref psref; + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + pfi_detach_ifnet(ifp); pfi_destroy_groups(ifp); + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) { RB_REMOVE(pfi_ifhead, &pfi_ifs, p); Index: src/sys/kern/kern_subr.c diff -u src/sys/kern/kern_subr.c:1.216 src/sys/kern/kern_subr.c:1.217 --- src/sys/kern/kern_subr.c:1.216 Sat Nov 22 11:04:57 2014 +++ src/sys/kern/kern_subr.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_subr.c,v 1.216 2014/11/22 11:04:57 mlelstv Exp $ */ +/* $NetBSD: kern_subr.c,v 1.217 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.216 2014/11/22 11:04:57 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.217 2016/05/12 02:24:16 ozaki-r Exp $"); #include "opt_ddb.h" #include "opt_md.h" @@ -224,7 +224,8 @@ setroot(device_t bootdv, int bootpartiti if (vops != NULL && strcmp(rootfstype, MOUNT_NFS) == 0 && rootspec == NULL && (bootdv == NULL || device_class(bootdv) != DV_IFNET)) { - IFNET_FOREACH(ifp) { + int s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if ((ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) break; @@ -242,6 +243,7 @@ setroot(device_t bootdv, int bootpartiti */ rootspec = (const char *)ifp->if_xname; } + pserialize_read_exit(s); } if (vops != NULL) vfs_delref(vops); Index: src/sys/kern/subr_tftproot.c diff -u src/sys/kern/subr_tftproot.c:1.16 src/sys/kern/subr_tftproot.c:1.17 --- src/sys/kern/subr_tftproot.c:1.16 Thu May 21 02:04:22 2015 +++ src/sys/kern/subr_tftproot.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_tftproot.c,v 1.16 2015/05/21 02:04:22 rtr Exp $ */ +/* $NetBSD: subr_tftproot.c,v 1.17 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 2007 Emmanuel Dreyfus, all rights reserved. @@ -39,7 +39,7 @@ #include "opt_md.h" #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_tftproot.c,v 1.16 2015/05/21 02:04:22 rtr Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_tftproot.c,v 1.17 2016/05/12 02:24:16 ozaki-r Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -131,16 +131,20 @@ tftproot_dhcpboot(device_t bootdv) int error = -1; if (rootspec != NULL) { - IFNET_FOREACH(ifp) + int s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) if (strcmp(rootspec, ifp->if_xname) == 0) break; + pserialize_read_exit(s); } if ((ifp == NULL) && (bootdv != NULL && device_class(bootdv) == DV_IFNET)) { - IFNET_FOREACH(ifp) + int s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) if (strcmp(device_xname(bootdv), ifp->if_xname) == 0) break; + pserialize_read_exit(s); } if (ifp == NULL) { Index: src/sys/kern/uipc_mbuf.c diff -u src/sys/kern/uipc_mbuf.c:1.164 src/sys/kern/uipc_mbuf.c:1.165 --- src/sys/kern/uipc_mbuf.c:1.164 Wed Apr 20 08:50:43 2016 +++ src/sys/kern/uipc_mbuf.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_mbuf.c,v 1.164 2016/04/20 08:50:43 knakahara Exp $ */ +/* $NetBSD: uipc_mbuf.c,v 1.165 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.164 2016/04/20 08:50:43 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.165 2016/05/12 02:24:16 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_mbuftrace.h" @@ -556,9 +556,23 @@ m_reclaim(void *arg, int flags) if (pr->pr_drain) (*pr->pr_drain)(); } - IFNET_FOREACH(ifp) { - if (ifp->if_drain) - (*ifp->if_drain)(ifp); + /* XXX we cannot use psref in H/W interrupt */ + if (!cpu_intr_p()) { + int bound = curlwp->l_pflag & LP_BOUND; + curlwp->l_pflag |= LP_BOUND; + IFNET_READER_FOREACH(ifp) { + struct psref psref; + + psref_acquire(&psref, &ifp->if_psref, + ifnet_psref_class); + + if (ifp->if_drain) + (*ifp->if_drain)(ifp); + + psref_release(&psref, &ifp->if_psref, + ifnet_psref_class); + } + curlwp->l_pflag ^= bound ^ LP_BOUND; } splx(s); mbstat.m_drain++; Index: src/sys/net/if.c diff -u src/sys/net/if.c:1.333 src/sys/net/if.c:1.334 --- src/sys/net/if.c:1.333 Mon May 2 08:03:23 2016 +++ src/sys/net/if.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.333 2016/05/02 08:03:23 skrll Exp $ */ +/* $NetBSD: if.c,v 1.334 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.333 2016/05/02 08:03:23 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.334 2016/05/12 02:24:16 ozaki-r Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -161,13 +161,19 @@ MALLOC_DEFINE(M_IFMADDR, "ether_multi", /* * Global list of interfaces. */ +/* DEPRECATED. Remove it once kvm(3) users disappeared */ struct ifnet_head ifnet_list; -static ifnet_t ** ifindex2ifnet = NULL; +struct pslist_head ifnet_pslist; +static ifnet_t ** ifindex2ifnet = NULL; static u_int if_index = 1; static size_t if_indexlim = 0; static uint64_t index_gen; -static kmutex_t index_gen_mtx; +/* Mutex to protect the above objects. */ +kmutex_t ifnet_mtx __cacheline_aligned; +struct psref_class *ifnet_psref_class __read_mostly; +static pserialize_t ifnet_psz; + static kmutex_t if_clone_mtx; struct ifnet *lo0ifp; @@ -269,9 +275,12 @@ ifinit(void) void ifinit1(void) { - mutex_init(&index_gen_mtx, MUTEX_DEFAULT, IPL_NONE); mutex_init(&if_clone_mtx, MUTEX_DEFAULT, IPL_NONE); TAILQ_INIT(&ifnet_list); + mutex_init(&ifnet_mtx, MUTEX_DEFAULT, IPL_NONE); + ifnet_psz = pserialize_create(); + ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET); + PSLIST_INIT(&ifnet_pslist); if_indexlim = 8; if_pfil = pfil_head_create(PFIL_TYPE_IFNET, NULL); @@ -525,9 +534,7 @@ if_getindex(ifnet_t *ifp) { bool hitlimit = false; - mutex_enter(&index_gen_mtx); ifp->if_index_gen = index_gen++; - mutex_exit(&index_gen_mtx); ifp->if_index = if_index; if (ifindex2ifnet == NULL) { @@ -644,7 +651,12 @@ if_initialize(ifnet_t *ifp) if (ifp->if_link_si == NULL) panic("%s: softint_establish() failed", __func__); + PSLIST_ENTRY_INIT(ifp, if_pslist_entry); + psref_target_init(&ifp->if_psref, ifnet_psref_class); + + IFNET_LOCK(); if_getindex(ifp); + IFNET_UNLOCK(); } /* @@ -675,7 +687,10 @@ if_register(ifnet_t *ifp) if (ifp->if_transmit == NULL || ifp->if_transmit == if_nulltransmit) ifp->if_transmit = if_transmit; + IFNET_LOCK(); TAILQ_INSERT_TAIL(&ifnet_list, ifp, if_list); + IFNET_WRITER_INSERT_TAIL(ifp); + IFNET_UNLOCK(); } /* @@ -929,11 +944,20 @@ if_attachdomain(void) { struct ifnet *ifp; int s; + int bound = curlwp->l_pflag & LP_BOUND; - s = splnet(); - IFNET_FOREACH(ifp) + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + struct psref psref; + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); if_attachdomain1(ifp); - splx(s); + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; } static void @@ -1022,8 +1046,18 @@ if_detach(struct ifnet *ifp) s = splnet(); + sysctl_teardown(&ifp->if_sysctl_log); + + IFNET_LOCK(); ifindex2ifnet[ifp->if_index] = NULL; TAILQ_REMOVE(&ifnet_list, ifp, if_list); + IFNET_WRITER_REMOVE(ifp); + pserialize_perform(ifnet_psz); + IFNET_UNLOCK(); + + /* Wait for all readers to drain before freeing. */ + psref_target_destroy(&ifp->if_psref, ifnet_psref_class); + PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry); if (ifp->if_slowtimo != NULL) { ifp->if_slowtimo = NULL; @@ -1047,8 +1081,6 @@ if_detach(struct ifnet *ifp) if (ifp->if_snd.ifq_lock) mutex_obj_free(ifp->if_snd.ifq_lock); - sysctl_teardown(&ifp->if_sysctl_log); - #if NCARP > 0 /* Remove the interface from any carp group it is a part of. */ if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP) @@ -1456,8 +1488,10 @@ ifa_ifwithaddr(const struct sockaddr *ad { struct ifnet *ifp; struct ifaddr *ifa; + int s; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; IFADDR_FOREACH(ifa, ifp) { @@ -1473,6 +1507,7 @@ ifa_ifwithaddr(const struct sockaddr *ad return ifa; } } + pserialize_read_exit(s); return NULL; } @@ -1485,8 +1520,10 @@ ifa_ifwithdstaddr(const struct sockaddr { struct ifnet *ifp; struct ifaddr *ifa; + int s; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; if ((ifp->if_flags & IFF_POINTOPOINT) == 0) @@ -1499,6 +1536,7 @@ ifa_ifwithdstaddr(const struct sockaddr return ifa; } } + pserialize_read_exit(s); return NULL; } @@ -1515,6 +1553,7 @@ ifa_ifwithnet(const struct sockaddr *add struct ifaddr *ifa_maybe = 0; u_int af = addr->sa_family; const char *addr_data = addr->sa_data, *cplim; + int s; if (af == AF_LINK) { sdl = satocsdl(addr); @@ -1528,7 +1567,8 @@ ifa_ifwithnet(const struct sockaddr *add if (af == AF_APPLETALK) { const struct sockaddr_at *sat, *sat2; sat = (const struct sockaddr_at *)addr; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; ifa = at_ifawithnet((const struct sockaddr_at *)addr, ifp); @@ -1542,10 +1582,12 @@ ifa_ifwithnet(const struct sockaddr *add ifa_maybe = ifa; } } + pserialize_read_exit(s); return ifa_maybe; } #endif - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; IFADDR_FOREACH(ifa, ifp) { @@ -1571,6 +1613,7 @@ ifa_ifwithnet(const struct sockaddr *add ifa_maybe = ifa; } } + pserialize_read_exit(s); return ifa_maybe; } @@ -1595,17 +1638,21 @@ struct ifaddr * ifa_ifwithaf(int af) { struct ifnet *ifp; - struct ifaddr *ifa; + struct ifaddr *ifa = NULL; + int s; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family == af) - return ifa; + goto out; } } - return NULL; +out: + pserialize_read_exit(s); + return ifa; } /* @@ -2038,6 +2085,7 @@ ifunit(const char *name) const char *cp = name; u_int unit = 0; u_int i; + int s; /* * If the entire name is a number, treat it as an ifindex. @@ -2058,13 +2106,17 @@ ifunit(const char *name) return ifp; } - IFNET_FOREACH(ifp) { + ifp = NULL; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp->if_output == if_nulloutput) continue; if (strcmp(ifp->if_xname, name) == 0) - return ifp; + goto out; } - return NULL; +out: + pserialize_read_exit(s); + return ifp; } ifnet_t * @@ -2591,17 +2643,27 @@ ifconf(u_long cmd, void *data) int space = 0, error = 0; const int sz = (int)sizeof(struct ifreq); const bool docopy = ifc->ifc_req != NULL; + int s; + int bound = curlwp->l_pflag & LP_BOUND; + struct psref psref; if (docopy) { space = ifc->ifc_len; ifrp = ifc->ifc_req; } - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + (void)strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); - if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') - return ENAMETOOLONG; + if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { + error = ENAMETOOLONG; + goto release_exit; + } if (IFADDR_EMPTY(ifp)) { /* Interface with no addresses - send zero sockaddr. */ memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); @@ -2612,7 +2674,7 @@ ifconf(u_long cmd, void *data) if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) - return error; + goto release_exit; ifrp++; space -= sz; } @@ -2631,11 +2693,17 @@ ifconf(u_long cmd, void *data) if (space >= sz) { error = copyout(&ifr, ifrp, sz); if (error != 0) - return (error); + goto release_exit; ifrp++; space -= sz; } } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; + if (docopy) { KASSERT(0 <= space && space <= ifc->ifc_len); ifc->ifc_len -= space; @@ -2644,6 +2712,11 @@ ifconf(u_long cmd, void *data) ifc->ifc_len = space; } return (0); + +release_exit: + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return error; } int Index: src/sys/net/if.h diff -u src/sys/net/if.h:1.203 src/sys/net/if.h:1.204 --- src/sys/net/if.h:1.203 Thu Apr 28 01:37:17 2016 +++ src/sys/net/if.h Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: if.h,v 1.203 2016/04/28 01:37:17 knakahara Exp $ */ +/* $NetBSD: if.h,v 1.204 2016/05/12 02:24:16 ozaki-r Exp $ */ /*- * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -85,6 +85,9 @@ #include <net/pfil.h> #ifdef _KERNEL #include <net/pktqueue.h> +#include <sys/pslist.h> +#include <sys/pserialize.h> +#include <sys/psref.h> #endif /* @@ -251,6 +254,7 @@ struct if_percpuq; typedef struct ifnet { void *if_softc; /* lower-level data for this if */ + /* DEPRECATED. Keep it to avoid breaking kvm(3) users */ TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */ TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */ char if_xname[IFNAMSIZ]; /* external name (name + unit) */ @@ -354,6 +358,8 @@ typedef struct ifnet { struct if_percpuq *if_percpuq; /* We should remove it in the future */ void *if_link_si; /* softint to handle link state changes */ uint16_t if_link_queue; /* masked link state change queue */ + struct pslist_entry if_pslist_entry; + struct psref_target if_psref; #endif } ifnet_t; @@ -984,10 +990,6 @@ __END_DECLS #ifdef _KERNEL -#define IFNET_FIRST() TAILQ_FIRST(&ifnet_list) -#define IFNET_EMPTY() TAILQ_EMPTY(&ifnet_list) -#define IFNET_NEXT(__ifp) TAILQ_NEXT((__ifp), if_list) -#define IFNET_FOREACH(__ifp) TAILQ_FOREACH(__ifp, &ifnet_list, if_list) #define IFADDR_FIRST(__ifp) TAILQ_FIRST(&(__ifp)->if_addrlist) #define IFADDR_NEXT(__ifa) TAILQ_NEXT((__ifa), ifa_list) #define IFADDR_FOREACH(__ifa, __ifp) TAILQ_FOREACH(__ifa, \ @@ -997,7 +999,52 @@ __END_DECLS &(__ifp)->if_addrlist, ifa_list, __nifa) #define IFADDR_EMPTY(__ifp) TAILQ_EMPTY(&(__ifp)->if_addrlist) -extern struct ifnet_head ifnet_list; +#define IFNET_LOCK() mutex_enter(&ifnet_mtx) +#define IFNET_UNLOCK() mutex_exit(&ifnet_mtx) +#define IFNET_LOCKED() mutex_owned(&ifnet_mtx) + +#define IFNET_READER_EMPTY() \ + (PSLIST_READER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry) == NULL) +#define IFNET_READER_FIRST() \ + PSLIST_READER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry) +#define IFNET_READER_NEXT(__ifp) \ + PSLIST_READER_NEXT((__ifp), struct ifnet, if_pslist_entry) +#define IFNET_READER_FOREACH(__ifp) \ + PSLIST_READER_FOREACH((__ifp), &ifnet_pslist, struct ifnet, \ + if_pslist_entry) +#define IFNET_WRITER_INSERT_HEAD(__ifp) \ + PSLIST_WRITER_INSERT_HEAD(&ifnet_pslist, (__ifp), if_pslist_entry) +#define IFNET_WRITER_REMOVE(__ifp) \ + PSLIST_WRITER_REMOVE((__ifp), if_pslist_entry) +#define IFNET_WRITER_FOREACH(__ifp) \ + PSLIST_WRITER_FOREACH((__ifp), &ifnet_pslist, struct ifnet, \ + if_pslist_entry) +#define IFNET_WRITER_NEXT(__ifp) \ + PSLIST_WRITER_NEXT((__ifp), struct ifnet, if_pslist_entry) +#define IFNET_WRITER_INSERT_AFTER(__ifp, __new) \ + PSLIST_WRITER_INSERT_AFTER((__ifp), (__new), if_pslist_entry) +#define IFNET_WRITER_EMPTY() \ + (PSLIST_WRITER_FIRST(&ifnet_pslist, struct ifnet, if_pslist_entry) == NULL) +#define IFNET_WRITER_INSERT_TAIL(__new) \ + do { \ + if (IFNET_WRITER_EMPTY()) { \ + IFNET_WRITER_INSERT_HEAD((__new)); \ + } else { \ + struct ifnet *__ifp; \ + IFNET_WRITER_FOREACH(__ifp) { \ + if (IFNET_WRITER_NEXT(__ifp) == NULL) { \ + IFNET_WRITER_INSERT_AFTER(__ifp,\ + (__new)); \ + break; \ + } \ + } \ + } \ + } while (0) + +extern struct pslist_head ifnet_pslist; +extern struct psref_class *ifnet_psref_class; +extern kmutex_t ifnet_mtx; + extern struct ifnet *lo0ifp; ifnet_t * if_byindex(u_int); Index: src/sys/net/rtsock.c diff -u src/sys/net/rtsock.c:1.185 src/sys/net/rtsock.c:1.186 --- src/sys/net/rtsock.c:1.185 Mon Apr 25 15:43:49 2016 +++ src/sys/net/rtsock.c Thu May 12 02:24:16 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: rtsock.c,v 1.185 2016/04/25 15:43:49 roy Exp $ */ +/* $NetBSD: rtsock.c,v 1.186 2016/05/12 02:24:16 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.185 2016/04/25 15:43:49 roy Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.186 2016/05/12 02:24:16 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1429,13 +1429,23 @@ sysctl_iflist(int af, struct rt_walkarg struct ifaddr *ifa; struct rt_addrinfo info; int len, error = 0; + int s; + struct psref psref; + int bound = curlwp->l_pflag & LP_BOUND; memset(&info, 0, sizeof(info)); - IFNET_FOREACH(ifp) { + + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (w->w_arg && w->w_arg != ifp->if_index) continue; if (IFADDR_EMPTY(ifp)) continue; + + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + info.rti_info[RTAX_IFP] = ifp->if_dl->ifa_addr; switch (type) { case NET_RT_IFLIST: @@ -1455,7 +1465,7 @@ sysctl_iflist(int af, struct rt_walkarg panic("sysctl_iflist(1)"); } if (error) - return error; + goto release_exit; info.rti_info[RTAX_IFP] = NULL; if (w->w_where && w->w_tmem && w->w_needed <= 0) { switch (type) { @@ -1469,7 +1479,7 @@ sysctl_iflist(int af, struct rt_walkarg ifm->ifm_addrs = info.rti_addrs; error = copyout(ifm, w->w_where, len); if (error) - return error; + goto release_exit; w->w_where = (char *)w->w_where + len; break; } @@ -1478,14 +1488,14 @@ sysctl_iflist(int af, struct rt_walkarg case NET_RT_OOIFLIST: error = compat_14_iflist(ifp, w, &info, len); if (error) - return error; + goto release_exit; break; #endif #ifdef COMPAT_50 case NET_RT_OIFLIST: error = compat_50_iflist(ifp, w, &info, len); if (error) - return error; + goto release_exit; break; #endif default: @@ -1499,7 +1509,7 @@ sysctl_iflist(int af, struct rt_walkarg info.rti_info[RTAX_NETMASK] = ifa->ifa_netmask; info.rti_info[RTAX_BRD] = ifa->ifa_dstaddr; if ((error = rt_msg2(RTM_NEWADDR, &info, 0, w, &len))) - return error; + goto release_exit; if (w->w_where && w->w_tmem && w->w_needed <= 0) { struct ifa_xmsghdr *ifam; @@ -1510,14 +1520,25 @@ sysctl_iflist(int af, struct rt_walkarg ifam->ifam_addrs = info.rti_addrs; error = copyout(w->w_tmem, w->w_where, len); if (error) - return error; + goto release_exit; w->w_where = (char *)w->w_where + len; } } info.rti_info[RTAX_IFA] = info.rti_info[RTAX_NETMASK] = info.rti_info[RTAX_BRD] = NULL; + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return 0; + +release_exit: + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); + curlwp->l_pflag ^= bound ^ LP_BOUND; + return error; } static int Index: src/sys/net/npf/npf_if.c diff -u src/sys/net/npf/npf_if.c:1.5 src/sys/net/npf/npf_if.c:1.6 --- src/sys/net/npf/npf_if.c:1.5 Sun Jul 12 23:51:53 2015 +++ src/sys/net/npf/npf_if.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_if.c,v 1.5 2015/07/12 23:51:53 rmind Exp $ */ +/* $NetBSD: npf_if.c,v 1.6 2016/05/12 02:24:17 ozaki-r Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. @@ -45,7 +45,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_if.c,v 1.5 2015/07/12 23:51:53 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_if.c,v 1.6 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "pf.h" @@ -139,9 +139,11 @@ npf_ifmap_flush(void) npf_ifmap_cnt = 0; KERNEL_LOCK(1, NULL); - IFNET_FOREACH(ifp) { + IFNET_LOCK(); + IFNET_WRITER_FOREACH(ifp) { ifp->if_pf_kif = (void *)(uintptr_t)0; } + IFNET_UNLOCK(); KERNEL_UNLOCK_ONE(NULL); } Index: src/sys/netinet/ip_carp.c diff -u src/sys/netinet/ip_carp.c:1.64 src/sys/netinet/ip_carp.c:1.65 --- src/sys/netinet/ip_carp.c:1.64 Thu Apr 28 00:16:56 2016 +++ src/sys/netinet/ip_carp.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.c,v 1.64 2016/04/28 00:16:56 ozaki-r Exp $ */ +/* $NetBSD: ip_carp.c,v 1.65 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ /* @@ -33,7 +33,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.64 2016/04/28 00:16:56 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.65 2016/05/12 02:24:17 ozaki-r Exp $"); /* * TODO: @@ -928,18 +928,31 @@ carp_send_ad_all(void) struct ifnet *ifp; struct carp_if *cif; struct carp_softc *vh; + int s; + int bound = curlwp->l_pflag & LP_BOUND; - IFNET_FOREACH(ifp) { + curlwp->l_pflag |= LP_BOUND; + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { + struct psref psref; if (ifp->if_carp == NULL || ifp->if_type == IFT_CARP) continue; + psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + cif = (struct carp_if *)ifp->if_carp; TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER) carp_send_ad(vh); } + + s = pserialize_read_enter(); + psref_release(&psref, &ifp->if_psref, ifnet_psref_class); } + pserialize_read_exit(s); + curlwp->l_pflag ^= bound ^ LP_BOUND; } Index: src/sys/netinet/raw_ip.c diff -u src/sys/netinet/raw_ip.c:1.157 src/sys/netinet/raw_ip.c:1.158 --- src/sys/netinet/raw_ip.c:1.157 Tue Apr 26 08:44:44 2016 +++ src/sys/netinet/raw_ip.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: raw_ip.c,v 1.157 2016/04/26 08:44:44 ozaki-r Exp $ */ +/* $NetBSD: raw_ip.c,v 1.158 2016/05/12 02:24:17 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -65,7 +65,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.157 2016/04/26 08:44:44 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.158 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -478,7 +478,7 @@ int rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr) { - if (IFNET_EMPTY()) + if (IFNET_READER_EMPTY()) return (EADDRNOTAVAIL); if (addr->sin_family != AF_INET) return (EAFNOSUPPORT); @@ -565,7 +565,7 @@ rip_bind(struct socket *so, struct socka return EINVAL; s = splsoftnet(); - if (IFNET_EMPTY()) { + if (IFNET_READER_EMPTY()) { error = EADDRNOTAVAIL; goto release; } Index: src/sys/netinet/sctp_asconf.c diff -u src/sys/netinet/sctp_asconf.c:1.2 src/sys/netinet/sctp_asconf.c:1.3 --- src/sys/netinet/sctp_asconf.c:1.2 Sun Apr 3 09:57:40 2016 +++ src/sys/netinet/sctp_asconf.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sctp_asconf.c,v 1.2 2016/04/03 09:57:40 mlelstv Exp $ */ +/* $NetBSD: sctp_asconf.c,v 1.3 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: sctp_asconf.c,v 1.25 2005/06/16 20:44:24 jinmei Exp $ */ /* @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctp_asconf.c,v 1.2 2016/04/03 09:57:40 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctp_asconf.c,v 1.3 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_ipsec.h" @@ -2115,8 +2115,10 @@ sctp_find_valid_localaddr(struct sctp_tc { struct ifnet *ifn; struct ifaddr *ifa, *nifa; + int s; - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if (stcb->asoc.loopback_scope == 0 && ifn->if_type == IFT_LOOP) { /* Skip if loopback_scope not set */ continue; @@ -2138,6 +2140,8 @@ sctp_find_valid_localaddr(struct sctp_tc if (sctp_is_addr_restricted(stcb, ifa->ifa_addr)) continue; + pserialize_read_exit(s); + /* found a valid local v4 address to use */ return (ifa->ifa_addr); } else if (ifa->ifa_addr->sa_family == AF_INET6 && @@ -2163,11 +2167,14 @@ sctp_find_valid_localaddr(struct sctp_tc IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) continue; + pserialize_read_exit(s); /* found a valid local v6 address to use */ return (ifa->ifa_addr); } } } + pserialize_read_exit(s); + /* no valid addresses found */ return (NULL); } @@ -2772,9 +2779,11 @@ sctp_check_address_list_all(struct sctp_ { struct ifnet *ifn; struct ifaddr *ifa; + int s; /* go through all our known interfaces */ - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if (loopback_scope == 0 && ifn->if_type == IFT_LOOP) { /* skip loopback interface */ continue; @@ -2801,6 +2810,7 @@ sctp_check_address_list_all(struct sctp_ } } /* end foreach ifa */ } /* end foreach ifn */ + pserialize_read_exit(s); } /* Index: src/sys/netinet/sctp_output.c diff -u src/sys/netinet/sctp_output.c:1.3 src/sys/netinet/sctp_output.c:1.4 --- src/sys/netinet/sctp_output.c:1.3 Mon Apr 25 21:21:02 2016 +++ src/sys/netinet/sctp_output.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: sctp_output.c,v 1.3 2016/04/25 21:21:02 rjs Exp $ */ +/* $NetBSD: sctp_output.c,v 1.4 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: sctp_output.c,v 1.48 2005/06/16 18:29:24 jinmei Exp $ */ /* @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctp_output.c,v 1.3 2016/04/25 21:21:02 rjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctp_output.c,v 1.4 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_ipsec.h" @@ -897,6 +897,7 @@ sctp_choose_v4_boundall(struct sctp_inpc struct sockaddr_in *sin; struct in_addr ans; struct ifaddr *ifa; + int s; /* * For v4 we can use (in boundall) any address in the association. If * non_asoc_addr_ok is set we can use any address (at least in theory). @@ -975,7 +976,8 @@ sctp_choose_v4_boundall(struct sctp_inpc * address. If we reache here we are in trouble I think. */ bound_all_v4_plan_c: - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if (ifn == inp->next_ifn_touse) break; if (loopscope == 0 && ifn->if_type == IFT_LOOP) { @@ -1008,9 +1010,11 @@ sctp_choose_v4_boundall(struct sctp_inpc ipv4_scope, cur_addr_num); if (sin == NULL) continue; + pserialize_read_exit(s); return (sin->sin_addr); } + pserialize_read_exit(s); /* * plan_d: We are in deep trouble. No prefered address on @@ -1021,7 +1025,8 @@ sctp_choose_v4_boundall(struct sctp_inpc * illicit an ABORT, falling through. */ - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if (ifn == inp->next_ifn_touse) break; if (loopscope == 0 && ifn->if_type == IFT_LOOP) { @@ -1044,9 +1049,11 @@ sctp_choose_v4_boundall(struct sctp_inpc continue; } } + pserialize_read_exit(s); return (sin->sin_addr); } } + pserialize_read_exit(s); /* * Ok we can find NO address to source from that is * not on our negative list. It is either the special @@ -1636,6 +1643,7 @@ sctp_choose_v6_boundall(struct sctp_inpc */ struct ifnet *ifn; struct sockaddr_in6 *sin6; + int s; ifn = rt->rt_ifp; if (net) { @@ -1715,14 +1723,14 @@ sctp_choose_v6_boundall(struct sctp_inpc #endif if (inp->next_ifn_touse == NULL) { started_at_beginning=1; - inp->next_ifn_touse = IFNET_FIRST(); + inp->next_ifn_touse = IFNET_READER_FIRST(); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { printf("Start at first IFN:%p\n", inp->next_ifn_touse); } #endif } else { - inp->next_ifn_touse = IFNET_NEXT(inp->next_ifn_touse); + inp->next_ifn_touse = IFNET_READER_NEXT(inp->next_ifn_touse); #ifdef SCTP_DEBUG if (sctp_debug_on & SCTP_DEBUG_OUTPUT1) { printf("Resume at IFN:%p\n", inp->next_ifn_touse); @@ -1735,10 +1743,12 @@ sctp_choose_v6_boundall(struct sctp_inpc } #endif started_at_beginning=1; - inp->next_ifn_touse = IFNET_FIRST(); + inp->next_ifn_touse = IFNET_READER_FIRST(); } } - IFNET_FOREACH(ifn) { + + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if (loopscope == 0 && ifn->if_type == IFT_LOOP) { /* wrong base scope */ continue; @@ -1797,8 +1807,11 @@ sctp_choose_v6_boundall(struct sctp_inpc cur_addr_num, ifn); } #endif + pserialize_read_exit(s); return (sin6); } + pserialize_read_exit(s); + if (started_at_beginning == 0) { /* we have not been through all of them yet, force * us to go through them all. @@ -2711,9 +2724,11 @@ sctp_send_initiate(struct sctp_inpcb *in struct ifnet *ifn; struct ifaddr *ifa; int cnt; + int s; cnt = cnt_inits_to; - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if ((stcb->asoc.loopback_scope == 0) && (ifn->if_type == IFT_LOOP)) { /* @@ -2735,8 +2750,11 @@ sctp_send_initiate(struct sctp_inpcb *in cnt++; } } + pserialize_read_exit(s); + if (cnt > 1) { - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if ((stcb->asoc.loopback_scope == 0) && (ifn->if_type == IFT_LOOP)) { /* @@ -2758,6 +2776,7 @@ sctp_send_initiate(struct sctp_inpcb *in m_at = sctp_add_addr_to_mbuf(m_at, ifa); } } + pserialize_read_exit(s); } } else { struct sctp_laddr *laddr; @@ -3657,8 +3676,10 @@ sctp_send_initiate_ack(struct sctp_inpcb struct ifnet *ifn; struct ifaddr *ifa; int cnt = cnt_inits_to; + int s; - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if ((stc.loopback_scope == 0) && (ifn->if_type == IFT_LOOP)) { /* @@ -3677,8 +3698,11 @@ sctp_send_initiate_ack(struct sctp_inpcb cnt++; } } + pserialize_read_exit(s); + if (cnt > 1) { - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if ((stc.loopback_scope == 0) && (ifn->if_type == IFT_LOOP)) { /* @@ -3698,6 +3722,7 @@ sctp_send_initiate_ack(struct sctp_inpcb m_at = sctp_add_addr_to_mbuf(m_at, ifa); } } + pserialize_read_exit(s); } } else { struct sctp_laddr *laddr; Index: src/sys/netinet/sctp_pcb.c diff -u src/sys/netinet/sctp_pcb.c:1.4 src/sys/netinet/sctp_pcb.c:1.5 --- src/sys/netinet/sctp_pcb.c:1.4 Mon Apr 25 21:21:02 2016 +++ src/sys/netinet/sctp_pcb.c Thu May 12 02:24:17 2016 @@ -1,5 +1,5 @@ /* $KAME: sctp_pcb.c,v 1.39 2005/06/16 18:29:25 jinmei Exp $ */ -/* $NetBSD: sctp_pcb.c,v 1.4 2016/04/25 21:21:02 rjs Exp $ */ +/* $NetBSD: sctp_pcb.c,v 1.5 2016/05/12 02:24:17 ozaki-r Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc. @@ -33,7 +33,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctp_pcb.c,v 1.4 2016/04/25 21:21:02 rjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctp_pcb.c,v 1.5 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -2338,7 +2338,10 @@ sctp_is_address_on_local_host(struct soc { struct ifnet *ifn; struct ifaddr *ifa; - IFNET_FOREACH(ifn) { + int s; + + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { IFADDR_FOREACH(ifa, ifn) { if (addr->sa_family == ifa->ifa_addr->sa_family) { /* same family */ @@ -2350,6 +2353,7 @@ sctp_is_address_on_local_host(struct soc if (sin->sin_addr.s_addr == sin_c->sin_addr.s_addr) { /* we are on the same machine */ + pserialize_read_exit(s); return (1); } } else if (addr->sa_family == AF_INET6) { @@ -2360,12 +2364,15 @@ sctp_is_address_on_local_host(struct soc if (SCTP6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &sin_c6->sin6_addr)) { /* we are on the same machine */ + pserialize_read_exit(s); return (1); } } } } } + pserialize_read_exit(s); + return (0); } Index: src/sys/netinet/sctp_usrreq.c diff -u src/sys/netinet/sctp_usrreq.c:1.4 src/sys/netinet/sctp_usrreq.c:1.5 --- src/sys/netinet/sctp_usrreq.c:1.4 Mon Apr 25 21:21:02 2016 +++ src/sys/netinet/sctp_usrreq.c Thu May 12 02:24:17 2016 @@ -1,5 +1,5 @@ /* $KAME: sctp_usrreq.c,v 1.50 2005/06/16 20:45:29 jinmei Exp $ */ -/* $NetBSD: sctp_usrreq.c,v 1.4 2016/04/25 21:21:02 rjs Exp $ */ +/* $NetBSD: sctp_usrreq.c,v 1.5 2016/05/12 02:24:17 ozaki-r Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc. @@ -33,7 +33,7 @@ * SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctp_usrreq.c,v 1.4 2016/04/25 21:21:02 rjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctp_usrreq.c,v 1.5 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -943,7 +943,8 @@ sctp_fill_up_addresses(struct sctp_inpcb } if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { - IFNET_FOREACH(ifn) { + int s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { if ((loopback_scope == 0) && (ifn->if_type == IFT_LOOP)) { /* Skip loopback if loopback_scope not set */ @@ -988,6 +989,7 @@ sctp_fill_up_addresses(struct sctp_inpcb actual += sizeof(*sin); } if (actual >= limit) { + pserialize_read_exit(s); return (actual); } } else if ((ifa->ifa_addr->sa_family == AF_INET6) && @@ -1010,11 +1012,13 @@ sctp_fill_up_addresses(struct sctp_inpcb sas = (struct sockaddr_storage *)((vaddr_t)sas + sizeof(*sin6)); actual += sizeof(*sin6); if (actual >= limit) { + pserialize_read_exit(s); return (actual); } } } } + pserialize_read_exit(s); } else { struct sctp_laddr *laddr; /* @@ -1095,8 +1099,10 @@ sctp_count_max_addresses(struct sctp_inp if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { struct ifnet *ifn; struct ifaddr *ifa; + int s; - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { IFADDR_FOREACH(ifa, ifn) { /* Count them if they are the right type */ if (ifa->ifa_addr->sa_family == AF_INET) { @@ -1109,6 +1115,7 @@ sctp_count_max_addresses(struct sctp_inp cnt += sizeof(struct sockaddr_in6); } } + pserialize_read_exit(s); } else { struct sctp_laddr *laddr; LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { Index: src/sys/netinet/sctputil.c diff -u src/sys/netinet/sctputil.c:1.6 src/sys/netinet/sctputil.c:1.7 --- src/sys/netinet/sctputil.c:1.6 Tue Apr 26 11:02:57 2016 +++ src/sys/netinet/sctputil.c Thu May 12 02:24:17 2016 @@ -1,5 +1,5 @@ /* $KAME: sctputil.c,v 1.39 2005/06/16 20:54:06 jinmei Exp $ */ -/* $NetBSD: sctputil.c,v 1.6 2016/04/26 11:02:57 rjs Exp $ */ +/* $NetBSD: sctputil.c,v 1.7 2016/05/12 02:24:17 ozaki-r Exp $ */ /* * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sctputil.c,v 1.6 2016/04/26 11:02:57 rjs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sctputil.c,v 1.7 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -3607,9 +3607,11 @@ sctp_find_ifa_by_addr(struct sockaddr *s { struct ifnet *ifn; struct ifaddr *ifa; + int s; /* go through all our known interfaces */ - IFNET_FOREACH(ifn) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifn) { /* go through each interface addresses */ IFADDR_FOREACH(ifa, ifn) { /* correct family? */ @@ -3632,6 +3634,7 @@ sctp_find_ifa_by_addr(struct sockaddr *s if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, sizeof(struct in6_addr)) == 0) { /* found it */ + pserialize_read_exit(s); return (ifa); } } else @@ -3644,12 +3647,15 @@ sctp_find_ifa_by_addr(struct sockaddr *s if (sin1->sin_addr.s_addr == sin2->sin_addr.s_addr) { /* found it */ + pserialize_read_exit(s); return (ifa); } } /* else, not AF_INET or AF_INET6, so skip */ } /* end foreach ifa */ } /* end foreach ifn */ + pserialize_read_exit(s); + /* not found! */ return (NULL); } Index: src/sys/netinet6/icmp6.c diff -u src/sys/netinet6/icmp6.c:1.182 src/sys/netinet6/icmp6.c:1.183 --- src/sys/netinet6/icmp6.c:1.182 Mon Apr 4 07:37:07 2016 +++ src/sys/netinet6/icmp6.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: icmp6.c,v 1.182 2016/04/04 07:37:07 ozaki-r Exp $ */ +/* $NetBSD: icmp6.c,v 1.183 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.182 2016/04/04 07:37:07 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.183 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1650,7 +1650,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, st } } - IFNET_FOREACH(ifp) { + IFNET_READER_FOREACH(ifp) { addrsofif = 0; IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family != AF_INET6) @@ -1716,7 +1716,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *n struct icmp6_nodeinfo *nni6, struct ifnet *ifp0, int resid) { - struct ifnet *ifp = ifp0 ? ifp0 : IFNET_FIRST(); + struct ifnet *ifp = ifp0 ? ifp0 : IFNET_READER_FIRST(); struct in6_ifaddr *ifa6; struct ifaddr *ifa; struct ifnet *ifp_dep = NULL; @@ -1730,7 +1730,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *n again: - for (; ifp; ifp = TAILQ_NEXT(ifp, if_list)) + for (; ifp; ifp = IFNET_READER_NEXT(ifp)) { IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family != AF_INET6) Index: src/sys/netinet6/in6.c diff -u src/sys/netinet6/in6.c:1.198 src/sys/netinet6/in6.c:1.199 --- src/sys/netinet6/in6.c:1.198 Mon Apr 4 07:37:07 2016 +++ src/sys/netinet6/in6.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: in6.c,v 1.198 2016/04/04 07:37:07 ozaki-r Exp $ */ +/* $NetBSD: in6.c,v 1.199 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.198 2016/04/04 07:37:07 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.199 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -2178,8 +2178,10 @@ in6_setmaxmtu(void) { unsigned long maxmtu = 0; struct ifnet *ifp; + int s; - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { /* this function can be called during ifnet initialization */ if (!ifp->if_afdata[AF_INET6]) continue; @@ -2187,6 +2189,7 @@ in6_setmaxmtu(void) IN6_LINKMTU(ifp) > maxmtu) maxmtu = IN6_LINKMTU(ifp); } + pserialize_read_exit(s); if (maxmtu) /* update only when maxmtu is positive */ in6_maxmtu = maxmtu; } Index: src/sys/netinet6/in6_ifattach.c diff -u src/sys/netinet6/in6_ifattach.c:1.97 src/sys/netinet6/in6_ifattach.c:1.98 --- src/sys/netinet6/in6_ifattach.c:1.97 Wed Apr 27 07:51:14 2016 +++ src/sys/netinet6/in6_ifattach.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: in6_ifattach.c,v 1.97 2016/04/27 07:51:14 ozaki-r Exp $ */ +/* $NetBSD: in6_ifattach.c,v 1.98 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.97 2016/04/27 07:51:14 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.98 2016/05/12 02:24:17 ozaki-r Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -454,6 +454,7 @@ get_ifid(struct ifnet *ifp0, struct ifne struct in6_addr *in6) { struct ifnet *ifp; + int s; /* first, try to get it from the interface itself */ if (in6_get_hw_ifid(ifp0, in6) == 0) { @@ -470,7 +471,8 @@ get_ifid(struct ifnet *ifp0, struct ifne } /* next, try to get it from some other hardware interface */ - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { if (ifp == ifp0) continue; if (in6_get_hw_ifid(ifp, in6) != 0) @@ -487,6 +489,7 @@ get_ifid(struct ifnet *ifp0, struct ifne goto success; } } + pserialize_read_exit(s); #if 0 /* get from hostid - only for certain architectures */ @@ -954,6 +957,7 @@ in6_tmpaddrtimer(void *ignored_arg) struct nd_ifinfo *ndi; u_int8_t nullbuf[8]; struct ifnet *ifp; + int s; mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); @@ -963,7 +967,8 @@ in6_tmpaddrtimer(void *ignored_arg) ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL); memset(nullbuf, 0, sizeof(nullbuf)); - IFNET_FOREACH(ifp) { + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { ndi = ND_IFINFO(ifp); if (memcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { /* @@ -974,6 +979,7 @@ in6_tmpaddrtimer(void *ignored_arg) ndi->randomseed1, ndi->randomid); } } + pserialize_read_exit(s); KERNEL_UNLOCK_ONE(NULL); mutex_exit(softnet_lock); Index: src/sys/netinet6/nd6.c diff -u src/sys/netinet6/nd6.c:1.193 src/sys/netinet6/nd6.c:1.194 --- src/sys/netinet6/nd6.c:1.193 Tue Apr 26 09:30:01 2016 +++ src/sys/netinet6/nd6.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: nd6.c,v 1.193 2016/04/26 09:30:01 ozaki-r Exp $ */ +/* $NetBSD: nd6.c,v 1.194 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.193 2016/04/26 09:30:01 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.194 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -2090,12 +2090,15 @@ nd6_slowtimo(void *ignored_arg) { struct nd_ifinfo *nd6if; struct ifnet *ifp; + int s; mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, nd6_slowtimo, NULL); - IFNET_FOREACH(ifp) { + + s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { nd6if = ND_IFINFO(ifp); if (nd6if->basereachable && /* already initialized */ (nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) { @@ -2109,6 +2112,8 @@ nd6_slowtimo(void *ignored_arg) nd6if->reachable = ND_COMPUTE_RTIME(nd6if->basereachable); } } + pserialize_read_exit(s); + KERNEL_UNLOCK_ONE(NULL); mutex_exit(softnet_lock); } Index: src/sys/netinet6/raw_ip6.c diff -u src/sys/netinet6/raw_ip6.c:1.142 src/sys/netinet6/raw_ip6.c:1.143 --- src/sys/netinet6/raw_ip6.c:1.142 Tue Apr 26 08:44:45 2016 +++ src/sys/netinet6/raw_ip6.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: raw_ip6.c,v 1.142 2016/04/26 08:44:45 ozaki-r Exp $ */ +/* $NetBSD: raw_ip6.c,v 1.143 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.142 2016/04/26 08:44:45 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.143 2016/05/12 02:24:17 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_ipsec.h" @@ -667,7 +667,7 @@ rip6_bind(struct socket *so, struct sock if (addr->sin6_len != sizeof(*addr)) return EINVAL; - if (IFNET_EMPTY() || addr->sin6_family != AF_INET6) + if (IFNET_READER_EMPTY() || addr->sin6_family != AF_INET6) return EADDRNOTAVAIL; if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0) @@ -712,7 +712,7 @@ rip6_connect(struct socket *so, struct s KASSERT(in6p != NULL); KASSERT(nam != NULL); - if (IFNET_EMPTY()) + if (IFNET_READER_EMPTY()) return EADDRNOTAVAIL; if (addr->sin6_family != AF_INET6) return EAFNOSUPPORT; Index: src/sys/netipsec/xform_ipip.c diff -u src/sys/netipsec/xform_ipip.c:1.37 src/sys/netipsec/xform_ipip.c:1.38 --- src/sys/netipsec/xform_ipip.c:1.37 Tue Jan 26 06:00:10 2016 +++ src/sys/netipsec/xform_ipip.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: xform_ipip.c,v 1.37 2016/01/26 06:00:10 knakahara Exp $ */ +/* $NetBSD: xform_ipip.c,v 1.38 2016/05/12 02:24:17 ozaki-r Exp $ */ /* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ /* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.37 2016/01/26 06:00:10 knakahara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.38 2016/05/12 02:24:17 ozaki-r Exp $"); /* * IP-inside-IP processing @@ -333,7 +333,8 @@ _ipip_input(struct mbuf *m, int iphlen, if ((m->m_pkthdr.rcvif == NULL || !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && ipip_allow != 2) { - IFNET_FOREACH(ifp) { + int s = pserialize_read_enter(); + IFNET_READER_FOREACH(ifp) { IFADDR_FOREACH(ifa, ifp) { #ifdef INET if (ipo) { @@ -345,6 +346,7 @@ _ipip_input(struct mbuf *m, int iphlen, if (sin->sin_addr.s_addr == ipo->ip_src.s_addr) { + pserialize_read_exit(s); IPIP_STATINC(IPIP_STAT_SPOOF); m_freem(m); return; @@ -361,6 +363,7 @@ _ipip_input(struct mbuf *m, int iphlen, sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { + pserialize_read_exit(s); IPIP_STATINC(IPIP_STAT_SPOOF); m_freem(m); return; @@ -370,6 +373,7 @@ _ipip_input(struct mbuf *m, int iphlen, #endif /* INET6 */ } } + pserialize_read_exit(s); } /* Statistics */ Index: src/sys/rump/librump/rumpnet/net_stub.c diff -u src/sys/rump/librump/rumpnet/net_stub.c:1.22 src/sys/rump/librump/rumpnet/net_stub.c:1.23 --- src/sys/rump/librump/rumpnet/net_stub.c:1.22 Fri Apr 15 01:35:26 2016 +++ src/sys/rump/librump/rumpnet/net_stub.c Thu May 12 02:24:17 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: net_stub.c,v 1.22 2016/04/15 01:35:26 ozaki-r Exp $ */ +/* $NetBSD: net_stub.c,v 1.23 2016/05/12 02:24:17 ozaki-r Exp $ */ /* * Copyright (c) 2008 Antti Kantee. All Rights Reserved. @@ -26,11 +26,14 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: net_stub.c,v 1.22 2016/04/15 01:35:26 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: net_stub.c,v 1.23 2016/05/12 02:24:17 ozaki-r Exp $"); +#include <sys/mutex.h> #include <sys/param.h> #include <sys/protosw.h> #include <sys/socketvar.h> +#include <sys/pslist.h> +#include <sys/psref.h> #include <net/if.h> #include <net/route.h> @@ -65,6 +68,9 @@ __weak_alias(pppoe_input,rumpnet_stub); __weak_alias(pppoedisc_input,rumpnet_stub); struct ifnet_head ifnet_list; +struct pslist_head ifnet_pslist; +struct psref_class *ifnet_psref_class; +kmutex_t ifnet_mtx; int compat_ifconf(u_long cmd, void *data)