Date: Thu, 23 Apr 2009 21:41:37 +0000 (UTC) From: Robert Watson <rwatson@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r191443 - head/sys/netinet Message-ID: <200904232141.n3NLfbLv000246@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rwatson Date: Thu Apr 23 21:41:37 2009 New Revision: 191443 URL: http://svn.freebsd.org/changeset/base/191443 Log: Reorganize in_control() so that invariants are more obvious, and so that it is easier to lock: - Handle the unsupported ioctl case at the beginning of in_control(), handing off to ifp->if_ioctl, rather than looking up interfaces and addresses unnecessarily in this case. - Make it an invariant that ifp is always non-NULL when running in_control()-implemented ioctls, simplifying the code structure. MFC after: 3 weeks Modified: head/sys/netinet/in.c Modified: head/sys/netinet/in.c ============================================================================== --- head/sys/netinet/in.c Thu Apr 23 21:27:06 2009 (r191442) +++ head/sys/netinet/in.c Thu Apr 23 21:41:37 2009 (r191443) @@ -202,7 +202,8 @@ in_len2mask(struct in_addr *mask, int le /* * Generic internet control operations (ioctl's). - * Ifp is 0 if not an interface-specific ioctl. + * + * ifp is NULL if not an interface-specific ioctl. */ /* ARGSUSED */ int @@ -227,7 +228,23 @@ in_control(struct socket *so, u_long cmd iaIsNew = 0; allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + /* + * Filter out ioctls we implement directly; forward the rest on to + * in_lifaddr_ioctl() and ifp->if_ioctl(). + */ switch (cmd) { + case SIOCAIFADDR: + case SIOCDIFADDR: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCGIFNETMASK: + case SIOCSIFADDR: + case SIOCSIFBRDADDR: + case SIOCSIFDSTADDR: + case SIOCSIFNETMASK: + break; + case SIOCALIFADDR: if (td != NULL) { error = priv_check(td, PRIV_NET_ADDIFADDR); @@ -252,46 +269,51 @@ in_control(struct socket *so, u_long cmd if (ifp == NULL) return (EINVAL); return in_lifaddr_ioctl(so, cmd, data, ifp, td); + + default: + if (ifp == NULL || ifp->if_ioctl == NULL) + return (EOPNOTSUPP); + return ((*ifp->if_ioctl)(ifp, cmd, data)); } + if (ifp == NULL) + return (EADDRNOTAVAIL); + /* * Find address for this interface, if it exists. * - * If an alias address was specified, find that one instead of - * the first one on the interface, if possible. + * If an alias address was specified, find that one instead of the + * first one on the interface, if possible. */ - if (ifp != NULL) { - dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; - 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) { - if (td == NULL || prison_check_ip4( - td->td_ucred, &dst) == 0) - ia = iap; + dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; + 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) { + if (td == NULL || prison_check_ip4(td->td_ucred, + &dst) == 0) + ia = iap; + break; + } + } + if (ia == NULL) { + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + iap = ifatoia(ifa); + if (iap->ia_addr.sin_family == AF_INET) { + if (td != NULL && + prison_check_ip4(td->td_ucred, + &iap->ia_addr.sin_addr) != 0) + continue; + ia = iap; break; } - if (ia == NULL) - TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - iap = ifatoia(ifa); - if (iap->ia_addr.sin_family == AF_INET) { - if (td != NULL && - prison_check_ip4(td->td_ucred, - &iap->ia_addr.sin_addr) != 0) - continue; - ia = iap; - break; - } - } - if (ia == NULL) - iaIsFirst = 1; + } } + if (ia == NULL) + iaIsFirst = 1; switch (cmd) { - case SIOCAIFADDR: case SIOCDIFADDR: - if (ifp == NULL) - return (EADDRNOTAVAIL); if (ifra->ifra_addr.sin_family == AF_INET) { for (oia = ia; ia; ia = TAILQ_NEXT(ia, ia_link)) { if (ia->ia_ifp == ifp && @@ -319,8 +341,6 @@ in_control(struct socket *so, u_long cmd return (error); } - if (ifp == NULL) - return (EADDRNOTAVAIL); if (ia == NULL) { ia = (struct in_ifaddr *) malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO); @@ -505,9 +525,7 @@ in_control(struct socket *so, u_long cmd break; default: - if (ifp == NULL || ifp->if_ioctl == NULL) - return (EOPNOTSUPP); - return ((*ifp->if_ioctl)(ifp, cmd, data)); + panic("in_control: unsupported ioctl"); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904232141.n3NLfbLv000246>