From dbdfe722ae7d36c0cea45862e301a2a68831af63 Mon Sep 17 00:00:00 2001 From: brian Date: Mon, 26 Oct 1998 19:07:36 +0000 Subject: [PATCH] Fix the interface alias code. Previously, I was expecting something like tun0: flags=blah 10.0.0.1 -> 10.0.0.100 10.0.0.2 -> 10.0.0.100 10.0.0.3 -> 10.0.0.100 to DTRT, despite the SIOCAIFADDR for each new alias returning -1 & EEXIST while adding the alias anyway. In real life, once we have the second alias with the same destination, nothing will route any more ! Also, because I was ignoring EEXIST, the dynamic IP assignment code was assigning duplicate addresses ('cos it was being lied to by iface_inAdd()). Now we have tun0: flags=blah 10.0.0.1 -> 255.255.255.255 10.0.0.2 -> 10.0.0.100 10.0.0.3 -> 255.255.255.255 This works - stuff bound to 10.1 & 10.3 will be considered alive by the kernel, and when they route back to the tun device, the packets get aliased to 10.2 and go out to 10.100 (as with the original plan). We still see the EEXIST in SIOCAIFADDR, but ignore it when our destination is 255.255.255.255, assuming that the alias *was* actually added. Additionally, ``iface add'' may now optionally be given only the interface address. The mask & destination default to 255.255.255.255. --- usr.sbin/ppp/command.c | 32 ++++++++++-------- usr.sbin/ppp/iface.c | 74 +++++++++++++++++++++++++++++++++++------- usr.sbin/ppp/ppp.8 | 18 ++++++++-- usr.sbin/ppp/ppp.8.m4 | 18 ++++++++-- 4 files changed, 113 insertions(+), 29 deletions(-) diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index a1b1789cac17..f474aca87aca 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -17,7 +17,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: command.c,v 1.168 1998/10/22 02:32:48 brian Exp $ + * $Id: command.c,v 1.169 1998/10/24 01:08:45 brian Exp $ * */ #include @@ -132,7 +132,7 @@ #define NEG_DNS 50 const char Version[] = "2.0"; -const char VersionDate[] = "$Date: 1998/10/22 02:32:48 $"; +const char VersionDate[] = "$Date: 1998/10/24 01:08:45 $"; static int ShowCommand(struct cmdargs const *); static int TerminalCommand(struct cmdargs const *); @@ -2321,21 +2321,27 @@ IfaceAddCommand(struct cmdargs const *arg) int bits, n, how; struct in_addr ifa, mask, brd; - if (arg->argc == arg->argn + 2) { - if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, &mask, &bits)) - return -1; - n = 1; - } else if (arg->argc == arg->argn + 3) { + if (arg->argc == arg->argn + 1) { if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) return -1; - if (!ParseAddr(NULL, 1, arg->argv + arg->argn + 1, &mask, NULL, NULL)) + mask.s_addr = brd.s_addr = INADDR_BROADCAST; + } else { + if (arg->argc == arg->argn + 2) { + if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, &mask, &bits)) + return -1; + n = 1; + } else if (arg->argc == arg->argn + 3) { + if (!ParseAddr(NULL, 1, arg->argv + arg->argn, &ifa, NULL, NULL)) + return -1; + if (!ParseAddr(NULL, 1, arg->argv + arg->argn + 1, &mask, NULL, NULL)) + return -1; + n = 2; + } else return -1; - n = 2; - } else - return -1; - if (!ParseAddr(NULL, 1, arg->argv + arg->argn + n, &brd, NULL, NULL)) - return -1; + if (!ParseAddr(NULL, 1, arg->argv + arg->argn + n, &brd, NULL, NULL)) + return -1; + } how = IFACE_ADD_LAST; if (arg->cmd->args) diff --git a/usr.sbin/ppp/iface.c b/usr.sbin/ppp/iface.c index c21769016143..bca10ee0c3c6 100644 --- a/usr.sbin/ppp/iface.c +++ b/usr.sbin/ppp/iface.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id:$ + * $Id: iface.c,v 1.1 1998/10/22 02:32:49 brian Exp $ */ #include @@ -232,6 +232,7 @@ iface_addr_Zap(const char *name, struct iface_addr *addr) me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); me->sin_addr = addr->ifa; peer->sin_addr = addr->brd; + log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(addr->ifa)); if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) log_Printf(LogWARN, "iface_addr_Zap: ioctl(SIOCDIFADDR, %s): %s\n", inet_ntoa(addr->ifa), strerror(errno)); @@ -256,7 +257,7 @@ int iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, struct in_addr brd, int how) { - int slot, s; + int slot, s, chg; struct ifaliasreq ifra; struct sockaddr_in *me, *peer, *msk; struct iface_addr *addr; @@ -284,27 +285,76 @@ iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask, 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. + * Instead, we tweak all previous address entries that match the + * to-be-added destination to 255.255.255.255 (w/ a similar netmask). + * There *may* be more than one - if the user has ``iface add''ed + * stuff previously. + */ + 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) { + 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 = iface->in_addr[chg].ifa; + msk->sin_addr = iface->in_addr[chg].mask; + peer->sin_addr = iface->in_addr[chg].brd; + log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(me->sin_addr)); + ID0ioctl(s, SIOCDIFADDR, &ifra); /* Don't care if it fails... */ + if (chg != slot) { + peer->sin_addr.s_addr = iface->in_addr[chg].brd.s_addr = + msk->sin_addr.s_addr = iface->in_addr[chg].mask.s_addr = + INADDR_BROADCAST; + iface->in_addr[chg].bits = 32; + log_Printf(LogDEBUG, "Add %s -> 255.255.255.255\n", + inet_ntoa(me->sin_addr)); + if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) { + /* Oops - that's bad(ish) news ! We've lost an alias ! */ + log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n", + inet_ntoa(me->sin_addr), strerror(errno)); + iface->in_addrs--; + bcopy(iface->in_addr + chg + 1, iface->in_addr + chg, + (iface->in_addrs - chg) * sizeof iface->in_addr[0]); + if (slot > chg) + slot--; + chg--; + } + } + } + } + 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; - /* - * Note: EEXIST is sometimes returned, despite the route actually being - * added ! - */ - if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) { - log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s\n", - strerror(errno)); + 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; } diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index de37467146ed..80e18321a5b8 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.126 1998/09/18 23:28:10 brian Exp $ +.\" $Id: ppp.8,v 1.127 1998/10/22 02:32:49 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 @@ -2488,7 +2488,7 @@ This command is used to control the interface used by .Ar Command may be one of the following: .Bl -tag -width XX -.It iface add[!] Ar addr[/bits| mask] peer +.It iface add[!] Ar addr[[/bits| mask] peer] Add the given .Ar addr mask peer combination to the interface. Instead of specifying @@ -2500,6 +2500,20 @@ If the given address already exists, the command fails unless the .Dq \&! is used - in which case the previous interface address entry is overwritten with the new one, allowing a change of netmask or peer address. +.Pp +If only +.Ar addr +is specified, +.Ar bits +defaults to +.Dq 32 +and +.Ar peer +defaults to +.Dq 255.255.255.255 . +This address (the broadcast address) is the only duplicate peer address that +.Nm +allows. .It iface clear If this command is used while .Nm diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index de37467146ed..80e18321a5b8 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -1,4 +1,4 @@ -.\" $Id: ppp.8,v 1.126 1998/09/18 23:28:10 brian Exp $ +.\" $Id: ppp.8,v 1.127 1998/10/22 02:32:49 brian Exp $ .Dd 20 September 1995 .Os FreeBSD .Dt PPP 8 @@ -2488,7 +2488,7 @@ This command is used to control the interface used by .Ar Command may be one of the following: .Bl -tag -width XX -.It iface add[!] Ar addr[/bits| mask] peer +.It iface add[!] Ar addr[[/bits| mask] peer] Add the given .Ar addr mask peer combination to the interface. Instead of specifying @@ -2500,6 +2500,20 @@ If the given address already exists, the command fails unless the .Dq \&! is used - in which case the previous interface address entry is overwritten with the new one, allowing a change of netmask or peer address. +.Pp +If only +.Ar addr +is specified, +.Ar bits +defaults to +.Dq 32 +and +.Ar peer +defaults to +.Dq 255.255.255.255 . +This address (the broadcast address) is the only duplicate peer address that +.Nm +allows. .It iface clear If this command is used while .Nm