summaryrefslogtreecommitdiff
path: root/usr.sbin/ppp/iface.c
diff options
context:
space:
mode:
authorBrian Somers <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
committerBrian Somers <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
commit30949fd4b52d91188c23cb2ca0d130d89bb1678c (patch)
treeb09d46345a558a45e66b435c4386d76cf53405d3 /usr.sbin/ppp/iface.c
parent135047c346cac167948b8cbbe9529d74ef0b7dad (diff)
downloadsrc-test2-30949fd4b52d91188c23cb2ca0d130d89bb1678c.tar.gz
src-test2-30949fd4b52d91188c23cb2ca0d130d89bb1678c.zip
Notes
Diffstat (limited to 'usr.sbin/ppp/iface.c')
-rw-r--r--usr.sbin/ppp/iface.c561
1 files changed, 329 insertions, 232 deletions
diff --git a/usr.sbin/ppp/iface.c b/usr.sbin/ppp/iface.c
index 9676b38ec271..d8fa2067dd60 100644
--- a/usr.sbin/ppp/iface.c
+++ b/usr.sbin/ppp/iface.c
@@ -31,10 +31,15 @@
#include <netinet/in.h>
#include <net/if.h>
#include <net/if_dl.h>
+#include <net/if_var.h>
#include <net/route.h>
#include <arpa/inet.h>
#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
+#ifndef NOINET6
+#include <netinet6/nd6.h>
+#endif
#include <sys/un.h>
#include <errno.h>
@@ -60,6 +65,8 @@
#include "throughput.h"
#include "slcompress.h"
#include "descriptor.h"
+#include "ncpaddr.h"
+#include "ip.h"
#include "ipcp.h"
#include "filter.h"
#include "lcp.h"
@@ -69,32 +76,17 @@
#ifndef NORADIUS
#include "radius.h"
#endif
+#include "ipv6cp.h"
+#include "ncp.h"
#include "bundle.h"
#include "prompt.h"
#include "iface.h"
-static int
-bitsinmask(struct in_addr mask)
-{
- u_int32_t bitmask, maskaddr;
- int bits;
-
- bitmask = 0xffffffff;
- maskaddr = ntohl(mask.s_addr);
- for (bits = 32; bits >= 0; bits--) {
- if (maskaddr == bitmask)
- break;
- bitmask &= ~(1 << (32 - bits));
- }
-
- return bits;
-}
-
struct iface *
iface_Create(const char *name)
{
- int mib[6], s, maxtries, err;
+ int mib[6], maxtries, err;
size_t needed, namelen;
char *buf, *ptr, *end;
struct if_msghdr *ifm;
@@ -104,12 +96,6 @@ iface_Create(const char *name)
struct iface *iface;
struct iface_addr *addr;
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- fprintf(stderr, "iface_Create: socket(): %s\n", strerror(errno));
- return NULL;
- }
-
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
@@ -122,20 +108,17 @@ iface_Create(const char *name)
do {
if (maxtries-- == 0 || (err && err != ENOMEM)) {
fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
- close(s);
return NULL;
}
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
strerror(errno));
- close(s);
return NULL;
}
if ((buf = (char *)malloc(needed)) == NULL) {
fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
- close(s);
return NULL;
}
@@ -166,8 +149,8 @@ iface_Create(const char *name)
iface->index = ifm->ifm_index;
iface->flags = ifm->ifm_flags;
iface->mtu = 0;
- iface->in_addrs = 0;
- iface->in_addr = NULL;
+ iface->addrs = 0;
+ iface->addr = NULL;
}
ptr += ifm->ifm_msglen; /* First ifa_msghdr */
for (; ptr < end; ptr += ifam->ifam_msglen) {
@@ -180,255 +163,350 @@ iface_Create(const char *name)
/* Found a configured interface ! */
iface_ParseHdr(ifam, sa);
- if (sa[RTAX_IFA] && sa[RTAX_IFA]->sa_family == AF_INET) {
+ if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET
+#ifndef NOINET6
+ || sa[RTAX_IFA]->sa_family == AF_INET6
+#endif
+ )) {
/* Record the address */
- addr = (struct iface_addr *)realloc
- (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
+ addr = (struct iface_addr *)
+ realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
if (addr == NULL)
break;
- iface->in_addr = addr;
-
- addr += iface->in_addrs;
- iface->in_addrs++;
+ iface->addr = addr;
- addr->ifa = ((struct sockaddr_in *)sa[RTAX_IFA])->sin_addr;
+ addr += iface->addrs;
+ iface->addrs++;
+ ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]);
if (sa[RTAX_BRD])
- addr->brd = ((struct sockaddr_in *)sa[RTAX_BRD])->sin_addr;
+ ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]);
else
- addr->brd.s_addr = INADDR_ANY;
-
- if (sa[RTAX_NETMASK])
- addr->mask = ((struct sockaddr_in *)sa[RTAX_NETMASK])->sin_addr;
- else
- addr->mask.s_addr = INADDR_ANY;
-
- addr->bits = bitsinmask(addr->mask);
+ ncpaddr_init(&addr->peer);
}
}
}
}
free(buf);
- close(s);
return iface;
}
+static int
+iface_addr_Zap(const char *name, struct iface_addr *addr, int s)
+{
+ struct ifaliasreq ifra;
+#ifndef NOINET6
+ struct in6_aliasreq ifra6;
+#endif
+ struct sockaddr_in *me4, *msk4, *peer4;
+ struct sockaddr_storage ssme, sspeer, ssmsk;
+ int res;
+
+ ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
+ ncpaddr_getsa(&addr->peer, &sspeer);
+ res = 0;
+
+ switch (ncprange_family(&addr->ifa)) {
+ case AF_INET:
+ memset(&ifra, '\0', sizeof ifra);
+ strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
+
+ me4 = (struct sockaddr_in *)&ifra.ifra_addr;
+ memcpy(me4, &ssme, sizeof *me4);
+
+ msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
+ memcpy(msk4, &ssmsk, sizeof *msk4);
+
+ peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
+ peer4->sin_family = AF_INET;
+ peer4->sin_len = sizeof(*peer4);
+ peer4->sin_addr.s_addr = INADDR_NONE;
+ } else
+ memcpy(peer4, &sspeer, sizeof *peer4);
+
+ res = ID0ioctl(s, SIOCDIFADDR, &ifra);
+ break;
+
+#ifndef NOINET6
+ case AF_INET6:
+ memset(&ifra6, '\0', sizeof ifra6);
+ strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
+
+ memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
+ memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
+ ifra6.ifra_prefixmask.sin6_family = AF_UNSPEC;
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
+ ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
+ else
+ memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
+ ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+ ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+
+ res = ID0ioctl(s, SIOCDIFADDR_IN6, &ifra6);
+ break;
+#endif
+ }
+
+ if (res == -1) {
+ char dst[40];
+ const char *end =
+#ifndef NOINET6
+ ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
+#endif
+ "";
+
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
+ log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s): %s\n",
+ end, ncprange_ntoa(&addr->ifa), strerror(errno));
+ else {
+ snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
+ log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
+ end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
+ }
+ }
+
+ return res != -1;
+}
+
static void
-iface_addr_Zap(const char *name, struct iface_addr *addr)
+iface_addr_Add(const char *name, struct iface_addr *addr, int s)
{
struct ifaliasreq ifra;
- struct sockaddr_in *me, *peer;
- int s;
+#ifndef NOINET6
+ struct in6_aliasreq ifra6;
+#endif
+ struct sockaddr_in *me4, *msk4, *peer4;
+ struct sockaddr_storage ssme, sspeer, ssmsk;
+ int res;
- s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- log_Printf(LogERROR, "iface_addr_Zap: socket(): %s\n", strerror(errno));
- else {
+ ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
+ ncpaddr_getsa(&addr->peer, &sspeer);
+ res = 0;
+
+ switch (ncprange_family(&addr->ifa)) {
+ case AF_INET:
memset(&ifra, '\0', sizeof ifra);
strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
- me = (struct sockaddr_in *)&ifra.ifra_addr;
- peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
- me->sin_family = peer->sin_family = AF_INET;
- 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));
- close(s);
+
+ me4 = (struct sockaddr_in *)&ifra.ifra_addr;
+ memcpy(me4, &ssme, sizeof *me4);
+
+ msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
+ memcpy(msk4, &ssmsk, sizeof *msk4);
+
+ peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
+ peer4->sin_family = AF_INET;
+ peer4->sin_len = sizeof(*peer4);
+ peer4->sin_addr.s_addr = INADDR_NONE;
+ } else
+ memcpy(peer4, &sspeer, sizeof *peer4);
+
+ res = ID0ioctl(s, SIOCAIFADDR, &ifra);
+ break;
+
+#ifndef NOINET6
+ case AF_INET6:
+ memset(&ifra6, '\0', sizeof ifra6);
+ strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
+
+ memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
+ memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
+ ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
+ else
+ memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
+ ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+ ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+
+ res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6);
+ break;
+#endif
+ }
+
+ if (res == -1) {
+ char dst[40];
+ const char *end =
+#ifndef NOINET6
+ ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
+#endif
+ "";
+
+ if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
+ log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n",
+ end, ncprange_ntoa(&addr->ifa), strerror(errno));
+ else {
+ snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
+ log_Printf(LogWARN, "iface add: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
+ end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
+ }
}
}
+
void
-iface_inClear(struct iface *iface, int how)
+iface_Clear(struct iface *iface, struct ncp *ncp, int family, int how)
{
- int n, addrs;
+ int addrs, af, inskip, in6skip, n, s4 = -1, s6 = -1, *s;
+
+ if (iface->addrs) {
+ inskip = in6skip = how == IFACE_CLEAR_ALL ? 0 : 1;
+ addrs = 0;
+
+ for (n = 0; n < iface->addrs; n++) {
+ af = ncprange_family(&iface->addr[n].ifa);
+ if (family == 0 || family == af) {
+ if (!iface->addr[n].system && (how & IFACE_SYSTEM))
+ continue;
+ switch (af) {
+ case AF_INET:
+ if (inskip) {
+ inskip = 0;
+ continue;
+ }
+ s = &s4;
+ break;
+
+#ifndef NOINET6
+ case AF_INET6:
+ if (in6skip) {
+ in6skip = 0;
+ continue;
+ }
+ s = &s6;
+ break;
+#endif
+ }
- if (iface->in_addrs) {
- addrs = n = how == IFACE_CLEAR_ALL ? 0 : 1;
- for (; n < iface->in_addrs; n++)
- iface_addr_Zap(iface->name, iface->in_addr + n);
+ if (*s == -1 && (*s = ID0socket(af, SOCK_DGRAM, 0)) == -1)
+ log_Printf(LogERROR, "iface_Clear: socket(): %s\n", strerror(errno));
+ else if (iface_addr_Zap(iface->name, iface->addr + n, *s)) {
+ ncp_IfaceAddrDeleted(ncp, iface->addr + n);
+ bcopy(iface->addr + n + 1, iface->addr + n,
+ (iface->addrs - n - 1) * sizeof *iface->addr);
+ iface->addrs--;
+ n--;
+ }
+ }
+ }
- iface->in_addrs = addrs;
/* Don't bother realloc()ing - we have little to gain */
+
+ if (s4)
+ close(s4);
+ if (s6)
+ close(s6);
}
}
int
-iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask,
- struct in_addr brd, int how)
+iface_Add(struct iface *iface, struct ncp *ncp, const struct ncprange *ifa,
+ const struct ncpaddr *peer, int how)
{
- int slot, s, chg, nochange;
- struct ifaliasreq ifra;
- struct sockaddr_in *me, *peer, *msk;
+ int af, n, s, width;
+ struct ncpaddr ifaddr, ncplocal;
struct iface_addr *addr;
- for (slot = 0; slot < iface->in_addrs; slot++)
- if (iface->in_addr[slot].ifa.s_addr == ifa.s_addr) {
- if (how & IFACE_FORCE_ADD)
- break;
- else
- /* errno = EEXIST; */
- return 0;
- }
-
- addr = (struct iface_addr *)realloc
- (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
- if (addr == NULL) {
- log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
+ af = ncprange_family(ifa);
+ if ((s = ID0socket(af, SOCK_DGRAM, 0)) == -1) {
+ log_Printf(LogERROR, "iface_Add: socket(): %s\n", strerror(errno));
return 0;
}
- iface->in_addr = addr;
+ ncprange_getaddr(ifa, &ncplocal);
- /*
- * 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.
- */
- 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) {
- if (brd.s_addr == iface->in_addr[slot].brd.s_addr)
- nochange = 1;
- /*
- * If only the destination address has changed, the SIOCAIFADDR
- * we do after the current loop will change it.
- */
- continue;
- }
- if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
- return 0;
+ for (n = 0; n < iface->addrs; n++) {
+ if (ncprange_contains(&iface->addr[n].ifa, &ncplocal)) {
+ if (!(how & IFACE_FORCE_ADD)) {
+ close(s);
+ return 0; /* errno = EEXIST; */
}
- 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--;
- }
+ if (ncprange_equal(&iface->addr[n].ifa, ifa) &&
+ ncpaddr_equal(&iface->addr[n].peer, peer)) {
+ close(s);
+ return 1; /* Already there */
}
- }
- }
- 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;
+ width =
+#ifndef NOINET6
+ (af == AF_INET6) ? 128 :
+#endif
+ 32;
+ iface_addr_Zap(iface->name, iface->addr + n, s);
+ ncprange_setwidth(&iface->addr[n].ifa, width);
+ ncprange_getaddr(&iface->addr[n].ifa, &ifaddr);
+ if (ncpaddr_equal(&ifaddr, &ncplocal))
+ ncpaddr_copy(&iface->addr[n].peer, peer);
+ else
+ ncpaddr_init(&iface->addr[n].peer);
+ iface_addr_Add(iface->name, iface->addr + n, s);
+ if (ncpaddr_equal(&ifaddr, &ncplocal)) {
+ close(s);
+ ncp_IfaceAddrAdded(ncp, iface->addr + n);
+ return 1;
+ }
}
}
- if (s != -1)
+ addr = (struct iface_addr *)realloc
+ (iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
+ if (addr == NULL) {
+ log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
close(s);
+ return 0;
+ }
+ iface->addr = addr;
- if (slot == iface->in_addrs) {
- /* We're adding a new interface address */
+ if (how & IFACE_ADD_FIRST) {
+ /* Stuff it at the start of our list */
+ n = 0;
+ bcopy(iface->addr, iface->addr + 1, iface->addrs * sizeof *iface->addr);
+ } else
+ n = iface->addrs;
- if (how & IFACE_ADD_FIRST) {
- /* Stuff it at the start of our list */
- slot = 0;
- bcopy(iface->in_addr, iface->in_addr + 1,
- iface->in_addrs * sizeof iface->in_addr[0]);
- }
+ iface->addrs++;
+ ncprange_copy(&iface->addr[n].ifa, ifa);
+ ncpaddr_copy(&iface->addr[n].peer, peer);
+ iface->addr[n].system = !!(how & IFACE_SYSTEM);
+ iface_addr_Add(iface->name, iface->addr + n, s);
- iface->in_addrs++;
- } else if (how & IFACE_ADD_FIRST) {
- /* Shift it up to the first slot */
- bcopy(iface->in_addr, iface->in_addr + 1, slot * sizeof iface->in_addr[0]);
- slot = 0;
- }
-
- iface->in_addr[slot].ifa = ifa;
- iface->in_addr[slot].mask = mask;
- iface->in_addr[slot].brd = brd;
- iface->in_addr[slot].bits = bitsinmask(iface->in_addr[slot].mask);
+ close(s);
+ ncp_IfaceAddrAdded(ncp, iface->addr + n);
return 1;
}
int
-iface_inDelete(struct iface *iface, struct in_addr ip)
+iface_Delete(struct iface *iface, struct ncp *ncp, const struct ncpaddr *del)
{
- int n;
-
- for (n = 0; n < iface->in_addrs; n++)
- if (iface->in_addr[n].ifa.s_addr == ip.s_addr) {
- iface_addr_Zap(iface->name, iface->in_addr + n);
- bcopy(iface->in_addr + n + 1, iface->in_addr + n,
- (iface->in_addrs - n - 1) * sizeof iface->in_addr[0]);
- iface->in_addrs--;
- return 1;
+ struct ncpaddr found;
+ int n, res, s;
+
+ if ((s = ID0socket(ncpaddr_family(del), SOCK_DGRAM, 0)) == -1) {
+ log_Printf(LogERROR, "iface_Delete: socket(): %s\n", strerror(errno));
+ return 0;
+ }
+
+ for (n = res = 0; n < iface->addrs; n++) {
+ ncprange_getaddr(&iface->addr[n].ifa, &found);
+ if (ncpaddr_equal(&found, del)) {
+ iface_addr_Zap(iface->name, iface->addr + n, s);
+ ncp_IfaceAddrDeleted(ncp, iface->addr + n);
+ bcopy(iface->addr + n + 1, iface->addr + n,
+ (iface->addrs - n - 1) * sizeof *iface->addr);
+ iface->addrs--;
+ res = 1;
+ break;
}
+ }
- return 0;
+ close(s);
+
+ return res;
}
#define IFACE_ADDFLAGS 1
@@ -495,7 +573,7 @@ iface_Destroy(struct iface *iface)
if (iface != NULL) {
free(iface->name);
- free(iface->in_addr);
+ free(iface->addr);
free(iface);
}
}
@@ -527,8 +605,13 @@ struct {
int
iface_Show(struct cmdargs const *arg)
{
+ struct ncpaddr ncpaddr;
struct iface *iface = arg->bundle->iface, *current;
int f, flags;
+#ifndef NOINET6
+ int scopeid, width;
+#endif
+ struct in_addr mask;
current = iface_Create(iface->name);
flags = iface->flags = current->flags;
@@ -542,20 +625,34 @@ iface_Show(struct cmdargs const *arg)
flags &= ~if_flags[f].flag;
}
prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", iface->mtu,
- iface->in_addrs, iface->in_addrs == 1 ? "" : "es");
-
- for (f = 0; f < iface->in_addrs; f++) {
- prompt_Printf(arg->prompt, " %s", inet_ntoa(iface->in_addr[f].ifa));
- if (iface->in_addr[f].bits >= 0)
- prompt_Printf(arg->prompt, "/%d", iface->in_addr[f].bits);
- if (iface->flags & IFF_POINTOPOINT)
- prompt_Printf(arg->prompt, " -> %s", inet_ntoa(iface->in_addr[f].brd));
- else if (iface->flags & IFF_BROADCAST)
- prompt_Printf(arg->prompt, " broadcast %s",
- inet_ntoa(iface->in_addr[f].brd));
- if (iface->in_addr[f].bits < 0)
- prompt_Printf(arg->prompt, " (mask %s)",
- inet_ntoa(iface->in_addr[f].mask));
+ iface->addrs, iface->addrs == 1 ? "" : "es");
+
+ for (f = 0; f < iface->addrs; f++) {
+ ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr);
+ switch (ncprange_family(&iface->addr[f].ifa)) {
+ case AF_INET:
+ prompt_Printf(arg->prompt, " inet %s --> ", ncpaddr_ntoa(&ncpaddr));
+ if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
+ prompt_Printf(arg->prompt, "255.255.255.255");
+ else
+ prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer));
+ ncprange_getip4mask(&iface->addr[f].ifa, &mask);
+ prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr));
+ break;
+
+#ifndef NOINET6
+ case AF_INET6:
+ prompt_Printf(arg->prompt, " inet6 %s", ncpaddr_ntoa(&ncpaddr));
+ if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC)
+ prompt_Printf(arg->prompt, " --> %s",
+ ncpaddr_ntoa(&iface->addr[f].peer));
+ ncprange_getwidth(&iface->addr[f].ifa, &width);
+ prompt_Printf(arg->prompt, " prefixlen %d", width);
+ if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1)
+ prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid);
+ break;
+#endif
+ }
prompt_Printf(arg->prompt, "\n");
}