gifconfig, which configures gif IPv[46]-over-IPv[46] pseudo interface.

add gifconfig to SUBDIR.
This commit is contained in:
itojun 1999-07-01 19:41:56 +00:00
parent 125cb421d5
commit 618003328c
4 changed files with 980 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.109 1999/06/30 06:49:28 augustss Exp $
# $NetBSD: Makefile,v 1.110 1999/07/01 19:41:56 itojun Exp $
# from: @(#)Makefile 5.20 (Berkeley) 6/12/93
# XXX Temporary for NO_SENDMAIL and BUILD_POSTFIX
@ -21,6 +21,9 @@ SUBDIR= ac accton amd apm apmd arp bad144 bind bootp catman \
ypbind yppoll ypserv ypset \
zdump zic
# IPv6
SUBDIR+=gifconfig
.if !defined(NO_SENDMAIL)
SUBDIR+= sendmail
.endif

View File

@ -0,0 +1,7 @@
# $NetBSD: Makefile,v 1.1 1999/07/01 19:41:57 itojun Exp $
PROG= gifconfig
CFLAGS+=-DINET6
MAN= gifconfig.8
.include <bsd.prog.mk>

View File

@ -0,0 +1,138 @@
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" 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 project 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 PROJECT 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 PROJECT 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.
.\"
.\" $Id: gifconfig.8,v 1.1 1999/07/01 19:41:58 itojun Exp $
.\"
.Dd May 17, 1998
.Dt GIFCONFIG 8
.Os KAME
.\"
.Sh NAME
.Nm gifconfig
.Nd configure generic IP tunnel
.\"
.Sh SYNOPSIS
.Nm
.Ar interface
.Op Ar af
.Op Ar physsrc physdest
.Nm gifconfig
.Fl a
.\"
.Sh DESCRIPTION
.Nm
configures the physical address for the generic IP tunnel
inteface, such as "gif0".
Argument
.Ar physsrc
and
.Ar physdest
are interpreted as the outer source/destination address for
encapsulating IPv4/v6 header.
Argument
.Ar af
specifies the address family for
.Ar physsrc
and
.Ar physdest .
.Ar Af
can be
.Li inet
or
.Li inet6 ,
and will be treated as
.Li inet
if ommitted.
.Pp
.Nm
takes the following optional argument:
.Bl -tag -width Ds
.It Fl a
Display information associated all generic IP tunnel interfaces.
.El
.Pp
Please note that it is very easy to create infinite routing loop,
when you configure tunnel over same address family
.Po
e.g. IPv4-over-IPv4
.Pc .
.\"
.Sh EXAMPLES
If you would like to configure IPv6 over IPv4(aka IPv6 in IPv4)
tunnel between
.Li 10.1.1.1
and
.Li 10.2.3.4 ,
you should perform the following command:
.Bd -literal -offset
# gifconfig gif0 inet 10.1.1.1 10.2.3.4
.Ed
.Pp
To use the
.Li 0.0.0.0
feature to establish a tunnel from host1 to host3
which will encapsulate and carry packets from host2, on host1 do:
.Bd -literal -offset
# ifconfig gif0 inet host1 127.0.0.2 # assign an address to gif0
# gifconfig gif0 inet host1 0.0.0.0 # assign encapsulation addresses
# route add host2 host3 -ifp gif0: # encap host2 packets, send to host3
.Ed
.Pp
Note: the
.Fl ifp
option to route does not work as documented in
most versions of FreeBSD.
.Pp
On host3 do:
.Bd -literal -offset
# ifconfig gif0 inet host3 127.0.0.2 # assign an address to gif0
# gifconfig gif0 inet host3 0.0.0.0 # assign encapsulation addresses
.Ed
.Pp
Now if you ping host2 from host1, the packets should be encapsulated
with outer source address = host1 and outer destination address = host3,
and delivered to host3.
host3 will decapsulate the packet and deliver it normally to host2.
.Pp
This is also possible with IPv6 outer proto, by replacing
.Li inet
to
.Li inet6 ,
and IPv4 addresses to some appropriate IPv6 addresses in above example.
.\"
.Sh RETURN VALUES
The command exits with exit status of 1 on errors, 0 on success.
.\"
.Sh SEE ALSO
.Xr gif 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
command first appeared in WIDE Hydrangea IPv6 protocol stack kit.
.\" .Sh BUGS
.\" (to be written)

View File

@ -0,0 +1,831 @@
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
/*
* gifconfig, derived from ifconfig
*
* @(#) Copyright (c) 1983, 1993\n\
* The Regents of the University of California. All rights reserved.\n
*
* @(#)ifconfig.c 8.2 (Berkeley) 2/16/94
*/
/*
* 951109 - Andrew@pubnix.net - Changed to iterative buffer growing mechanism
* for ifconfig -a so all interfaces are queried.
*
* 960101 - peter@freebsd.org - Blow away the SIOCGIFCONF code and use
* sysctl() to get the structured interface conf
* and parse the messages in there. REALLY UGLY!
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
#endif /* __FreeBSD__ >= 3 */
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/protosw.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <nlist.h>
#include <kvm.h>
#include <fcntl.h>
struct ifreq ifr;
struct ifaliasreq addreq;
#ifdef INET6
struct in6_ifreq in6_ifr;
struct in6_aliasreq in6_addreq;
#endif
char name[32];
int flags;
int metric;
int mtu;
int setpsrc = 0;
int s;
kvm_t *kvmd;
extern int errno;
#ifdef INET6
char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/
#endif
void setifpsrc __P((char *, int));
void setifpdst __P((char *, int));
void setifflags __P((char *, int));
#define NEXTARG 0xffffff
struct cmd {
char *c_name;
int c_parameter; /* NEXTARG means next argv */
void (*c_func) __P((char *, int));
} cmds[] = {
{ "up", IFF_UP, setifflags } ,
{ "down", -IFF_UP, setifflags },
{ 0, 0, setifpsrc },
{ 0, 0, setifpdst },
};
/*
* XNS support liberally adapted from code written at the University of
* Maryland principally by James O'Toole and Chris Torek.
*/
int main __P((int, char *[]));
void status __P((void));
void phys_status __P((int));
void in_status __P((int));
#ifdef INET6
void in6_status __P((int));
#endif
void ether_status __P((int));
void Perror __P((char *));
void in_getaddr __P((char *, int));
#ifdef INET6
void in6_getaddr __P((char *, int));
void in6_getprefix __P((char *, int));
#endif
void printb __P((char *, unsigned int, char *));
int prefix __P((void *, int));
char ntop_buf[INET6_ADDRSTRLEN];
/* Known address families */
struct afswtch {
char *af_name;
short af_af;
void (*af_status) __P((int));
void (*af_getaddr) __P((char *, int));
void (*af_getprefix) __P((char *, int));
int af_pifaddr;
caddr_t af_addreq;
caddr_t af_req;
} afs[] = {
#define C(x) ((caddr_t) &x)
{ "inet", AF_INET, in_status, in_getaddr, 0,
SIOCSIFPHYADDR, C(addreq), C(ifr) },
#ifdef INET6
{ "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
SIOCSIFPHYADDR_IN6, C(in6_addreq), C(in6_ifr) },
#endif
{ "ether", AF_INET, ether_status, NULL, NULL }, /* XXX not real!! */
{ 0, 0, 0, 0, 0 }
};
struct afswtch *afp = NULL; /*the address family being set or asked about*/
void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
int ifconfig __P((int argc, char *argv[], int af, struct afswtch *rafp));
/*
* Expand the compacted form of addresses as returned via the
* configuration read via sysctl().
*/
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
void
rt_xaddrs(cp, cplim, rtinfo)
caddr_t cp, cplim;
struct rt_addrinfo *rtinfo;
{
struct sockaddr *sa;
int i;
memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
if ((rtinfo->rti_addrs & (1 << i)) == 0)
continue;
rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
ADVANCE(cp, sa);
}
}
/*
* Grunge for new-style sysctl() decoding.. :-(
* Apologies to the world for committing gross things like this in 1996..
*/
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl;
struct rt_addrinfo info;
char *buf, *lim, *next;
int
main(argc, argv)
int argc;
char *argv[];
{
int af = AF_INET;
struct afswtch *rafp = NULL;
size_t needed;
int mib[6];
int all;
if (argc < 2) {
fprintf(stderr, "usage: gifconfig interface %s",
"[ af ] physsrc physdst\n");
exit(1);
}
argc--, argv++;
strncpy(name, *argv, sizeof(name));
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
argc--, argv++;
if (argc > 0) {
for (afp = rafp = afs; rafp->af_name; rafp++)
if (strcmp(rafp->af_name, *argv) == 0) {
afp = rafp; argc--; argv++;
break;
}
rafp = afp;
af = ifr.ifr_addr.sa_family = rafp->af_af;
}
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0; /* address family */
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
/* if particular family specified, only ask about it */
if (afp) {
mib[3] = afp->af_af;
}
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
errx(1, "iflist-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
errx(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
errx(1, "actual retrieval of interface table");
lim = buf + needed;
all = 0;
if (strcmp(name, "-a") == 0)
all = 1; /* All interfaces */
else if (strcmp(name, "-au") == 0)
all = 2; /* All IFF_UPinterfaces */
else if (strcmp(name, "-ad") == 0)
all = 3; /* All !IFF_UP interfaces */
for (next = buf; next < lim; next += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)next;
/* XXX: Swallow up leftover NEWADDR messages */
if (ifm->ifm_type == RTM_NEWADDR)
continue;
if (ifm->ifm_type == RTM_IFINFO) {
sdl = (struct sockaddr_dl *)(ifm + 1);
flags = ifm->ifm_flags;
} else {
errx(1, "out of sync parsing NET_RT_IFLIST");
}
switch(all) {
case -1:
case 0:
if (strlen(name) != sdl->sdl_nlen)
continue; /* not same len */
if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
continue; /* not same name */
break;
case 1:
break; /* always do it */
case 2:
if ((flags & IFF_UP) == 0)
continue; /* not up */
break;
case 3:
if (flags & IFF_UP)
continue; /* not down */
break;
}
/*
* Let's just do it for gif only
*/
if (sdl->sdl_type != IFT_GIF) {
if (all != 0)
continue;
fprintf(stderr, "gifconfig: %s is not gif.\n",
ifr.ifr_name);
exit(1);
}
if (all > 0) {
strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
name[sdl->sdl_nlen] = '\0';
}
if ((s = socket(af, SOCK_DGRAM, 0)) < 0) {
perror("gifconfig: socket");
exit(1);
}
ifconfig(argc,argv,af,rafp);
close(s);
if (all == 0) {
all = -1; /* flag it as 'done' */
break;
}
}
free(buf);
if (all == 0)
errx(1, "interface %s does not exist", name);
exit (0);
}
int
ifconfig(argc, argv, af, rafp)
int argc;
char *argv[];
int af;
struct afswtch *rafp;
{
af = 0; /*fool gcc*/
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
#ifdef INET6
strncpy(in6_ifr.ifr_name, name, sizeof in6_ifr.ifr_name);
#endif /* INET6 */
if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0)
perror("ioctl (SIOCGIFMETRIC)");
else
metric = ifr.ifr_metric;
#ifdef SIOCGIFMTU
if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
perror("ioctl (SIOCGIFMTU)");
else
mtu = ifr.ifr_mtu;
#else
mtu = 0;
#endif
if (argc == 0) {
status();
return(0);
}
while (argc > 0) {
register struct cmd *p;
for (p = cmds; p->c_name; p++)
if (strcmp(*argv, p->c_name) == 0)
break;
if (p->c_name == 0 && setpsrc)
p++; /* got src, do dst */
if (p->c_func) {
if (p->c_parameter == NEXTARG) {
if (argv[1] == NULL)
errx(1, "'%s' requires argument",
p->c_name);
(*p->c_func)(argv[1], 0);
argc--, argv++;
} else
(*p->c_func)(*argv, p->c_parameter);
}
argc--, argv++;
}
if (1 /*newaddr*/) {
strncpy(rafp->af_addreq, name, sizeof ifr.ifr_name);
if (ioctl(s, rafp->af_pifaddr, rafp->af_addreq) < 0)
Perror("ioctl (SIOCSIFPHYADDR)");
}
return(0);
}
#define PSRC 0
#define PDST 1
/*ARGSUSED*/
void
setifpsrc(addr, param)
char *addr;
int param;
{
param = 0; /*fool gcc*/
(*afp->af_getaddr)(addr, PSRC);
setpsrc = 1;
}
/*ARGSUSED*/
void
setifpdst(addr, param)
char *addr;
int param;
{
param = 0; /*fool gcc*/
(*afp->af_getaddr)(addr, PDST);
}
void
setifflags(vname, value)
char *vname;
int value;
{
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
Perror("ioctl (SIOCGIFFLAGS)");
exit(1);
}
strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
flags = ifr.ifr_flags;
if (value < 0) {
value = -value;
flags &= ~value;
} else
flags |= value;
ifr.ifr_flags = flags;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
Perror(vname);
}
#define IFFBITS \
"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\
\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST"
/*
* Print the status of the interface. If an address family was
* specified, show it and it only; otherwise, show them all.
*/
void
status()
{
struct afswtch *p = NULL;
char *mynext;
struct if_msghdr *myifm;
printf("%s: ", name);
printb("flags", flags, IFFBITS);
if (metric)
printf(" metric %d", metric);
if (mtu)
printf(" mtu %d", mtu);
putchar('\n');
/*
* XXX: Sigh. This is bad, I know. At this point, we may have
* *zero* RTM_NEWADDR's, so we have to "feel the water" before
* incrementing the loop. One day, I might feel inspired enough
* to get the top level loop to pass a count down here so we
* dont have to mess with this. -Peter
*/
myifm = ifm;
while (1) {
mynext = next + ifm->ifm_msglen;
if (mynext >= lim)
break;
myifm = (struct if_msghdr *)mynext;
if (myifm->ifm_type != RTM_NEWADDR)
break;
next = mynext;
ifm = (struct if_msghdr *)next;
ifam = (struct ifa_msghdr *)myifm;
info.rti_addrs = ifam->ifam_addrs;
/* Expand the compacted addresses */
rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
&info);
if (afp) {
if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family &&
afp->af_status != ether_status) {
p = afp;
if (p->af_status != ether_status)
(*p->af_status)(1);
}
} else for (p = afs; p->af_name; p++) {
if (p->af_af == info.rti_info[RTAX_IFA]->sa_family &&
p->af_status != ether_status)
(*p->af_status)(0);
}
}
if (afp == NULL || afp->af_status == ether_status)
ether_status(0);
else if (afp && !p) {
warnx("%s has no %s IFA address!", name, afp->af_name);
}
phys_status(0);
}
void
phys_status(force)
int force;
{
char psrcaddr[256];
char pdstaddr[256];
char hostname[NI_MAXHOST];
int srccmd, dstcmd, flags = NI_NUMERICHOST;
struct ifreq *ifrp;
char *ver = "";
force = 0; /*fool gcc*/
psrcaddr[0] = pdstaddr[0] = '\0';
#ifdef INET6
srccmd = SIOCGIFPSRCADDR_IN6;
dstcmd = SIOCGIFPDSTADDR_IN6;
ifrp = (struct ifreq *)&in6_ifr;
#else /* INET6 */
ifrp = ifr;
srccmd = SIOCGIFPSRCADDR;
dstcmd = SIOCGIFPDSTADDR;
#endif /* INET6 */
if (0 <= ioctl(s, srccmd, (caddr_t)ifrp)) {
getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
hostname, NI_MAXHOST, 0, 0, flags);
#ifdef INET6
if (ifrp->ifr_addr.sa_family == AF_INET6)
ver = "6";
#endif /* INET6 */
sprintf(psrcaddr, "inet%s %s", ver, hostname);
}
if (0 <= ioctl(s, dstcmd, (caddr_t)ifrp)) {
getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
hostname, NI_MAXHOST, 0, 0, flags);
sprintf(pdstaddr, "%s", hostname);
}
printf("\tphysical address %s --> %s\n", psrcaddr, pdstaddr);
}
void
in_status(force)
int force;
{
struct sockaddr_in *sin, null_sin;
#if 0
char *inet_ntoa();
#endif
memset(&null_sin, 0, sizeof(null_sin));
sin = (struct sockaddr_in *)info.rti_info[RTAX_IFA];
if (!sin || sin->sin_family != AF_INET) {
if (!force)
return;
/* warnx("%s has no AF_INET IFA address!", name); */
sin = &null_sin;
}
printf("\tinet %s ", inet_ntoa(sin->sin_addr));
if (flags & IFF_POINTOPOINT) {
/* note RTAX_BRD overlap with IFF_BROADCAST */
sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
if (!sin)
sin = &null_sin;
printf("--> %s ", inet_ntoa(sin->sin_addr));
}
sin = (struct sockaddr_in *)info.rti_info[RTAX_NETMASK];
if (!sin)
sin = &null_sin;
printf("netmask 0x%x ", ntohl(sin->sin_addr.s_addr));
if (flags & IFF_BROADCAST) {
/* note RTAX_BRD overlap with IFF_POINTOPOINT */
sin = (struct sockaddr_in *)info.rti_info[RTAX_BRD];
if (sin && sin->sin_addr.s_addr != 0)
printf("broadcast %s", inet_ntoa(sin->sin_addr));
}
putchar('\n');
}
#ifdef INET6
void
in6_status(force)
int force;
{
struct sockaddr_in6 *sin, null_sin;
#if 0
char *inet_ntop();
#endif
memset(&null_sin, 0, sizeof(null_sin));
sin = (struct sockaddr_in6 *)info.rti_info[RTAX_IFA];
if (!sin || sin->sin6_family != AF_INET6) {
if (!force)
return;
/* warnx("%s has no AF_INET6 IFA address!", name); */
sin = &null_sin;
}
printf("\tinet6 %s ", inet_ntop(AF_INET6, &sin->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
if (flags & IFF_POINTOPOINT) {
/* note RTAX_BRD overlap with IFF_BROADCAST */
sin = (struct sockaddr_in6 *)info.rti_info[RTAX_BRD];
/*
* some of ther interfaces do not have valid destination
* address.
*/
if (sin->sin6_family == AF_INET6) {
if (!sin)
sin = &null_sin;
printf("--> %s ", inet_ntop(AF_INET6, &sin->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
}
}
sin = (struct sockaddr_in6 *)info.rti_info[RTAX_NETMASK];
if (!sin)
sin = &null_sin;
printf(" prefixlen %d ", prefix(&sin->sin6_addr,
sizeof(struct in6_addr)));
putchar('\n');
}
#endif /*INET6*/
/*ARGSUSED*/
void
ether_status(dummy)
int dummy;
{
char *cp;
int n;
dummy = 0; /*fool gcc*/
cp = (char *)LLADDR(sdl);
if ((n = sdl->sdl_alen) > 0) {
if (sdl->sdl_type == IFT_ETHER)
printf ("\tether ");
else
printf ("\tlladdr ");
while (--n >= 0)
printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' ');
putchar('\n');
}
}
void
Perror(cmd)
char *cmd;
{
extern int errno;
switch (errno) {
case ENXIO:
errx(1, "%s: no such interface", cmd);
break;
case EPERM:
errx(1, "%s: permission denied", cmd);
break;
default:
err(1, "%s", cmd);
}
}
#define SIN(x) ((struct sockaddr_in *) &(x))
struct sockaddr_in *sintab[] = {
SIN(addreq.ifra_addr), SIN(addreq.ifra_dstaddr)};
void
in_getaddr(s, which)
char *s;
int which;
{
register struct sockaddr_in *sin = sintab[which];
struct hostent *hp;
struct netent *np;
sin->sin_len = sizeof(*sin);
sin->sin_family = AF_INET;
if (inet_aton(s, &sin->sin_addr))
;
else if ((hp = gethostbyname(s)) != NULL)
bcopy(hp->h_addr, (char *)&sin->sin_addr, hp->h_length);
else if ((np = getnetbyname(s)) != NULL)
sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
else
errx(1, "%s: bad value", s);
}
#ifdef INET6
#define SIN6(x) ((struct sockaddr_in6 *) &(x))
struct sockaddr_in6 *sin6tab[] = {
SIN6(in6_addreq.ifra_addr), SIN6(in6_addreq.ifra_dstaddr)};
void
in6_getaddr(s, which)
char *s;
int which;
{
register struct sockaddr_in6 *sin = sin6tab[which];
sin->sin6_len = sizeof(*sin);
sin->sin6_family = AF_INET6;
if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
errx(1, "%s: bad value", s);
}
void
in6_getprefix(plen, which)
char *plen;
int which;
{
register struct sockaddr_in6 *sin = sin6tab[which];
register u_char *cp;
int len = atoi(plen);
if ((len < 0) || (len > 128))
errx(1, "%s: bad value", plen);
sin->sin6_len = sizeof(*sin);
sin->sin6_family = AF_INET6;
if ((len == 0) || (len == 128)) {
memset(&sin->sin6_addr, -1, sizeof(struct in6_addr));
return;
}
for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
*cp++ = -1;
*cp = (-1) << (8 - len);
}
#endif
/*
* Print a value a la the %b format of the kernel's printf
*/
void
printb(s, v, bits)
char *s;
register unsigned int v;
register char *bits;
{
register int i, any = 0;
register char c;
if (bits && *bits == 8)
printf("%s=%o", s, v & 0xffff);
else
printf("%s=%x", s, v & 0xffff);
bits++;
if (bits) {
putchar('<');
while ((i = *bits++) != 0) {
if ((v & (1 << (i-1))) != 0) {
if (any)
putchar(',');
any = 1;
for (; (c = *bits) > 32; bits++)
putchar(c);
} else
for (; *bits > 32; bits++)
;
}
putchar('>');
}
}
#ifdef INET6
int
prefix(val, size)
void *val;
int size;
{
register u_char *name = (u_char *)val;
register int byte, bit, plen = 0;
for (byte = 0; byte < size; byte++, plen += 8)
if (name[byte] != 0xff)
break;
if (byte == size)
return (plen);
for (bit = 7; bit != 0; bit--, plen++)
if (!(name[byte] & (1 << bit)))
break;
for (; bit != 0; bit--)
if (name[byte] & (1 << bit))
return(0);
byte++;
for (; byte < size; byte++)
if (name[byte])
return(0);
return (plen);
}
#endif /*INET6*/