diff --git a/sys/compat/linux/linux.c b/sys/compat/linux/linux.c --- a/sys/compat/linux/linux.c +++ b/sys/compat/linux/linux.c @@ -278,7 +278,7 @@ ret = 0; CURVNET_SET(TD_TO_VNET(curthread)); NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(idx); + ifp = ifnet_byindex_attached(idx); if (ifp != NULL) ret = ifname_bsd_to_linux_ifp(ifp, lxname, len); NET_EPOCH_EXIT(et); diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c --- a/sys/dev/hyperv/netvsc/if_hn.c +++ b/sys/dev/hyperv/netvsc/if_hn.c @@ -4717,7 +4717,7 @@ continue; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(i); + ifp = ifnet_byindex_ori(i); /* XXXZL want detached VF ? */ if (ifp != NULL) { if (first) sbuf_printf(sb, "%s", if_name(ifp)); @@ -4763,7 +4763,7 @@ continue; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(i); + ifp = ifnet_byindex_ori(i); /* XXXZL: want detached ifnet ? */ if (ifp != NULL) { if (first) { sbuf_printf(sb, "%s:%s", if_name(ifp), diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -363,7 +363,7 @@ MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); struct ifnet * -ifnet_byindex(u_int idx) +ifnet_byindex_ori(u_int idx) { struct ifnet *ifp; @@ -380,17 +380,37 @@ return (ifp); } +struct ifnet * +ifnet_byindex_attached(u_int idx) +{ + struct ifnet *ifp, *iter; + + NET_EPOCH_ASSERT(); + CURVNET_ASSERT_SET(); + + ifp = ifnet_byindex_ori(idx); + if (ifp != NULL) { + /* + * XXXZL: This can be optimized... + */ + CK_STAILQ_FOREACH(iter, &V_ifnet, if_link) { + if (iter == ifp) + return (ifp); + } + } + return (NULL); +} + struct ifnet * ifnet_byindex_ref(u_int idx) { struct ifnet *ifp; - ifp = ifnet_byindex(idx); - if (ifp == NULL || (ifp->if_flags & IFF_DYING)) - return (NULL); - if (!if_try_ref(ifp)) - return (NULL); - return (ifp); + ifp = ifnet_byindex_attached(idx); + if (ifp != NULL && if_try_ref(ifp)) + return (ifp); + + return (NULL); } struct ifnet * @@ -1979,7 +1999,7 @@ * so do that if we can. */ if (af == AF_LINK) { - ifp = ifnet_byindex( + ifp = ifnet_byindex_attached( ((const struct sockaddr_dl *)addr)->sdl_index); return (ifp ? ifp->if_addr : NULL); } diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -981,7 +981,7 @@ return (EINVAL); /* XXX: should be ntohs() */ - ifp = ifnet_byindex(dl->sdl_index); + ifp = ifnet_byindex_attached(dl->sdl_index); if (ifp == NULL) { log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n", __func__, dl->sdl_index); diff --git a/sys/net/if_var.h b/sys/net/if_var.h --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -480,10 +480,12 @@ /* * Look up an ifnet given its index. The returned value protected from - * being freed by the network epoch. The _ref variant also acquires a - * reference that must be freed using if_rele(). + * being freed by the network epoch. The _attached variant filter only + * attached ifnet. The _ref variant also acquires a reference that must + * be freed using if_rele(). */ -if_t ifnet_byindex(u_int); +if_t ifnet_byindex_ori(u_int); +if_t ifnet_byindex_attached(u_int); if_t ifnet_byindex_ref(u_int); /* diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1289,7 +1289,7 @@ struct ifc_data ifd_new = { .flags = IFC_F_SYSSPACE, .unit = ifd->unit, .params = ¶ms }; NET_EPOCH_ENTER(et); - ifp_parent = ifnet_byindex(lattrs->ifi_index); + ifp_parent = ifnet_byindex_attached(lattrs->ifi_index); if (ifp_parent != NULL) strlcpy(params.vlr_parent, if_name(ifp_parent), sizeof(params.vlr_parent)); NET_EPOCH_EXIT(et); diff --git a/sys/net/route.c b/sys/net/route.c --- a/sys/net/route.c +++ b/sys/net/route.c @@ -375,7 +375,7 @@ return (NULL); if (sdl->sdl_index != 0) - return (ifnet_byindex(sdl->sdl_index)); + return (ifnet_byindex_attached(sdl->sdl_index)); if (sdl->sdl_nlen > 0) { char if_name[IF_NAMESIZE]; if (sdl->sdl_nlen + offsetof(struct sockaddr_dl, sdl_data) > sdl->sdl_len) diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c --- a/sys/net/route/nhop_ctl.c +++ b/sys/net/route/nhop_ctl.c @@ -136,7 +136,7 @@ */ if ((nh->nh_ifp->if_flags & IFF_LOOPBACK) && nh->gw_sa.sa_family == AF_LINK) { - aifp = ifnet_byindex(nh->gwl_sa.sdl_index); + aifp = ifnet_byindex_attached(nh->gwl_sa.sdl_index); if (aifp == NULL) { FIB_NH_LOG(LOG_WARNING, nh, "unable to get aifp for %s index %d", if_name(nh->nh_ifp), nh->gwl_sa.sdl_index); @@ -208,7 +208,7 @@ * compatible sa with shorter total length. */ struct sockaddr_dl *sdl = (struct sockaddr_dl *)gw; - struct ifnet *ifp = ifnet_byindex(sdl->sdl_index); + struct ifnet *ifp = ifnet_byindex_attached(sdl->sdl_index); if (ifp == NULL) { FIB_NH_LOG(LOG_DEBUG, nh, "error: invalid ifindex %d", sdl->sdl_index); diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -474,7 +474,7 @@ * Expose struct igmp_ifsoftc to userland, keyed by ifindex. * For use by ifmcstat(8). * - * SMPng: NOTE: Does an unlocked ifindex space read. + * SMPng: NOTE: Does an unlocked ifindex space read. XXXZL this apears wrong. * VIMAGE: Assume curvnet set by caller. The node handler itself * is not directly virtualized. */ @@ -507,7 +507,7 @@ error = ENOENT; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(name[0]); + ifp = ifnet_byindex_ori(name[0]); NET_EPOCH_EXIT(et); if (ifp == NULL) goto out_locked; @@ -3461,11 +3461,11 @@ ifindex = igmp_restore_context(m); /* - * Check if the ifnet still exists. This limits the scope of + * Check if the ifnet still attached. This limits the scope of * any race in the absence of a global ifp lock for low cost * (an array lookup). */ - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifp == NULL) { CTR3(KTR_IGMPV3, "%s: dropped %p as ifindex %u went away.", __func__, m, ifindex); diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -1436,7 +1436,7 @@ return (EINVAL); NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(gsr.gsr_interface); + ifp = ifnet_byindex_ori(gsr.gsr_interface); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -1641,7 +1641,7 @@ return (error); NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(msfr.msfr_ifindex); + ifp = ifnet_byindex_ori(msfr.msfr_ifindex); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifnet pointer left */ if (ifp == NULL) return (EINVAL); @@ -2326,7 +2326,7 @@ } NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(gsr.gsr_interface); + ifp = ifnet_byindex_ori(gsr.gsr_interface); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2473,7 +2473,7 @@ struct epoch_tracker et; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(mreqn.imr_ifindex); + ifp = ifnet_byindex_ori(mreqn.imr_ifindex); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2553,7 +2553,7 @@ gsa->sin.sin_port = 0; /* ignore port */ NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(msfr.msfr_ifindex); + ifp = ifnet_byindex_ori(msfr.msfr_ifindex); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2871,7 +2871,7 @@ ifindex = name[0]; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_ori(ifindex); if (ifp == NULL) { NET_EPOCH_EXIT(et); CTR2(KTR_IGMPV3, "%s: no ifp for ifindex %u", diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1063,7 +1063,7 @@ /* Validate the interface index if specified. */ if (pktinfo->ipi6_ifindex) { - ifp = ifnet_byindex(pktinfo->ipi6_ifindex); + ifp = ifnet_byindex_attached(pktinfo->ipi6_ifindex); if (ifp == NULL) return (ENXIO); } else diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c --- a/sys/netinet6/in6_mcast.c +++ b/sys/netinet6/in6_mcast.c @@ -1468,7 +1468,7 @@ * the reference. */ NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(gsr.gsr_interface); + ifp = ifnet_byindex_attached(gsr.gsr_interface); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -1696,7 +1696,7 @@ * epoch section all the way to where the interface is referenced. */ NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(msfr.msfr_ifindex); + ifp = ifnet_byindex_attached(msfr.msfr_ifindex); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -1888,7 +1888,7 @@ * FIXME: The KAME use of the unspecified address (::) * to join *all* multicast groups is currently unsupported. * - * XXXGL: this function multiple times uses ifnet_byindex() without + * XXXGL: this function multiple times uses ifnet_byindex_attached() without * proper protection - staying in epoch, or putting reference on ifnet. */ static int @@ -1939,7 +1939,7 @@ ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6); } else { NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(mreq.ipv6mr_interface); + ifp = ifnet_byindex_attached(mreq.ipv6mr_interface); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -1982,7 +1982,7 @@ ssa->sin6.sin6_scope_id = 0; } NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(gsr.gsr_interface); + ifp = ifnet_byindex_attached(gsr.gsr_interface); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2304,7 +2304,7 @@ */ if (ifindex != 0) { NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2331,7 +2331,7 @@ ifp = in6p_lookup_mcast_ifp(inp, &gsa->sin6); } else { NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); NET_EPOCH_EXIT(et); /* XXXGL: unsafe ifp */ } if (ifp == NULL) @@ -2465,7 +2465,7 @@ if (ifindex == 0) ifp = NULL; else { - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) { NET_EPOCH_EXIT(et); return (EADDRNOTAVAIL); @@ -2519,7 +2519,7 @@ gsa->sin6.sin6_port = 0; /* ignore port */ NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(msfr.msfr_ifindex); + ifp = ifnet_byindex_attached(msfr.msfr_ifindex); NET_EPOCH_EXIT(et); if (ifp == NULL) return (EADDRNOTAVAIL); @@ -2765,7 +2765,7 @@ * The filter mode is written out as a uint32_t, followed by * 0..n of struct in6_addr. * For use by ifmcstat(8). - * SMPng: NOTE: unlocked read of ifindex space. + * SMPng: NOTE: unlocked read of ifindex space. XXXZL: sounds wrong to me. */ static int sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS) @@ -2804,7 +2804,7 @@ ifindex = name[0]; NET_EPOCH_ENTER(et); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifp == NULL) { NET_EPOCH_EXIT(et); CTR2(KTR_MLD, "%s: no ifp for ifindex %u", diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -700,7 +700,7 @@ /* If the caller specify the outgoing interface explicitly, use it. */ if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) { /* XXX boundary check is assumed to be already done. */ - ifp = ifnet_byindex(pi->ipi6_ifindex); + ifp = ifnet_byindex_attached(pi->ipi6_ifindex); if (ifp != NULL && (norouteok || IN6_IS_ADDR_MULTICAST(dst))) { /* * we do not have to check or get the route for diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -687,7 +687,7 @@ } NET_EPOCH_ENTER(et); - if ((ifp = ifnet_byindex(mifcp->mif6c_pifi)) == NULL) { + if ((ifp = ifnet_byindex_ori(mifcp->mif6c_pifi)) == NULL) { NET_EPOCH_EXIT(et); MIF6_UNLOCK(); return (ENXIO); diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -836,7 +836,7 @@ dst_sa.sin6_scope_id == 0 || (src_sa.sin6_scope_id != 0 && src_sa.sin6_scope_id != dst_sa.sin6_scope_id) || - ifnet_byindex(dst_sa.sin6_scope_id) == NULL) { + ifnet_byindex_attached(dst_sa.sin6_scope_id) == NULL) { /* * If the destination network interface is not a * loopback interface, or the destination network @@ -2813,8 +2813,8 @@ return (EINVAL); /* - * ip6_setpktopt can call ifnet_byindex(), so it's imperative that we - * are in the network epoch here. + * ip6_setpktopt can call ifnet_byindex_attached(), so it's imperative + * that we are in the network epoch here. */ NET_EPOCH_ASSERT(); @@ -2956,7 +2956,7 @@ return (EINVAL); /* validate the interface index if specified. */ if (pktinfo->ipi6_ifindex) { - ifp = ifnet_byindex(pktinfo->ipi6_ifindex); + ifp = ifnet_byindex_attached(pktinfo->ipi6_ifindex); if (ifp == NULL) return (ENXIO); } diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -382,7 +382,7 @@ NET_EPOCH_ENTER(et); error = ENOENT; - ifp = ifnet_byindex(name[0]); + ifp = ifnet_byindex_attached(name[0]); if (ifp == NULL) goto out_locked; @@ -3078,7 +3078,7 @@ * any race in the absence of a global ifp lock for low cost * (an array lookup). */ - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifp == NULL) { CTR3(KTR_MLD, "%s: dropped %p as ifindex %u went away.", __func__, m, ifindex); diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -2413,9 +2413,10 @@ /* * XXXGL: this function should use ifnet_byindex_ref! + * XXXZL: V_nd6_defifp is only used within this function */ NET_EPOCH_ENTER(et); - V_nd6_defifp = ifnet_byindex(V_nd6_defifindex); + V_nd6_defifp = ifnet_byindex_attached(V_nd6_defifindex); NET_EPOCH_EXIT(et); if (V_nd6_defifp == NULL) return (EINVAL); diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c --- a/sys/netinet6/scope6.c +++ b/sys/netinet6/scope6.c @@ -179,7 +179,7 @@ struct epoch_tracker et; NET_EPOCH_ENTER(et); - if (!ifnet_byindex(idlist->s6id_list[i])) { + if (!ifnet_byindex_attached(idlist->s6id_list[i])) { /* * XXX: theoretically, there should be * no relationship between link IDs and @@ -338,7 +338,7 @@ * and links. */ NET_EPOCH_ENTER(et); - if (ifnet_byindex(zoneid) == NULL) { + if (ifnet_byindex_attached(zoneid) == NULL) { NET_EPOCH_EXIT(et); return (ENXIO); } @@ -372,7 +372,7 @@ NET_EPOCH_ENTER(et); /* sanity check */ - if (!ifnet_byindex(zoneid)) { + if (!ifnet_byindex_attached(zoneid)) { NET_EPOCH_EXIT(et); return (ENXIO); } @@ -506,7 +506,7 @@ in6_getlinkifnet(uint32_t zoneid) { - return (ifnet_byindex((u_short)zoneid)); + return (ifnet_byindex_attached((u_short)zoneid)); } /* diff --git a/sys/netlink/netlink_message_parser.c b/sys/netlink/netlink_message_parser.c --- a/sys/netlink/netlink_message_parser.c +++ b/sys/netlink/netlink_message_parser.c @@ -441,7 +441,7 @@ NET_EPOCH_ASSERT(); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (__predict_false(ifp == NULL)) { NLMSG_REPORT_ERR_MSG(npt, "nla type %d: ifindex %u invalid", nla->nla_type, ifindex); @@ -566,6 +566,7 @@ *(void **)target)); } +/* XXXZL: It appears not used anywhere */ int nlf_get_ifp(void *src, struct nl_pstate *npt, void *target) { @@ -575,7 +576,7 @@ NET_EPOCH_ASSERT(); ifindex = *((const u_int *)src); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifp == NULL) { NL_LOG(LOG_DEBUG, "ifindex %u invalid", ifindex); return (ENOENT); @@ -594,7 +595,7 @@ NET_EPOCH_ASSERT(); ifindex = *((const u_int *)src); - ifp = ifnet_byindex(ifindex); + ifp = ifnet_byindex_attached(ifindex); if (ifindex != 0 && ifp == NULL) { NL_LOG(LOG_DEBUG, "ifindex %u invalid", ifindex); return (ENOENT); diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c --- a/sys/netlink/route/iface.c +++ b/sys/netlink/route/iface.c @@ -1081,7 +1081,7 @@ NL_LOG(LOG_DEBUG2, "Start dump"); if (attrs.ifa_index != 0) { - ifp = ifnet_byindex(attrs.ifa_index); + ifp = ifnet_byindex_attached(attrs.ifa_index); if (ifp == NULL) error = ENOENT; else