Split IPv6 support out into its own file.

This commit is contained in:
thorpej 2005-03-20 01:09:16 +00:00
parent 4fd9a96b1d
commit 26dbe00d59
6 changed files with 528 additions and 431 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.24 2005/03/20 00:02:58 thorpej Exp $
# $NetBSD: Makefile,v 1.25 2005/03/20 01:09:16 thorpej Exp $
# @(#)Makefile 8.1 (Berkeley) 6/5/93
.include <bsd.own.mk>
@ -22,6 +22,7 @@ LDADD+=-lutil
SRCS= ifconfig.c
SRCS+= af_atalk.c
SRCS+= af_inet6.c
SRCS+= af_iso.c
SRCS+= af_ns.c

460
sbin/ifconfig/af_inet6.c Normal file
View File

@ -0,0 +1,460 @@
/* $NetBSD: af_inet6.c,v 1.1 2005/03/20 01:09:16 thorpej Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifdef INET6
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: af_inet6.c,v 1.1 2005/03/20 01:09:16 thorpej Exp $");
#endif /* not lint */
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/nd6.h>
#include <err.h>
#include <errno.h>
#include <ifaddrs.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "extern.h"
#include "af_inet6.h"
static struct in6_ifreq ifr6;
struct in6_ifreq in6_ridreq;
struct in6_aliasreq in6_addreq;
static char *
sec2str(time_t total)
{
static char result[256];
int days, hours, mins, secs;
int first = 1;
char *p = result;
char *end = &result[sizeof(result)];
int n;
if (0) { /*XXX*/
days = total / 3600 / 24;
hours = (total / 3600) % 24;
mins = (total / 60) % 60;
secs = total % 60;
if (days) {
first = 0;
n = snprintf(p, end - p, "%dd", days);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
if (!first || hours) {
first = 0;
n = snprintf(p, end - p, "%dh", hours);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
if (!first || mins) {
first = 0;
n = snprintf(p, end - p, "%dm", mins);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
snprintf(p, end - p, "%ds", secs);
} else
snprintf(p, end - p, "%lu", (u_long)total);
return(result);
}
static int
prefix(void *val, int size)
{
u_char *pname = (u_char *)val;
int byte, bit, plen = 0;
for (byte = 0; byte < size; byte++, plen += 8)
if (pname[byte] != 0xff)
break;
if (byte == size)
return (plen);
for (bit = 7; bit != 0; bit--, plen++)
if (!(pname[byte] & (1 << bit)))
break;
for (; bit != 0; bit--)
if (pname[byte] & (1 << bit))
return(0);
byte++;
for (; byte < size; byte++)
if (pname[byte])
return(0);
return (plen);
}
void
setia6flags(const char *vname, int value)
{
if (value < 0) {
value = -value;
in6_addreq.ifra_flags &= ~value;
} else
in6_addreq.ifra_flags |= value;
}
void
setia6pltime(const char *val, int d)
{
setia6lifetime("pltime", val);
}
void
setia6vltime(const char *val, int d)
{
setia6lifetime("vltime", val);
}
void
setia6lifetime(const char *cmd, const char *val)
{
time_t newval, t;
char *ep;
t = time(NULL);
newval = (time_t)strtoul(val, &ep, 0);
if (val == ep)
errx(EXIT_FAILURE, "invalid %s", cmd);
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
if (strcmp(cmd, "vltime") == 0) {
in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
in6_addreq.ifra_lifetime.ia6t_vltime = newval;
} else if (strcmp(cmd, "pltime") == 0) {
in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
in6_addreq.ifra_lifetime.ia6t_pltime = newval;
}
}
void
setia6eui64(const char *cmd, int val)
{
struct ifaddrs *ifap, *ifa;
const struct sockaddr_in6 *sin6 = NULL;
const struct in6_addr *lladdr = NULL;
struct in6_addr *in6;
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
errx(EXIT_FAILURE, "interface index is already filled");
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family == AF_INET6 &&
strcmp(ifa->ifa_name, name) == 0) {
sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
lladdr = &sin6->sin6_addr;
break;
}
}
}
if (!lladdr)
errx(EXIT_FAILURE, "could not determine link local address");
memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
freeifaddrs(ifap);
}
void
in6_fillscopeid(struct sockaddr_in6 *sin6)
{
#if defined(__KAME__) && defined(KAME_SCOPEID)
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
sin6->sin6_scope_id =
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
}
#endif
}
/* XXX not really an alias */
void
in6_alias(struct in6_ifreq *creq)
{
struct sockaddr_in6 *sin6;
char hbuf[NI_MAXHOST];
u_int32_t scopeid;
const int niflag = NI_NUMERICHOST;
/* Get the non-alias address for this interface. */
getsock(AF_INET6);
if (s < 0) {
if (errno == EPROTONOSUPPORT)
return;
err(EXIT_FAILURE, "socket");
}
sin6 = (struct sockaddr_in6 *)&creq->ifr_addr;
in6_fillscopeid(sin6);
scopeid = sin6->sin6_scope_id;
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflag))
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
printf("\tinet6 %s", hbuf);
if (flags & IFF_POINTOPOINT) {
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFDSTADDR_IN6");
(void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
}
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
in6_fillscopeid(sin6);
hbuf[0] = '\0';
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflag))
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
printf(" -> %s", hbuf);
}
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFNETMASK_IN6");
} else {
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
printf(" prefixlen %d", prefix(&sin6->sin6_addr,
sizeof(struct in6_addr)));
}
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFAFLAG_IN6");
} else {
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
printf(" anycast");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
printf(" tentative");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED)
printf(" duplicated");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED)
printf(" detached");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
printf(" deprecated");
}
if (scopeid)
printf(" scopeid 0x%x", scopeid);
if (Lflag) {
struct in6_addrlifetime *lifetime;
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFALIFETIME_IN6");
} else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
time_t t = time(NULL);
printf(" pltime ");
if (lifetime->ia6t_preferred) {
printf("%s", lifetime->ia6t_preferred < t
? "0"
: sec2str(lifetime->ia6t_preferred - t));
} else
printf("infty");
printf(" vltime ");
if (lifetime->ia6t_expire) {
printf("%s", lifetime->ia6t_expire < t
? "0"
: sec2str(lifetime->ia6t_expire - t));
} else
printf("infty");
}
}
printf("\n");
}
void
in6_status(int force)
{
struct ifaddrs *ifap, *ifa;
struct in6_ifreq isifr;
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcmp(name, ifa->ifa_name) != 0)
continue;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len)
continue;
memset(&isifr, 0, sizeof(isifr));
strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name));
memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
in6_alias(&isifr);
}
freeifaddrs(ifap);
}
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
struct sockaddr_in6 *sin6tab[] = {
SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)};
void
in6_getaddr(const char *str, int which)
{
#if defined(__KAME__) && defined(KAME_SCOPEID)
struct sockaddr_in6 *sin6 = sin6tab[which];
struct addrinfo hints, *res;
int error;
char *slash = NULL;
if (which == ADDR) {
if ((slash = strrchr(str, '/')) != NULL)
*slash = '\0';
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
#if 0 /* in_getaddr() allows FQDN */
hints.ai_flags = AI_NUMERICHOST;
#endif
error = getaddrinfo(str, "0", &hints, &res);
if (error && slash) {
/* try again treating the '/' as part of the name */
*slash = '/';
slash = NULL;
error = getaddrinfo(str, "0", &hints, &res);
}
if (error)
errx(EXIT_FAILURE, "%s: %s", str, gai_strerror(error));
if (res->ai_next)
errx(EXIT_FAILURE, "%s: resolved to multiple addresses", str);
if (res->ai_addrlen != sizeof(struct sockaddr_in6))
errx(EXIT_FAILURE, "%s: bad value", str);
memcpy(sin6, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) {
*(u_int16_t *)&sin6->sin6_addr.s6_addr[2] =
htons(sin6->sin6_scope_id);
sin6->sin6_scope_id = 0;
}
if (slash) {
in6_getprefix(slash + 1, MASK);
explicit_prefix = 1;
}
#else
struct sockaddr_in6 *gasin = sin6tab[which];
gasin->sin6_len = sizeof(*gasin);
if (which != MASK)
gasin->sin6_family = AF_INET6;
if (which == ADDR) {
char *p = NULL;
if((p = strrchr(str, '/')) != NULL) {
*p = '\0';
in6_getprefix(p + 1, MASK);
explicit_prefix = 1;
}
}
if (inet_pton(AF_INET6, str, &gasin->sin6_addr) != 1)
errx(EXIT_FAILURE, "%s: bad value", str);
#endif
}
void
in6_getprefix(const char *plen, int which)
{
struct sockaddr_in6 *gpsin = sin6tab[which];
u_char *cp;
int len = strtol(plen, (char **)NULL, 10);
if ((len < 0) || (len > 128))
errx(EXIT_FAILURE, "%s: bad value", plen);
gpsin->sin6_len = sizeof(*gpsin);
if (which != MASK)
gpsin->sin6_family = AF_INET6;
if ((len == 0) || (len == 128)) {
memset(&gpsin->sin6_addr, 0xff, sizeof(struct in6_addr));
return;
}
memset((void *)&gpsin->sin6_addr, 0x00, sizeof(gpsin->sin6_addr));
for (cp = (u_char *)&gpsin->sin6_addr; len > 7; len -= 8)
*cp++ = 0xff;
if (len)
*cp = 0xff << (8 - len);
}
void
in6_init(void)
{
in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
}
#endif /* INET6 */

51
sbin/ifconfig/af_inet6.h Normal file
View File

@ -0,0 +1,51 @@
/* $NetBSD: af_inet6.h,v 1.1 2005/03/20 01:09:16 thorpej Exp $ */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* XXX */
#include <netinet/in.h>
/* XXX */
extern struct in6_ifreq ifr6;
extern struct in6_ifreq in6_ridreq;
extern struct in6_aliasreq in6_addreq;
void setia6flags(const char *, int);
void setia6pltime(const char *, int);
void setia6vltime(const char *, int);
void setia6lifetime(const char *, const char *);
void setia6eui64(const char *, int);
void in6_fillscopeid(struct sockaddr_in6 *sin6);
void in6_alias(struct in6_ifreq *);
void in6_status(int);
void in6_getaddr(const char *, int);
void in6_getprefix(const char *, int);
void in6_init(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.6 2005/03/19 23:32:55 thorpej Exp $ */
/* $NetBSD: extern.h,v 1.7 2005/03/20 01:09:16 thorpej Exp $ */
/*
* Copyright (c) 1983, 1993
@ -50,10 +50,14 @@ struct afswtch {
extern const struct afswtch *afp;
extern struct ifreq ifr;
extern int s;
extern int explicit_prefix;
extern char name[30];
extern u_short flags;
extern int zflag;
#ifdef INET6
extern int Lflag;
#endif /* INET6 */
extern struct ifreq ifr, ridreq;
extern struct ifaliasreq addreq;

View File

@ -1,4 +1,4 @@
/* $NetBSD: ifconfig.c,v 1.163 2005/03/20 00:02:58 thorpej Exp $ */
/* $NetBSD: ifconfig.c,v 1.164 2005/03/20 01:09:16 thorpej Exp $ */
/*-
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
@ -76,7 +76,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
#if 0
static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
#else
__RCSID("$NetBSD: ifconfig.c,v 1.163 2005/03/20 00:02:58 thorpej Exp $");
__RCSID("$NetBSD: ifconfig.c,v 1.164 2005/03/20 01:09:16 thorpej Exp $");
#endif
#endif /* not lint */
@ -90,9 +90,6 @@ __RCSID("$NetBSD: ifconfig.c,v 1.163 2005/03/20 00:02:58 thorpej Exp $");
#include <net/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#ifdef INET6
#include <netinet6/nd6.h>
#endif
#include <arpa/inet.h>
#include <netdb.h>
@ -117,6 +114,9 @@ __RCSID("$NetBSD: ifconfig.c,v 1.163 2005/03/20 00:02:58 thorpej Exp $");
#include "af_iso.h"
#include "af_ns.h"
#endif /* ! INET_ONLY */
#ifdef INET6
#include "af_inet6.h"
#endif /* INET6 */
#include "agr.h"
#include "ieee80211.h"
@ -126,11 +126,7 @@ __RCSID("$NetBSD: ifconfig.c,v 1.163 2005/03/20 00:02:58 thorpej Exp $");
struct ifreq ifr, ridreq;
struct ifaliasreq addreq __attribute__((aligned(4)));
struct in_aliasreq in_addreq;
#ifdef INET6
struct in6_ifreq ifr6;
struct in6_ifreq in6_ridreq;
struct in6_aliasreq in6_addreq;
#endif
struct sockaddr_in netmask;
char name[30];
@ -162,13 +158,6 @@ void setifmetric(const char *, int);
void setifmtu(const char *, int);
void setifnetmask(const char *, int);
void setifprefixlen(const char *, int);
#ifdef INET6
void setia6flags(const char *, int);
void setia6pltime(const char *, int);
void setia6vltime(const char *, int);
void setia6lifetime(const char *, const char *);
void setia6eui64(const char *, int);
#endif
void setmedia(const char *, int);
void setmediamode(const char *, int);
void setmediaopt(const char *, int);
@ -307,10 +296,8 @@ int getinfo(struct ifreq *);
int carrier(void);
void printall(const char *);
void list_cloners(void);
int prefix(void *, int);
void status(const struct sockaddr_dl *);
void usage(void);
char *sec2str(time_t);
void print_media_word(int, const char *);
void process_media_commands(void);
@ -324,13 +311,6 @@ void in_alias(struct ifreq *);
void in_status(int);
void in_getaddr(const char *, int);
void in_getprefix(const char *, int);
#ifdef INET6
void in6_fillscopeid(struct sockaddr_in6 *sin6);
void in6_alias(struct in6_ifreq *);
void in6_status(int);
void in6_getaddr(const char *, int);
void in6_getprefix(const char *, int);
#endif
/* Known address families */
const struct afswtch afs[] = {
@ -529,9 +509,7 @@ main(int argc, char *argv[])
af = ifr.ifr_addr.sa_family = afp->af_af;
#ifdef INET6
/* initialization */
in6_addreq.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
in6_addreq.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
in6_init();
#endif
/* Process commands. */
@ -934,87 +912,6 @@ setifcaps(const char *vname, int value)
g_ifcr_updated = 1;
}
#ifdef INET6
void
setia6flags(const char *vname, int value)
{
if (value < 0) {
value = -value;
in6_addreq.ifra_flags &= ~value;
} else
in6_addreq.ifra_flags |= value;
}
void
setia6pltime(const char *val, int d)
{
setia6lifetime("pltime", val);
}
void
setia6vltime(const char *val, int d)
{
setia6lifetime("vltime", val);
}
void
setia6lifetime(const char *cmd, const char *val)
{
time_t newval, t;
char *ep;
t = time(NULL);
newval = (time_t)strtoul(val, &ep, 0);
if (val == ep)
errx(EXIT_FAILURE, "invalid %s", cmd);
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
if (strcmp(cmd, "vltime") == 0) {
in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
in6_addreq.ifra_lifetime.ia6t_vltime = newval;
} else if (strcmp(cmd, "pltime") == 0) {
in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
in6_addreq.ifra_lifetime.ia6t_pltime = newval;
}
}
void
setia6eui64(const char *cmd, int val)
{
struct ifaddrs *ifap, *ifa;
const struct sockaddr_in6 *sin6 = NULL;
const struct in6_addr *lladdr = NULL;
struct in6_addr *in6;
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
errx(EXIT_FAILURE, "interface index is already filled");
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family == AF_INET6 &&
strcmp(ifa->ifa_name, name) == 0) {
sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
lladdr = &sin6->sin6_addr;
break;
}
}
}
if (!lladdr)
errx(EXIT_FAILURE, "could not determine link local address");
memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
freeifaddrs(ifap);
}
#endif
void
setifmetric(const char *val, int d)
{
@ -1663,156 +1560,6 @@ setifprefixlen(const char *addr, int d)
explicit_prefix = 1;
}
#ifdef INET6
void
in6_fillscopeid(struct sockaddr_in6 *sin6)
{
#if defined(__KAME__) && defined(KAME_SCOPEID)
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
sin6->sin6_scope_id =
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
}
#endif
}
/* XXX not really an alias */
void
in6_alias(struct in6_ifreq *creq)
{
struct sockaddr_in6 *sin6;
char hbuf[NI_MAXHOST];
u_int32_t scopeid;
const int niflag = NI_NUMERICHOST;
/* Get the non-alias address for this interface. */
getsock(AF_INET6);
if (s < 0) {
if (errno == EPROTONOSUPPORT)
return;
err(EXIT_FAILURE, "socket");
}
sin6 = (struct sockaddr_in6 *)&creq->ifr_addr;
in6_fillscopeid(sin6);
scopeid = sin6->sin6_scope_id;
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflag))
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
printf("\tinet6 %s", hbuf);
if (flags & IFF_POINTOPOINT) {
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFDSTADDR_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFDSTADDR_IN6");
(void) memset(&ifr6.ifr_addr, 0, sizeof(ifr6.ifr_addr));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_len = sizeof(struct sockaddr_in6);
}
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
in6_fillscopeid(sin6);
hbuf[0] = '\0';
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, niflag))
strlcpy(hbuf, "", sizeof(hbuf)); /* some message? */
printf(" -> %s", hbuf);
}
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFNETMASK_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFNETMASK_IN6");
} else {
sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
printf(" prefixlen %d", prefix(&sin6->sin6_addr,
sizeof(struct in6_addr)));
}
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFAFLAG_IN6");
} else {
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
printf(" anycast");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
printf(" tentative");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED)
printf(" duplicated");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED)
printf(" detached");
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
printf(" deprecated");
}
if (scopeid)
printf(" scopeid 0x%x", scopeid);
if (Lflag) {
struct in6_addrlifetime *lifetime;
(void) memset(&ifr6, 0, sizeof(ifr6));
(void) strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr = creq->ifr_addr;
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) == -1) {
if (errno != EADDRNOTAVAIL)
warn("SIOCGIFALIFETIME_IN6");
} else if (lifetime->ia6t_preferred || lifetime->ia6t_expire) {
time_t t = time(NULL);
printf(" pltime ");
if (lifetime->ia6t_preferred) {
printf("%s", lifetime->ia6t_preferred < t
? "0"
: sec2str(lifetime->ia6t_preferred - t));
} else
printf("infty");
printf(" vltime ");
if (lifetime->ia6t_expire) {
printf("%s", lifetime->ia6t_expire < t
? "0"
: sec2str(lifetime->ia6t_expire - t));
} else
printf("infty");
}
}
printf("\n");
}
void
in6_status(int force)
{
struct ifaddrs *ifap, *ifa;
struct in6_ifreq isifr;
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (strcmp(name, ifa->ifa_name) != 0)
continue;
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
if (sizeof(isifr.ifr_addr) < ifa->ifa_addr->sa_len)
continue;
memset(&isifr, 0, sizeof(isifr));
strncpy(isifr.ifr_name, ifa->ifa_name, sizeof(isifr.ifr_name));
memcpy(&isifr.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
in6_alias(&isifr);
}
freeifaddrs(ifap);
}
#endif /*INET6*/
#define SIN(x) ((struct sockaddr_in *) &(x))
struct sockaddr_in *sintab[] = {
SIN(ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
@ -1870,125 +1617,6 @@ in_getprefix(const char *plen, int which)
*cp = 0xff << (8 - len);
}
#ifdef INET6
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
struct sockaddr_in6 *sin6tab[] = {
SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)};
void
in6_getaddr(const char *str, int which)
{
#if defined(__KAME__) && defined(KAME_SCOPEID)
struct sockaddr_in6 *sin6 = sin6tab[which];
struct addrinfo hints, *res;
int error;
char *slash = NULL;
if (which == ADDR) {
if ((slash = strrchr(str, '/')) != NULL)
*slash = '\0';
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
#if 0 /* in_getaddr() allows FQDN */
hints.ai_flags = AI_NUMERICHOST;
#endif
error = getaddrinfo(str, "0", &hints, &res);
if (error && slash) {
/* try again treating the '/' as part of the name */
*slash = '/';
slash = NULL;
error = getaddrinfo(str, "0", &hints, &res);
}
if (error)
errx(EXIT_FAILURE, "%s: %s", str, gai_strerror(error));
if (res->ai_next)
errx(EXIT_FAILURE, "%s: resolved to multiple addresses", str);
if (res->ai_addrlen != sizeof(struct sockaddr_in6))
errx(EXIT_FAILURE, "%s: bad value", str);
memcpy(sin6, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && sin6->sin6_scope_id) {
*(u_int16_t *)&sin6->sin6_addr.s6_addr[2] =
htons(sin6->sin6_scope_id);
sin6->sin6_scope_id = 0;
}
if (slash) {
in6_getprefix(slash + 1, MASK);
explicit_prefix = 1;
}
#else
struct sockaddr_in6 *gasin = sin6tab[which];
gasin->sin6_len = sizeof(*gasin);
if (which != MASK)
gasin->sin6_family = AF_INET6;
if (which == ADDR) {
char *p = NULL;
if((p = strrchr(str, '/')) != NULL) {
*p = '\0';
in6_getprefix(p + 1, MASK);
explicit_prefix = 1;
}
}
if (inet_pton(AF_INET6, str, &gasin->sin6_addr) != 1)
errx(EXIT_FAILURE, "%s: bad value", str);
#endif
}
void
in6_getprefix(const char *plen, int which)
{
struct sockaddr_in6 *gpsin = sin6tab[which];
u_char *cp;
int len = strtol(plen, (char **)NULL, 10);
if ((len < 0) || (len > 128))
errx(EXIT_FAILURE, "%s: bad value", plen);
gpsin->sin6_len = sizeof(*gpsin);
if (which != MASK)
gpsin->sin6_family = AF_INET6;
if ((len == 0) || (len == 128)) {
memset(&gpsin->sin6_addr, 0xff, sizeof(struct in6_addr));
return;
}
memset((void *)&gpsin->sin6_addr, 0x00, sizeof(gpsin->sin6_addr));
for (cp = (u_char *)&gpsin->sin6_addr; len > 7; len -= 8)
*cp++ = 0xff;
if (len)
*cp = 0xff << (8 - len);
}
int
prefix(void *val, int size)
{
u_char *pname = (u_char *)val;
int byte, bit, plen = 0;
for (byte = 0; byte < size; byte++, plen += 8)
if (pname[byte] != 0xff)
break;
if (byte == size)
return (plen);
for (bit = 7; bit != 0; bit--, plen++)
if (!(pname[byte] & (1 << bit)))
break;
for (; bit != 0; bit--)
if (pname[byte] & (1 << bit))
return(0);
byte++;
for (; byte < size; byte++)
if (pname[byte])
return(0);
return (plen);
}
#endif /*INET6*/
void
usage(void)
{
@ -2022,50 +1650,3 @@ usage(void)
progname, progname, progname, progname, progname, progname);
exit(1);
}
#ifdef INET6
char *
sec2str(total)
time_t total;
{
static char result[256];
int days, hours, mins, secs;
int first = 1;
char *p = result;
char *end = &result[sizeof(result)];
int n;
if (0) { /*XXX*/
days = total / 3600 / 24;
hours = (total / 3600) % 24;
mins = (total / 60) % 60;
secs = total % 60;
if (days) {
first = 0;
n = snprintf(p, end - p, "%dd", days);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
if (!first || hours) {
first = 0;
n = snprintf(p, end - p, "%dh", hours);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
if (!first || mins) {
first = 0;
n = snprintf(p, end - p, "%dm", mins);
if (n < 0 || n >= end - p)
return(result);
p += n;
}
snprintf(p, end - p, "%ds", secs);
} else
snprintf(p, end - p, "%lu", (u_long)total);
return(result);
}
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: tunnel.c,v 1.4 2005/03/19 23:16:55 thorpej Exp $ */
/* $NetBSD: tunnel.c,v 1.5 2005/03/20 01:09:16 thorpej Exp $ */
/*
* Copyright (c) 1983, 1993
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: tunnel.c,v 1.4 2005/03/19 23:16:55 thorpej Exp $");
__RCSID("$NetBSD: tunnel.c,v 1.5 2005/03/20 01:09:16 thorpej Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -55,7 +55,7 @@ __RCSID("$NetBSD: tunnel.c,v 1.4 2005/03/19 23:16:55 thorpej Exp $");
#include "tunnel.h"
#ifdef INET6
extern void in6_fillscopeid(struct sockaddr_in6 *sin6); /* XXX */
#include "af_inet6.h"
#endif
void