diff options
author | brian <brian@cvs.openbsd.org> | 2001-03-25 01:38:14 +0000 |
---|---|---|
committer | brian <brian@cvs.openbsd.org> | 2001-03-25 01:38:14 +0000 |
commit | c97ded69a1166774c30654b41b463eb26177f9d6 (patch) | |
tree | 3488abaec17e80f3f474a8224d0656ce4b85ace3 /usr.sbin | |
parent | 64a2c8ccef31802636b2bb3dd413fd98bbd96eb8 (diff) |
If we're adding an interface address that is already one of the interface's
aliases with the same netmask and destination, don't remove it and then
re-add exactly the same thing.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ppp/ppp/iface.c | 87 |
1 files changed, 53 insertions, 34 deletions
diff --git a/usr.sbin/ppp/ppp/iface.c b/usr.sbin/ppp/ppp/iface.c index 666fc0ed41a..86bcfea1aff 100644 --- a/usr.sbin/ppp/ppp/iface.c +++ b/usr.sbin/ppp/ppp/iface.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $OpenBSD: iface.c,v 1.12 2000/12/14 13:24:02 brian Exp $ + * $OpenBSD: iface.c,v 1.13 2001/03/25 01:38:13 brian Exp $ */ #include <sys/param.h> @@ -252,7 +252,7 @@ int iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, struct in_addr brd, int how) { - int slot, s, chg; + int slot, s, chg, nochange; struct ifaliasreq ifra; struct sockaddr_in *me, *peer, *msk; struct iface_addr *addr; @@ -274,12 +274,6 @@ iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, } iface->in_addr = addr; - s = ID0socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) { - log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno)); - return 0; - } - /* * We've gotta be careful here. If we try to add an address with the * same destination as an existing interface, nothing will work. @@ -288,9 +282,26 @@ iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, * There *may* be more than one - if the user has ``iface add''ed * stuff previously. */ + nochange = 0; + s = -1; for (chg = 0; chg < iface->in_addrs; chg++) { if ((iface->in_addr[chg].brd.s_addr == brd.s_addr && brd.s_addr != INADDR_BROADCAST) || chg == slot) { + /* + * If we've found an entry that exactly matches what we want to add, + * don't remove it and then add it again. If we do, it's possible + * that the kernel will (correctly) ``tidy up'' any routes that use + * the IP number as a destination. + */ + if (chg == slot && iface->in_addr[chg].mask.s_addr == mask.s_addr) { + nochange = 1; + continue; + } + if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno)); + return 0; + } + memset(&ifra, '\0', sizeof ifra); strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1); me = (struct sockaddr_in *)&ifra.ifra_addr; @@ -325,35 +336,43 @@ iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, } } - memset(&ifra, '\0', sizeof ifra); - strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1); - me = (struct sockaddr_in *)&ifra.ifra_addr; - msk = (struct sockaddr_in *)&ifra.ifra_mask; - peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; - me->sin_family = msk->sin_family = peer->sin_family = AF_INET; - me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in); - me->sin_addr = ifa; - msk->sin_addr = mask; - peer->sin_addr = brd; - - if (log_IsKept(LogDEBUG)) { - char buf[16]; - - strncpy(buf, inet_ntoa(brd), sizeof buf-1); - buf[sizeof buf - 1] = '\0'; - log_Printf(LogDEBUG, "Add %s -> %s\n", inet_ntoa(ifa), buf); + if (!nochange) { + if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno)); + return 0; + } + memset(&ifra, '\0', sizeof ifra); + strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1); + me = (struct sockaddr_in *)&ifra.ifra_addr; + msk = (struct sockaddr_in *)&ifra.ifra_mask; + peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; + me->sin_family = msk->sin_family = peer->sin_family = AF_INET; + me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in); + me->sin_addr = ifa; + msk->sin_addr = mask; + peer->sin_addr = brd; + + if (log_IsKept(LogDEBUG)) { + char buf[16]; + + strncpy(buf, inet_ntoa(brd), sizeof buf-1); + buf[sizeof buf - 1] = '\0'; + log_Printf(LogDEBUG, "Add %s -> %s\n", inet_ntoa(ifa), buf); + } + + /* An EEXIST failure w/ brd == INADDR_BROADCAST is ok (and works!) */ + if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && + (brd.s_addr != INADDR_BROADCAST || errno != EEXIST)) { + log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n", + inet_ntoa(ifa), strerror(errno)); + ID0ioctl(s, SIOCDIFADDR, &ifra); /* EEXIST ? */ + close(s); + return 0; + } } - /* An EEXIST failure w/ brd == INADDR_BROADCAST is ok (and works!) */ - if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && - (brd.s_addr != INADDR_BROADCAST || errno != EEXIST)) { - log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n", - inet_ntoa(ifa), strerror(errno)); - ID0ioctl(s, SIOCDIFADDR, &ifra); /* EEXIST ? */ + if (s != -1) close(s); - return 0; - } - close(s); if (slot == iface->in_addrs) { /* We're adding a new interface address */ |