During SIOCAIFADDR, if in_ifinit() fails and we've already added an
interface address, blow the address away again before returning the error. In in_ifinit(), if we get an error from rtinit() and we've also got a destination address, return the error rather than masking EEXISTS. Failing to create a host route when configuring an interface should be treated as an error.
This commit is contained in:
parent
4a57e677c7
commit
0f02fdac67
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=87124
@ -197,7 +197,9 @@ in_control(so, cmd, data, ifp, td)
|
||||
struct in_ifaddr *oia;
|
||||
struct in_aliasreq *ifra = (struct in_aliasreq *)data;
|
||||
struct sockaddr_in oldaddr;
|
||||
int error, hostIsNew, maskIsNew, s;
|
||||
int error, hostIsNew, iaIsNew, maskIsNew, s;
|
||||
|
||||
iaIsNew = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCALIFADDR:
|
||||
@ -294,6 +296,7 @@ in_control(so, cmd, data, ifp, td)
|
||||
if (!(ifp->if_flags & IFF_LOOPBACK))
|
||||
in_interfaces++;
|
||||
splx(s);
|
||||
iaIsNew = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -314,23 +317,23 @@ in_control(so, cmd, data, ifp, td)
|
||||
|
||||
case SIOCGIFADDR:
|
||||
*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCGIFBRDADDR:
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
return (EINVAL);
|
||||
*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCGIFDSTADDR:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
return (EINVAL);
|
||||
*((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCGIFNETMASK:
|
||||
*((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCSIFDSTADDR:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
@ -349,22 +352,25 @@ in_control(so, cmd, data, ifp, td)
|
||||
(struct sockaddr *)&ia->ia_dstaddr;
|
||||
rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
|
||||
}
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCSIFBRDADDR:
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
return (EINVAL);
|
||||
ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCSIFADDR:
|
||||
return (in_ifinit(ifp, ia,
|
||||
(struct sockaddr_in *) &ifr->ifr_addr, 1));
|
||||
error = in_ifinit(ifp, ia,
|
||||
(struct sockaddr_in *) &ifr->ifr_addr, 1);
|
||||
if (error != 0 && iaIsNew)
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCSIFNETMASK:
|
||||
ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
|
||||
ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
|
||||
break;
|
||||
return (0);
|
||||
|
||||
case SIOCAIFADDR:
|
||||
maskIsNew = 0;
|
||||
@ -395,6 +401,9 @@ in_control(so, cmd, data, ifp, td)
|
||||
if (ifra->ifra_addr.sin_family == AF_INET &&
|
||||
(hostIsNew || maskIsNew))
|
||||
error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
|
||||
if (error != 0 && iaIsNew)
|
||||
break;
|
||||
|
||||
if ((ifp->if_flags & IFF_BROADCAST) &&
|
||||
(ifra->ifra_broadaddr.sin_family == AF_INET))
|
||||
ia->ia_broadaddr = ifra->ifra_broadaddr;
|
||||
@ -420,19 +429,7 @@ in_control(so, cmd, data, ifp, td)
|
||||
in_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
|
||||
in_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Protect from ipintr() traversing address list
|
||||
* while we're modifying it.
|
||||
*/
|
||||
s = splnet();
|
||||
|
||||
ifa = &ia->ia_ifa;
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
|
||||
TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
splx(s);
|
||||
error = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -440,7 +437,19 @@ in_control(so, cmd, data, ifp, td)
|
||||
return (EOPNOTSUPP);
|
||||
return ((*ifp->if_ioctl)(ifp, cmd, data));
|
||||
}
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Protect from ipintr() traversing address list while we're modifying
|
||||
* it.
|
||||
*/
|
||||
s = splnet();
|
||||
TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
|
||||
TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
splx(s);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -716,6 +725,12 @@ in_ifinit(ifp, ia, sin, scrub)
|
||||
}
|
||||
if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
|
||||
if (error != 0 && ia->ia_dstaddr.sin_family == AF_INET) {
|
||||
ia->ia_addr = oldaddr;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* XXX check if the subnet route points to the same interface */
|
||||
if (error == EEXIST)
|
||||
error = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user