commit 2a51860533e251991aeaf77713c0bd284da83fe8 Author: Ryota Ozaki Date: Fri May 13 10:41:50 2016 +0900 Add if_get, if_get_byindex and if_put diff --git a/sys/net/if.c b/sys/net/if.c index 7f48bdb..2a72c39 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2119,12 +2119,92 @@ out: return ifp; } +/* + * Get a reference of an ifnet object by an interface name. + * The returned reference is protected by psref(9). The caller + * must release a returned reference by if_put after use. + */ +struct ifnet * +if_get(const char *name, struct psref *psref) +{ + struct ifnet *ifp; + 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. + */ + for (i = 0; i < IFNAMSIZ && *cp >= '0' && *cp <= '9'; i++, cp++) { + unit = unit * 10 + (*cp - '0'); + } + + /* + * If the number took all of the name, then it's a valid ifindex. + */ + if (i == IFNAMSIZ || (cp != name && *cp == '\0')) { + if (unit >= if_indexlim) + return NULL; + ifp = ifindex2ifnet[unit]; + if (ifp == NULL || ifp->if_output == if_nulloutput) + return NULL; + return 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) { + psref_acquire(psref, &ifp->if_psref, + ifnet_psref_class); + goto out; + } + } +out: + pserialize_read_exit(s); + return ifp; +} + +/* + * Release a reference of an ifnet object given by if_get or + * if_get_byindex. + */ +void +if_put(const struct ifnet *ifp, struct psref *psref) +{ + + psref_release(psref, &ifp->if_psref, ifnet_psref_class); +} + ifnet_t * if_byindex(u_int idx) { return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL; } +/* + * Get a reference of an ifnet object by an interface index. + * The returned reference is protected by psref(9). The caller + * must release a returned reference by if_put after use. + */ +ifnet_t * +if_get_byindex(u_int idx, struct psref *psref) +{ + ifnet_t *ifp; + int s; + + s = pserialize_read_enter(); + ifp = (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL; + if (ifp != NULL) + psref_acquire(psref, &ifp->if_psref, ifnet_psref_class); + pserialize_read_exit(s); + + return ifp; +} + /* common */ int ifioctl_common(struct ifnet *ifp, u_long cmd, void *data) diff --git a/sys/net/if.h b/sys/net/if.h index e2d0f87..69e55c9 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -912,6 +912,10 @@ extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *); int ifioctl_common(struct ifnet *, u_long, void *); int ifpromisc(struct ifnet *, int); struct ifnet *ifunit(const char *); +struct ifnet *if_get(const char *, struct psref *); +ifnet_t *if_byindex(u_int); +ifnet_t *if_get_byindex(u_int, struct psref *); +void if_put(const struct ifnet *, struct psref *); int if_addr_init(ifnet_t *, struct ifaddr *, bool); int if_do_dad(struct ifnet *); int if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *); @@ -1047,8 +1051,6 @@ extern kmutex_t ifnet_mtx; extern struct ifnet *lo0ifp; -ifnet_t * if_byindex(u_int); - /* * ifq sysctl support */