summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>1999-12-07 17:39:16 +0000
committershin <shin@FreeBSD.org>1999-12-07 17:39:16 +0000
commit70f0bdf6818a73c858bc47a23afc1e9d7c56d716 (patch)
tree446280db4239de7d7d9030c47d2c30515a265a54 /sbin
parent7bdf4b7db0db632bec3b1040d83cdfbdb35e59cd (diff)
downloadFreeBSD-src-70f0bdf6818a73c858bc47a23afc1e9d7c56d716.zip
FreeBSD-src-70f0bdf6818a73c858bc47a23afc1e9d7c56d716.tar.gz
udp IPv6 support, IPv6/IPv4 tunneling support in kernel,
packet divert at kernel for IPv6/IPv4 translater daemon This includes queue related patch submitted by jburkhol@home.com. Submitted by: queue related patch from jburkhol@home.com Reviewed by: freebsd-arch, cvs-committers Obtained from: KAME project
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ifconfig/Makefile1
-rw-r--r--sbin/ifconfig/ifconfig.829
-rw-r--r--sbin/ifconfig/ifconfig.c314
-rw-r--r--sbin/route/Makefile2
-rw-r--r--sbin/route/keywords3
-rw-r--r--sbin/route/route.825
-rw-r--r--sbin/route/route.c150
7 files changed, 508 insertions, 16 deletions
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile
index b1fe95b..385946d 100644
--- a/sbin/ifconfig/Makefile
+++ b/sbin/ifconfig/Makefile
@@ -7,6 +7,7 @@ SRCS= ifconfig.c
#comment out to exclude SIOC[GS]IFMEDIA support
SRCS+= ifmedia.c
CFLAGS+=-DUSE_IF_MEDIA
+#CFLAGS+=-DINET6
#comment out to exclude SIOC[GS]ETVLAN support
SRCS+= ifvlan.c
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index a2b399a..6defcd4 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -109,6 +109,7 @@ with different naming schemes, specifying the address family is recommended.
The address or protocol families currently
supported are
.Dq inet ,
+.Dq inet6 ,
.Dq atalk ,
.\" .Dq iso ,
and
@@ -135,6 +136,13 @@ This is sometimes useful when changing network numbers, and
one wishes to accept packets addressed to the old interface.
If the alias is on the same subnet as the first network adress
for this interface, a netmask of 0xffffffff has to be specified.
+.It Cm anycast
+(Inet6 only)
+Specify that the address configured is an anycast address.
+Based on the current specification,
+only routers may configure anycast addresses.
+Anycast address will not be used as source address of any of outgoing
+IPv6 packets.
.It Cm arp
Enable the use of the Address Resolution Protocol in mapping
between network level addresses and link level addresses (default).
@@ -279,6 +287,16 @@ and 0's for the host part.
The mask should contain at least the standard network portion,
and the subnet field should be contiguous with the network
portion.
+.It Cm prefixlen Ar len
+(Inet6 only)
+Specify that
+.Ar len
+bits are reserved for subdividing networks into sub-networks.
+The
+.Ar len
+must be integer, and for syntactical reason it must be between 0 to 128.
+It is almost always 64 under the current IPv6 assignment rule.
+If the parameter is ommitted, 64 is used.
.\" see
.\" Xr eon 5 .
.\" .It Cm nsellength Ar n
@@ -345,6 +363,11 @@ will report only the details specific to that protocol family.
If the driver does supports the media selection system, the supported
media list will be included in the output.
.Pp
+If
+.Fl L
+flag is supplied, address lifetime is dislayed for IPv6 addresses,
+as time offset string.
+.Pp
Optionally, the
.Fl a
flag may be used instead of an interface name. This flag instructs
@@ -375,6 +398,12 @@ it (or have need for it).
Messages indicating the specified interface does not exist, the
requested address is unknown, or the user is not privileged and
tried to alter an interface's configuration.
+.Sh BUGS
+IPv6 link-local addresses are required for several basic communication
+between IPv6 node. If they are deleted by
+.Nm ifconfig
+manually, the kernel might show very strange behavior.
+So, such manuall deletions are strongly discouraged.
.Sh SEE ALSO
.Xr netstat 1 ,
.Xr netintro 4 ,
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 00fb30f..32c7ee8 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -96,6 +96,10 @@ static const char rcsid[] =
struct ifreq ifr, ridreq;
struct ifaliasreq addreq;
+#ifdef INET6
+struct in6_ifreq in6_ridreq;
+struct in6_aliasreq in6_addreq;
+#endif
struct sockaddr_in netmask;
struct netrange at_nr; /* AppleTalk net range */
@@ -108,9 +112,16 @@ int setipdst;
int doalias;
int clearaddr;
int newaddr = 1;
+#ifdef INET6
+static int ip6lifetime;
+#endif
struct afswtch;
+#ifdef INET6
+char ntop_buf[INET6_ADDRSTRLEN]; /*inet_ntop()*/
+#endif
+
void Perror __P((const char *cmd));
void checkatrange __P((struct sockaddr_at *));
int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp));
@@ -123,9 +134,19 @@ void status __P((const struct afswtch *afp, int addrcount,
void usage __P((void));
void ifmaybeload __P((char *name));
+#ifdef INET6
+int prefix __P((void *, int));
+static char *sec2str __P((time_t));
+int explicit_prefix = 0;
+#endif
+
typedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp));
c_func setatphase, setatrange;
c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
+#ifdef INET6
+c_func setifprefixlen;
+c_func setip6flags;
+#endif
c_func setifipdst;
c_func setifflags, setifmetric, setifmtu;
@@ -153,6 +174,12 @@ struct cmd {
{ "-swabips", -EN_SWABIPS, setifflags },
#endif
{ "netmask", NEXTARG, setifnetmask },
+#ifdef INET6
+ { "prefixlen", NEXTARG, setifprefixlen },
+ { "anycast", IN6_IFF_ANYCAST, setip6flags },
+ { "tentative", IN6_IFF_TENTATIVE, setip6flags },
+ { "-tentative", -IN6_IFF_TENTATIVE, setip6flags },
+#endif
{ "range", NEXTARG, setatrange },
{ "phase", NEXTARG, setatphase },
{ "metric", NEXTARG, setifmetric },
@@ -188,10 +215,16 @@ struct cmd {
*/
typedef void af_status __P((int, struct rt_addrinfo *));
typedef void af_getaddr __P((const char *, int));
+typedef void af_getprefix __P((const char *, int));
af_status in_status, ipx_status, at_status, ether_status;
af_getaddr in_getaddr, ipx_getaddr, at_getaddr;
+#ifdef INET6
+af_status in6_status;
+af_getaddr in6_getaddr;
+af_getprefix in6_getprefix;
+#endif /*INET6*/
#ifdef NS
af_status xns_status;
af_getaddr xns_getaddr;
@@ -204,29 +237,35 @@ struct afswtch {
short af_af;
af_status *af_status;
af_getaddr *af_getaddr;
+ af_getprefix *af_getprefix;
u_long af_difaddr;
u_long af_aifaddr;
caddr_t af_ridreq;
caddr_t af_addreq;
} afs[] = {
#define C(x) ((caddr_t) &x)
- { "inet", AF_INET, in_status, in_getaddr,
+ { "inet", AF_INET, in_status, in_getaddr, NULL,
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
- { "ipx", AF_IPX, ipx_status, ipx_getaddr,
+#ifdef INET6
+ { "inet6", AF_INET6, in6_status, in6_getaddr, in6_getprefix,
+ SIOCDIFADDR_IN6, SIOCAIFADDR_IN6,
+ C(in6_ridreq), C(in6_addreq) },
+#endif /*INET6*/
+ { "ipx", AF_IPX, ipx_status, ipx_getaddr, NULL,
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
- { "atalk", AF_APPLETALK, at_status, at_getaddr,
+ { "atalk", AF_APPLETALK, at_status, at_getaddr, NULL,
SIOCDIFADDR, SIOCAIFADDR, C(addreq), C(addreq) },
#ifdef NS
- { "ns", AF_NS, xns_status, xns_getaddr,
+ { "ns", AF_NS, xns_status, xns_getaddr, NULL,
SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) },
#endif
- { "ether", AF_INET, ether_status, NULL }, /* XXX not real!! */
+ { "ether", AF_INET, ether_status, NULL, NULL }, /* XXX not real!! */
#if 0 /* XXX conflicts with the media command */
#ifdef USE_IF_MEDIA
- { "media", AF_INET, media_status, NULL }, /* XXX not real!! */
+ { "media", AF_INET, media_status, NULL, NULL, }, /* XXX not real!! */
#endif
#ifdef USE_VLANS
- { "vlan", AF_INET, media_status, NULL }, /* XXX not real!! */
+ { "vlan", AF_INET, media_status, NULL, NULL, }, /* XXX not real!! */
#endif
#endif
{ 0, 0, 0, 0 }
@@ -262,11 +301,19 @@ rt_xaddrs(cp, cplim, rtinfo)
void
usage()
{
+#ifndef INET6
fprintf(stderr, "%s\n%s\n%s\n%s\n",
"usage: ifconfig interface address_family [address [dest_address]]",
" [parameters]",
" ifconfig -a [-d] [-u] [address_family]",
" ifconfig -l [-d] [-u] [address_family]");
+#else
+ fprintf(stderr, "%s\n%s\n%s\n%s\n",
+ "usage: ifconfig [-L] interface address_family [address [dest_address]]",
+ " [parameters]",
+ " ifconfig -a [-L] [-d] [-u] [address_family]",
+ " ifconfig -l [-d] [-u] [address_family]");
+#endif
exit(1);
}
@@ -291,11 +338,20 @@ main(argc, argv)
/* Parse leading line options */
all = downonly = uponly = namesonly = 0;
- while ((c = getopt(argc, argv, "adlmu")) != -1) {
+ while ((c = getopt(argc, argv, "adlmu"
+#ifdef INET6
+ "L"
+#endif
+ )) != -1) {
switch (c) {
case 'a': /* scan all interfaces */
all++;
break;
+#ifdef INET6
+ case 'L':
+ ip6lifetime++; /* print IPv6 adress lifetime */
+ break;
+#endif
case 'l': /* scan interface names only */
namesonly++;
break;
@@ -502,6 +558,15 @@ ifconfig(argc, argv, afp)
}
argc--, argv++;
}
+#ifdef INET6
+ if (ifr.ifr_addr.sa_family == AF_INET6 && explicit_prefix == 0) {
+ /* Aggregatable address architecture defines all prefixes
+ are 64. So, it is convenient to set prefixlen to 64 if
+ it is not specified. */
+ setifprefixlen("64", 0, s, afp);
+ /* in6_getprefix("64", MASK) if MASK is available here... */
+ }
+#endif
if (setipdst && ifr.ifr_addr.sa_family == AF_IPX) {
struct ipxip_req rq;
int size = sizeof(rq);
@@ -592,6 +657,36 @@ setifnetmask(addr, dummy, s, afp)
(*afp->af_getaddr)(addr, MASK);
}
+#ifdef INET6
+void
+setifprefixlen(addr, dummy, s, afp)
+ const char *addr;
+ int dummy __unused;
+ int s;
+ const struct afswtch *afp;
+{
+ if (*afp->af_getprefix)
+ (*afp->af_getprefix)(addr, MASK);
+ explicit_prefix = 1;
+}
+
+void
+setip6flags(dummyaddr, flag, dummysoc, afp)
+ const char *dummyaddr __unused;
+ int flag;
+ int dummysoc __unused;
+ const struct afswtch *afp;
+{
+ if (afp->af_af != AF_INET6)
+ err(1, "address flags can be set only for inet6 addresses");
+
+ if (flag < 0)
+ in6_addreq.ifra_flags &= ~(-flag);
+ else
+ in6_addreq.ifra_flags |= flag;
+}
+#endif
+
void
setifbroadaddr(addr, dummy, s, afp)
const char *addr;
@@ -854,6 +949,99 @@ in_status(s, info)
putchar('\n');
}
+#ifdef INET6
+void
+in6_status(s, info)
+ int s __unused;
+ struct rt_addrinfo * info;
+{
+ struct sockaddr_in6 *sin, null_sin;
+ struct in6_ifreq ifr6;
+ int s6;
+ u_int32_t flags6;
+ struct in6_addrlifetime lifetime;
+ time_t t = time(NULL);
+
+ memset(&null_sin, 0, sizeof(null_sin));
+
+ sin = (struct sockaddr_in6 *)info->rti_info[RTAX_IFA];
+ strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+ if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("ifconfig: socket");
+ return;
+ }
+ ifr6.ifr_addr = *sin;
+ if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+ perror("ifconfig: ioctl(SIOCGIFAFLAG_IN6)");
+ close(s6);
+ return;
+ }
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ memset(&lifetime, 0, sizeof(lifetime));
+ ifr6.ifr_addr = *sin;
+ if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
+ perror("ifconfig: ioctl(SIOCGIFALIFETIME_IN6)");
+ close(s6);
+ return;
+ }
+ lifetime = ifr6.ifr_ifru.ifru_lifetime;
+ close(s6);
+
+ 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 the interfaces do not have valid destination
+ * address.
+ */
+ if (sin && sin->sin6_family == AF_INET6) {
+ 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)));
+
+ if (flags6 & IN6_IFF_ANYCAST)
+ printf("anycast ");
+ if (flags6 & IN6_IFF_TENTATIVE)
+ printf("tentative ");
+ if (flags6 & IN6_IFF_DUPLICATED)
+ printf("duplicated ");
+ if (flags6 & IN6_IFF_DETACHED)
+ printf("detached ");
+ if (flags6 & IN6_IFF_DEPRECATED)
+ printf("deprecated ");
+
+
+ if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
+ 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 ");
+ }
+
+ putchar('\n');
+}
+#endif /*INET6*/
+
void
ipx_status(s, info)
int s __unused;
@@ -1005,6 +1193,54 @@ in_getaddr(s, which)
errx(1, "%s: bad value", s);
}
+#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(s, which)
+ const char *s;
+ int which;
+{
+ register struct sockaddr_in6 *sin = sin6tab[which];
+
+ newaddr &= 1;
+
+ sin->sin6_len = sizeof(*sin);
+ if (which != MASK)
+ 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)
+ const 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);
+ if (which != MASK)
+ sin->sin6_family = AF_INET6;
+ if ((len == 0) || (len == 128)) {
+ memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr));
+ return;
+ }
+ memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr));
+ for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
+ *cp++ = 0xff;
+ *cp = 0xff << (8 - len);
+}
+#endif
+
/*
* Print a value a la the %b format of the kernel's printf
*/
@@ -1150,6 +1386,68 @@ xns_getaddr(addr, which)
}
#endif
+#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);
+}
+
+static char *
+sec2str(total)
+ time_t total;
+{
+ static char result[256];
+ int days, hours, mins, secs;
+ int first = 1;
+ char *p = result;
+
+ if (0) {
+ days = total / 3600 / 24;
+ hours = (total / 3600) % 24;
+ mins = (total / 60) % 60;
+ secs = total % 60;
+
+ if (days) {
+ first = 0;
+ p += sprintf(p, "%dd", days);
+ }
+ if (!first || hours) {
+ first = 0;
+ p += sprintf(p, "%dh", hours);
+ }
+ if (!first || mins) {
+ first = 0;
+ p += sprintf(p, "%dm", mins);
+ }
+ sprintf(p, "%ds", secs);
+ } else
+ sprintf(result, "%lu", (unsigned long)total);
+
+ return(result);
+}
+#endif /*INET6*/
+
void
ifmaybeload(name)
char *name;
diff --git a/sbin/route/Makefile b/sbin/route/Makefile
index 56679e1..e581d8c 100644
--- a/sbin/route/Makefile
+++ b/sbin/route/Makefile
@@ -1,9 +1,11 @@
# @(#)Makefile 8.1 (Berkeley) 6/5/93
+# $FreeBSD$
PROG= route
MAN8= route.8
SRCS= route.c keywords.h
CFLAGS+=-I. -Wall -DNS
+#CFLAGS+=-DINET6
CLEANFILES+=keywords.h
BINMODE=4555
diff --git a/sbin/route/keywords b/sbin/route/keywords
index 07a0ddc..00080a7 100644
--- a/sbin/route/keywords
+++ b/sbin/route/keywords
@@ -1,4 +1,5 @@
# @(#)keywords 8.2 (Berkeley) 3/19/94
+# $FreeBSD$
add
atalk
@@ -19,6 +20,7 @@ interface
ifa
ifp
inet
+inet6
iso
link
llinfo
@@ -31,6 +33,7 @@ net
netmask
nostatic
osi
+prefixlen
proto1
proto2
recvpipe
diff --git a/sbin/route/route.8 b/sbin/route/route.8
index 04cd23a..d8a36b9 100644
--- a/sbin/route/route.8
+++ b/sbin/route/route.8
@@ -69,7 +69,7 @@ Bypass attempts to print host and network names symbolically
when reporting actions. (The process of translating between symbolic
names and numerical equivalents can be quite time consuming, and
may require correct operation of the network; thus it may be expedient
-to forgo this, especially when attempting to repair networking operations).
+to forgot this, especially when attempting to repair networking operations).
.It Fl v
(verbose) Print additional details.
.It Fl q
@@ -120,6 +120,7 @@ When the address family may is specified by any of the
.Fl osi ,
.Fl xns ,
.Fl atalk ,
+.Fl inet6 ,
or
.Fl inet
modifiers, only routes having destinations with addresses in the
@@ -225,6 +226,28 @@ One specifies an additional ensuing address parameter
The implicit network mask generated in the AF_INET case
can be overridden by making sure this option follows the destination parameter.
.Pp
+For
+.Dv AF_INET6 ,
+the
+.Fl prefixlen
+qualifier
+is available instead of the
+.Fl mask
+qualifier because non-continuous masks are not allowed in IPv6.
+For example,
+.Fl prefixlen Li 32
+specifies network mask of
+.Li ffff:ffff:0000:0000:0000:0000:0000:0000
+to be used.
+The default value of prefixlen is 64 to get along with
+the aggregatable address.
+But 0 is assumed if
+.Cm default
+is specified.
+Note that the qualifier works only for
+.Dv AF_INET6
+address family.
+.Pp
Routes have associated flags which influence operation of the protocols
when sending to destinations matched by the routes.
These flags may be set (or sometimes cleared)
diff --git a/sbin/route/route.c b/sbin/route/route.c
index e0260b1..8576d75 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -84,6 +84,9 @@ struct ortentry route;
union sockunion {
struct sockaddr sa;
struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
struct sockaddr_at sat;
#ifdef NS
struct sockaddr_ns sns;
@@ -105,10 +108,15 @@ char *routename(), *netname();
void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
int getaddr(), rtmsg(), x25_makemask();
+int prefixlen();
extern char *iso_ntoa();
void usage __P((const char *)) __dead2;
+#ifdef INET6
+char ntop_buf[INET6_ADDRSTRLEN]; /*for inet_ntop()*/
+#endif
+
void
usage(cp)
const char *cp;
@@ -219,6 +227,11 @@ flushroutes(argc, argv)
case K_INET:
af = AF_INET;
break;
+#ifdef INET6
+ case K_INET6:
+ af = AF_INET6;
+ break;
+#endif
case K_ATALK:
af = AF_APPLETALK;
break;
@@ -346,6 +359,21 @@ routename(sa)
break;
}
+#ifdef INET6
+ case AF_INET6:
+ { struct sockaddr_in6 *sin6;
+ int gap;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ gap = sizeof(struct sockaddr_in6) - sin6->sin6_len;
+ if (gap > 0)
+ bzero((char *)(sin6) + sin6->sin6_len, gap);
+ (void) snprintf(line, sizeof(line), "%s",
+ inet_ntop(AF_INET6, &sin6->sin6_addr,
+ ntop_buf, sizeof(ntop_buf)));
+ }
+#endif
+
case AF_APPLETALK:
(void) snprintf(line, sizeof(line), "atalk %s",
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
@@ -443,6 +471,21 @@ netname(sa)
break;
}
+#ifdef INET6
+ case AF_INET6:
+ { struct in6_addr in6;
+ int gap;
+
+ in6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
+ gap = sizeof(struct sockaddr_in6) - sa->sa_len;
+ if (gap > 0)
+ bzero((char *)(&in6 + 1) - gap, gap);
+ (void)snprintf(line, sizeof(line), "%s",
+ inet_ntop(AF_INET6, &in6, ntop_buf,
+ sizeof(ntop_buf)));
+ }
+#endif
+
case AF_APPLETALK:
(void) snprintf(line, sizeof(line), "atalk %s",
atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
@@ -526,6 +569,19 @@ newroute(argc, argv)
af = AF_INET;
aflen = sizeof(struct sockaddr_in);
break;
+#ifdef INET6
+ case K_INET6:
+ af = AF_INET6;
+ aflen = sizeof(struct sockaddr_in6);
+ if (prefixlen("64") != 64) {
+ fprintf(stderr, "internal error: "
+ "setting prefixlen=64\n");
+ exit(1);
+ }
+ forcenet = 0;
+ ishost = 1;
+ break;
+#endif
case K_ATALK:
af = AF_APPLETALK;
aflen = sizeof(struct sockaddr_at);
@@ -614,6 +670,17 @@ newroute(argc, argv)
case K_NET:
forcenet++;
break;
+ case K_PREFIXLEN:
+ if (!--argc)
+ usage((char *)NULL);
+ if (prefixlen(*++argv) == -1) {
+ forcenet = 0;
+ ishost = 1;
+ } else {
+ forcenet = 1;
+ ishost = 0;
+ }
+ break;
case K_MTU:
case K_HOPCOUNT:
case K_EXPIRE:
@@ -641,8 +708,15 @@ newroute(argc, argv)
}
}
}
- if (forcehost)
+ if (forcehost) {
ishost = 1;
+#ifdef INET6
+ if (af == AF_INET6) {
+ rtm_addrs &= ~RTA_NETMASK;
+ memset((void *)&so_mask, 0, sizeof(so_mask));
+ }
+#endif
+ }
if (forcenet)
ishost = 0;
flags |= RTF_UP;
@@ -754,11 +828,13 @@ getaddr(which, s, hpp)
struct netent *np;
u_long val;
char *q,qs;
+ int afamily; /* local copy of af so we can change it */
if (af == 0) {
af = AF_INET;
aflen = sizeof(struct sockaddr_in);
}
+ afamily = af;
rtm_addrs |= which;
switch (which) {
case RTA_DST:
@@ -818,6 +894,7 @@ getaddr(which, s, hpp)
break;
case RTA_IFP:
su = &so_ifp;
+ afamily = AF_LINK;
break;
case RTA_IFA:
su = &so_ifa;
@@ -827,7 +904,7 @@ getaddr(which, s, hpp)
/*NOTREACHED*/
}
su->sa.sa_len = aflen;
- su->sa.sa_family = af; /* cases that don't want it have left already */
+ su->sa.sa_family = afamily; /* cases that don't want it have left already */
if (strcmp(s, "default") == 0) {
/*
* Default is net 0.0.0.0/0
@@ -844,7 +921,16 @@ getaddr(which, s, hpp)
}
return (0);
}
- switch (af) {
+ switch (afamily) {
+#ifdef INET6
+ case AF_INET6:
+ if (inet_pton(AF_INET6, s, (void *)&su->sin6.sin6_addr) == -1) {
+ (void) fprintf(stderr, "%s: bad value\n", s);
+ exit(1);
+ }
+ return 0;
+#endif
+
#ifdef NS
case AF_NS:
if (which == RTA_DST) {
@@ -926,6 +1012,51 @@ netdone:
errx(EX_NOHOST, "bad address: %s", s);
}
+int
+prefixlen(s)
+ char *s;
+{
+ int len = atoi(s), q, r;
+ int max;
+ char *p;
+
+ rtm_addrs |= RTA_NETMASK;
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ max = 128;
+ p = (char *)&so_mask.sin6.sin6_addr;
+ break;
+#endif
+ case AF_INET:
+ max = 32;
+ p = (char *)&so_mask.sin.sin_addr;
+ break;
+ default:
+ (void) fprintf(stderr, "prefixlen not supported in this af\n");
+ exit(1);
+ /*NOTREACHED*/
+ }
+
+ if (len < 0 || max < len) {
+ (void) fprintf(stderr, "%s: bad value\n", s);
+ exit(1);
+ }
+
+ q = len >> 3;
+ r = len & 7;
+ so_mask.sa.sa_family = af;
+ so_mask.sa.sa_len = aflen;
+ memset((void *)p, 0, max / 8);
+ if (q > 0)
+ memset((void *)p, 0xff, q);
+ if (r > 0)
+ *((u_char *)p + q) = (0xff00 >> r) & 0xff;
+ if (len == max)
+ return -1;
+ else
+ return len;
+}
#ifdef NS
short ns_nullh[] = {0,0,0};
@@ -971,9 +1102,9 @@ ns_print(sns)
else
*cport = 0;
- (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s",
- (unsigned long)ntohl(net.long_e),
- host, cport);
+ (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s",
+ (unsigned long)ntohl(net.long_e),
+ host, cport);
return (mybuf);
}
#endif
@@ -1017,8 +1148,10 @@ monitor()
exit(0);
}
for(;;) {
+ time_t now;
n = read(s, msg, 2048);
- (void) printf("got message of size %d\n", n);
+ now = time(NULL);
+ (void) printf("got message of size %d on %s", n, ctime(&now));
print_rtmsg((struct rt_msghdr *)msg, n);
}
}
@@ -1115,6 +1248,9 @@ mask_addr()
case AF_NS:
#endif
case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
case AF_APPLETALK:
case 0:
return;
OpenPOWER on IntegriCloud