Restore historical behavior of in_control, which, when no matching address
is found, the first usable address is returned for legacy ioctls like SIOCGIFBRDADDR, SIOCGIFDSTADDR, SIOCGIFNETMASK and SIOCGIFADDR. While there also fix a subtle issue that a caller from a jail asking for INADDR_ANY may get the first IP of the host that do not belong to the jail. Submitted by: glebius Differential Revision: https://reviews.freebsd.org/D667
This commit is contained in:
parent
4e6f2e5a1e
commit
3fc68a2c42
@ -242,19 +242,26 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
|
||||
return (EADDRNOTAVAIL);
|
||||
|
||||
/*
|
||||
* For SIOCGIFADDR, pick the first address. For the rest of
|
||||
* ioctls, try to find specified address.
|
||||
* Find address for this interface, if it exists. If an
|
||||
* address was specified, find that one instead of the
|
||||
* first one on the interface, if possible.
|
||||
*/
|
||||
IF_ADDR_RLOCK(ifp);
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
if (cmd == SIOCGIFADDR || addr->sin_addr.s_addr == INADDR_ANY)
|
||||
break;
|
||||
if (ia->ia_addr.sin_addr.s_addr == addr->sin_addr.s_addr)
|
||||
break;
|
||||
}
|
||||
if (ifa == NULL)
|
||||
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
|
||||
if (ifa->ifa_addr->sa_family == AF_INET) {
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
if (prison_check_ip4(td->td_ucred,
|
||||
&ia->ia_addr.sin_addr) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ifa == NULL) {
|
||||
IF_ADDR_RUNLOCK(ifp);
|
||||
|
Loading…
Reference in New Issue
Block a user