summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp/iface.c
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
committerbrian <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
commitde3feff3f8839f8f26a69dfb7cd667332a8536dc (patch)
treeb09d46345a558a45e66b435c4386d76cf53405d3 /usr.sbin/ppp/iface.c
parentdbc6471fad42e595668d0f00254797ef89e618b0 (diff)
downloadFreeBSD-src-de3feff3f8839f8f26a69dfb7cd667332a8536dc.zip
FreeBSD-src-de3feff3f8839f8f26a69dfb7cd667332a8536dc.tar.gz
o Add ipv6 support, abstracting most NCP addresses into opaque
structures (well, they're treated as opaque). It's now possible to manage IPv6 interface addresses and routing table entries and to filter IPV6 traffic whether encapsulated or not. IPV6CP support is crude for now, and hasn't been tested against any other implementations. RADIUS and IPv6 are independent of eachother for now. ppp.linkup/ppp.linkdown aren't currently used by IPV6CP o Understand all protocols(5) in filter rules rather than only a select few. o Allow a mask specification for the ``delete'' command. It's now possible to specifically delete one of two conflicting routes. o When creating and deleting proxy arp entries, do it for all IPv4 interface addresses rather than doing it just for the ``current'' peer address. o When iface-alias isn't in effect, don't blow away manually (via ``iface add'') added interface addresses. o When listening on a tcp server (diagnostic) socket, bind so that a tcp46 socket is created -- allowing both IPv4 and IPv6 connections. o When displaying ICMP traffic, don't display the icmp type twice. When display traffic, display at least some information about unrecognised traffic. o Bump version Inspired after filtering work by: Makoto MATSUSHITA <matusita@jp.FreeBSD.org>
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 9676b38..d8fa206 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");
}
OpenPOWER on IntegriCloud