Index: if.c =================================================================== --- if.c (revision 179487) +++ if.c (working copy) @@ -133,7 +133,6 @@ #endif int if_index = 0; -struct ifindex_entry *ifindex_table = NULL; int ifqmaxlen = IFQ_MAXLEN; struct ifnethead ifnet; /* depend on static init XXX */ struct ifgrouphead ifg_head; @@ -144,6 +143,11 @@ static int if_indexlim = 8; static struct knlist ifklist; +/* + * Table of ifnet/cdev by index. Locked with ifnet_lock. + */ +static struct ifindex_entry *ifindex_table = NULL; + static void filt_netdetach(struct knote *kn); static int filt_netdev(struct knote *kn, long hint); @@ -160,6 +164,57 @@ MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address"); MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); +struct ifnet * +ifnet_byindex(u_short idx) +{ + struct ifnet *ifp; + + IFNET_RLOCK(); + ifp = ifindex_table[idx].ife_ifnet; + IFNET_RUNLOCK(); + return (ifp); +} + +static void +ifnet_setbyindex(u_short idx, struct ifnet *ifp) +{ + + IFNET_WLOCK_ASSERT(); + + ifindex_table[idx].ife_ifnet = ifp; +} + +struct ifaddr * +ifaddr_byindex(u_short idx) +{ + struct ifaddr *ifa; + + IFNET_RLOCK(); + ifa = ifnet_byindex(idx)->if_addr; + IFNET_RUNLOCK(); + return (ifa); +} + +struct cdev * +ifdev_byindex(u_short idx) +{ + struct cdev *cdev; + + IFNET_RLOCK(); + cdev = ifindex_table[idx].ife_dev; + IFNET_RUNLOCK(); + return (cdev); +} + +static void +ifdev_setbyindex(u_short idx, struct cdev *cdev) +{ + + IFNET_WLOCK(); + ifindex_table[idx].ife_dev = cdev; + IFNET_WUNLOCK(); +} + static d_open_t netopen; static d_close_t netclose; static d_ioctl_t netioctl; @@ -298,8 +353,8 @@ TAILQ_INIT(&ifg_head); knlist_init(&ifklist, NULL, NULL, NULL, NULL); if_grow(); /* create initial table */ - ifdev_byindex(0) = make_dev(&net_cdevsw, 0, - UID_ROOT, GID_WHEEL, 0600, "network"); + ifdev_setbyindex(0, make_dev(&net_cdevsw, 0, UID_ROOT, GID_WHEEL, + 0600, "network")); if_clone_init(); } @@ -356,11 +411,14 @@ if (if_com_alloc[type] != NULL) { ifp->if_l2com = if_com_alloc[type](type, ifp); if (ifp->if_l2com == NULL) { + IFNET_WUNLOCK(); free(ifp, M_IFNET); return (NULL); } } - ifnet_byindex(ifp->if_index) = ifp; + IFNET_WLOCK(); + ifnet_setbyindex(ifp->if_index, ifp); + IFNET_WUNLOCK(); IF_ADDR_LOCK_INIT(ifp); return (ifp); @@ -394,17 +452,18 @@ return; } - IF_ADDR_LOCK_DESTROY(ifp); + IFNET_WLOCK(); + ifnet_setbyindex(ifp->if_index, NULL); - ifnet_byindex(ifp->if_index) = NULL; - /* XXX: should be locked with if_findindex() */ while (if_index > 0 && ifnet_byindex(if_index) == NULL) if_index--; + IFNET_WUNLOCK(); if (if_com_free[type] != NULL) if_com_free[type](ifp->if_l2com, type); + IF_ADDR_LOCK_DESTROY(ifp); free(ifp, M_IFNET); }; @@ -454,10 +513,9 @@ mac_ifnet_create(ifp); #endif - ifdev_byindex(ifp->if_index) = make_dev(&net_cdevsw, - unit2minor(ifp->if_index), - UID_ROOT, GID_WHEEL, 0600, "%s/%s", - net_cdevsw.d_name, ifp->if_xname); + ifdev_setbyindex(ifp->if_index, make_dev(&net_cdevsw, + unit2minor(ifp->if_index), UID_ROOT, GID_WHEEL, 0600, "%s/%s", + net_cdevsw.d_name, ifp->if_xname)); make_dev_alias(ifdev_byindex(ifp->if_index), "%s%d", net_cdevsw.d_name, ifp->if_index); @@ -706,7 +764,7 @@ */ ifp->if_addr = NULL; destroy_dev(ifdev_byindex(ifp->if_index)); - ifdev_byindex(ifp->if_index) = NULL; + ifdev_setbyindex(ifp->if_index, NULL); /* We can now free link ifaddr. */ if (!TAILQ_EMPTY(&ifp->if_addrhead)) { Index: if_var.h =================================================================== --- if_var.h (revision 179487) +++ if_var.h (working copy) @@ -636,6 +636,7 @@ mtx_init(&ifnet_lock, "ifnet", NULL, MTX_DEF | MTX_RECURSE) #define IFNET_WLOCK() mtx_lock(&ifnet_lock) #define IFNET_WUNLOCK() mtx_unlock(&ifnet_lock) +#define IFNET_WLOCK_ASSERT() mtx_assert(&ifnet_lock, MA_OWNED) #define IFNET_RLOCK() IFNET_WLOCK() #define IFNET_RUNLOCK() IFNET_WUNLOCK() @@ -644,17 +645,17 @@ struct cdev *ife_dev; }; -#define ifnet_byindex(idx) ifindex_table[(idx)].ife_ifnet + +struct ifnet *ifnet_byindex(u_short idx); /* * Given the index, ifaddr_byindex() returns the one and only * link-level ifaddr for the interface. You are not supposed to use * it to traverse the list of addresses associated to the interface. */ -#define ifaddr_byindex(idx) ifnet_byindex(idx)->if_addr -#define ifdev_byindex(idx) ifindex_table[(idx)].ife_dev +struct ifaddr *ifaddr_byindex(u_short idx); +struct cdev *ifdev_byindex(u_short idx); extern struct ifnethead ifnet; -extern struct ifindex_entry *ifindex_table; extern int ifqmaxlen; extern struct ifnet *loif; /* first loopback interface */ extern int if_index;