diff options
author | shin <shin@FreeBSD.org> | 1999-12-07 17:39:16 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 1999-12-07 17:39:16 +0000 |
commit | 70f0bdf6818a73c858bc47a23afc1e9d7c56d716 (patch) | |
tree | 446280db4239de7d7d9030c47d2c30515a265a54 /sbin | |
parent | 7bdf4b7db0db632bec3b1040d83cdfbdb35e59cd (diff) | |
download | FreeBSD-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/Makefile | 1 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.8 | 29 | ||||
-rw-r--r-- | sbin/ifconfig/ifconfig.c | 314 | ||||
-rw-r--r-- | sbin/route/Makefile | 2 | ||||
-rw-r--r-- | sbin/route/keywords | 3 | ||||
-rw-r--r-- | sbin/route/route.8 | 25 | ||||
-rw-r--r-- | sbin/route/route.c | 150 |
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; |