summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
committerume <ume@FreeBSD.org>2001-06-11 12:39:29 +0000
commit832f8d224926758a9ae0b23a6b45353e44fbc87a (patch)
treea79fc7ad2b97862c4a404f352f0211ad93a7b5f1 /sbin
parent2693854b01a52b0395a91322aa3edf926bddff38 (diff)
downloadFreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.zip
FreeBSD-src-832f8d224926758a9ae0b23a6b45353e44fbc87a.tar.gz
Sync with recent KAME.
This work was based on kame-20010528-freebsd43-snap.tgz and some critical problem after the snap was out were fixed. There are many many changes since last KAME merge. TODO: - The definitions of SADB_* in sys/net/pfkeyv2.h are still different from RFC2407/IANA assignment because of binary compatibility issue. It should be fixed under 5-CURRENT. - ip6po_m member of struct ip6_pktopts is no longer used. But, it is still there because of binary compatibility issue. It should be removed under 5-CURRENT. Reviewed by: itojun Obtained from: KAME MFC after: 3 weeks
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ifconfig/ifconfig.813
-rw-r--r--sbin/ifconfig/ifconfig.c231
-rw-r--r--sbin/ping6/ping6.865
-rw-r--r--sbin/ping6/ping6.c1601
-rw-r--r--sbin/route/route.c234
-rw-r--r--sbin/rtsol/Makefile4
-rw-r--r--sbin/setkey/parse.y85
-rw-r--r--sbin/setkey/scriptdump.pl4
-rw-r--r--sbin/setkey/setkey.8161
-rw-r--r--sbin/setkey/setkey.c78
-rw-r--r--sbin/setkey/token.l36
11 files changed, 1833 insertions, 679 deletions
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index 176af6a..e4ef0f4 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -256,6 +256,19 @@ list of available options.
.It Fl mediaopt Ar opts
If the driver supports the media selection system, disable the
specified media options on the interface.
+.It Cm tunnel Ar src_addr Ar dest_addr
+(IP tunnel devices only)
+Configure the physical source and destination address for IP tunnel
+interfaces (gif). The arguments
+.Ar src_addr
+and
+.Ar dest_addr
+are interpreted as the outer source/destination for the encapsulating
+IPv4/IPv6 header.
+.It Cm deletetunnel
+Unconfigure the physical source and destination address for IP tunnel
+interfaces previously configured with
+.Cm tunnel .
.It Cm vlan Ar vlan_tag
If the interface is a vlan pseudo interface, set the vlan tag value
to
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index f865af24..72c0f16 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -149,35 +149,43 @@ void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
void status __P((const struct afswtch *afp, int addrcount,
struct sockaddr_dl *sdl, struct if_msghdr *ifm,
struct ifa_msghdr *ifam));
+void tunnel_status __P((int s));
void usage __P((void));
void ifmaybeload __P((char *name));
#ifdef INET6
+void in6_fillscopeid __P((struct sockaddr_in6 *sin6));
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));
+typedef void c_func2 __P((const char *arg, const char *arg2, int s, const struct afswtch *afp));
c_func setatphase, setatrange;
c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask;
+c_func2 settunnel;
+c_func deletetunnel;
#ifdef INET6
c_func setifprefixlen;
c_func setip6flags;
-c_func setip6vltime;
c_func setip6pltime;
+c_func setip6vltime;
+c_func2 setip6lifetime;
#endif
c_func setifipdst;
c_func setifflags, setifmetric, setifmtu, setiflladdr;
#define NEXTARG 0xffffff
+#define NEXTARG2 0xfffffe
const
struct cmd {
const char *c_name;
int c_parameter; /* NEXTARG means next argv */
void (*c_func) __P((const char *, int, int, const struct afswtch *afp));
+ void (*c_func2) __P((const char *, const char *, int, const struct afswtch *afp));
} cmds[] = {
{ "up", IFF_UP, setifflags } ,
{ "down", -IFF_UP, setifflags },
@@ -201,14 +209,20 @@ struct cmd {
{ "anycast", IN6_IFF_ANYCAST, setip6flags },
{ "tentative", IN6_IFF_TENTATIVE, setip6flags },
{ "-tentative", -IN6_IFF_TENTATIVE, setip6flags },
- { "vltime", NEXTARG, setip6vltime },
+ { "deprecated", IN6_IFF_DEPRECATED, setip6flags },
+ { "-deprecated", -IN6_IFF_DEPRECATED, setip6flags },
+ { "autoconf", IN6_IFF_AUTOCONF, setip6flags },
+ { "-autoconf", -IN6_IFF_AUTOCONF, setip6flags },
{ "pltime", NEXTARG, setip6pltime },
+ { "vltime", NEXTARG, setip6vltime },
#endif
{ "range", NEXTARG, setatrange },
{ "phase", NEXTARG, setatphase },
{ "metric", NEXTARG, setifmetric },
{ "broadcast", NEXTARG, setifbroadaddr },
{ "ipdst", NEXTARG, setifipdst },
+ { "tunnel", NEXTARG2, NULL, settunnel },
+ { "deletetunnel", 0, deletetunnel },
{ "link0", IFF_LINK0, setifflags },
{ "-link0", -IFF_LINK0, setifflags },
{ "link1", IFF_LINK1, setifflags },
@@ -600,13 +614,19 @@ ifconfig(argc, argv, afp)
break;
if (p->c_name == 0 && setaddr)
p++; /* got src, do dst */
- if (p->c_func) {
+ if (p->c_func || p->c_func2) {
if (p->c_parameter == NEXTARG) {
if (argv[1] == NULL)
errx(1, "'%s' requires argument",
p->c_name);
(*p->c_func)(argv[1], 0, s, afp);
argc--, argv++;
+ } else if (p->c_parameter == NEXTARG2) {
+ if (argc < 3)
+ errx(1, "'%s' requires 2 arguments",
+ p->c_name);
+ (*p->c_func2)(argv[1], argv[2], s, afp);
+ argc -= 2, argv += 2;
} else
(*p->c_func)(*argv, p->c_parameter, s, afp);
}
@@ -704,6 +724,82 @@ setifaddr(addr, param, s, afp)
}
void
+settunnel(src, dst, s, afp)
+ const char *src, *dst;
+ int s;
+ const struct afswtch *afp;
+{
+ struct addrinfo hints, *srcres, *dstres;
+ struct ifaliasreq addreq;
+ int ecode;
+#ifdef INET6
+ struct in6_aliasreq in6_addreq;
+#endif
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = afp->af_af;
+
+ if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(ecode));
+
+ if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(ecode));
+
+ if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
+ errx(1,
+ "source and destination address families do not match");
+
+ switch (srcres->ai_addr->sa_family) {
+ case AF_INET:
+ memset(&addreq, 0, sizeof(addreq));
+ strncpy(addreq.ifra_name, name, IFNAMSIZ);
+ memcpy(&addreq.ifra_addr, srcres->ai_addr,
+ srcres->ai_addr->sa_len);
+ memcpy(&addreq.ifra_dstaddr, dstres->ai_addr,
+ dstres->ai_addr->sa_len);
+
+ if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
+ warn("SIOCSIFPHYADDR");
+ break;
+
+#ifdef INET6
+ case AF_INET6:
+ memset(&in6_addreq, 0, sizeof(in6_addreq));
+ strncpy(in6_addreq.ifra_name, name, IFNAMSIZ);
+ memcpy(&in6_addreq.ifra_addr, srcres->ai_addr,
+ srcres->ai_addr->sa_len);
+ memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
+ dstres->ai_addr->sa_len);
+
+ if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0)
+ warn("SIOCSIFPHYADDR_IN6");
+ break;
+#endif /* INET6 */
+
+ default:
+ warn("address family not supported");
+ }
+
+ freeaddrinfo(srcres);
+ freeaddrinfo(dstres);
+}
+
+/* ARGSUSED */
+void
+deletetunnel(vname, param, s, afp)
+ const char *vname;
+ int param;
+ int s;
+ const struct afswtch *afp;
+{
+
+ if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
+ err(1, "SIOCDIFPHYADDR");
+}
+
+void
setifnetmask(addr, dummy, s, afp)
const char *addr;
int dummy __unused;
@@ -745,23 +841,48 @@ setip6flags(dummyaddr, flag, dummysoc, afp)
}
void
-setip6vltime(seconds, dummy, s, afp)
+setip6pltime(seconds, dummy, s, afp)
const char *seconds;
int dummy __unused;
int s;
const struct afswtch *afp;
{
- in6_addreq.ifra_lifetime.ia6t_vltime = atoi(seconds);
+ setip6lifetime("pltime", seconds, s, afp);
}
void
-setip6pltime(seconds, dummy, s, afp)
+setip6vltime(seconds, dummy, s, afp)
const char *seconds;
int dummy __unused;
int s;
const struct afswtch *afp;
{
- in6_addreq.ifra_lifetime.ia6t_pltime = atoi(seconds);
+ setip6lifetime("vltime", seconds, s, afp);
+}
+
+void
+setip6lifetime(cmd, val, s, afp)
+ const char *cmd;
+ const char *val;
+ int s;
+ const struct afswtch *afp;
+{
+ time_t newval, t;
+ char *ep;
+
+ t = time(NULL);
+ newval = (time_t)strtoul(val, &ep, 0);
+ if (val == ep)
+ errx(1, "invalid %s", cmd);
+ if (afp->af_af != AF_INET6)
+ errx(1, "%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;
+ }
}
#endif
@@ -964,6 +1085,8 @@ status(afp, addrcount, sdl, ifm, ifam)
printf(" mtu %d", mtu);
putchar('\n');
+ tunnel_status(s);
+
while (addrcount > 0) {
info.rti_addrs = ifam->ifam_addrs;
@@ -1015,6 +1138,73 @@ status(afp, addrcount, sdl, ifm, ifam)
}
void
+tunnel_status(s)
+ int s;
+{
+ char psrcaddr[NI_MAXHOST];
+ char pdstaddr[NI_MAXHOST];
+ u_long srccmd, dstcmd;
+ struct ifreq *ifrp;
+ const char *ver = "";
+#ifdef NI_WITHSCOPEID
+ const int niflag = NI_NUMERICHOST | NI_WITHSCOPEID;
+#else
+ const int niflag = NI_NUMERICHOST;
+#endif
+#ifdef INET6
+ struct in6_ifreq in6_ifr;
+ int s6;
+#endif /* INET6 */
+
+ psrcaddr[0] = pdstaddr[0] = '\0';
+
+#ifdef INET6
+ memset(&in6_ifr, 0, sizeof(in6_ifr));
+ strncpy(in6_ifr.ifr_name, name, IFNAMSIZ);
+ s6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (s6 < 0) {
+ srccmd = SIOCGIFPSRCADDR;
+ dstcmd = SIOCGIFPDSTADDR;
+ ifrp = &ifr;
+ } else {
+ close(s6);
+ srccmd = SIOCGIFPSRCADDR_IN6;
+ dstcmd = SIOCGIFPDSTADDR_IN6;
+ ifrp = (struct ifreq *)&in6_ifr;
+ }
+#else /* INET6 */
+ srccmd = SIOCGIFPSRCADDR;
+ dstcmd = SIOCGIFPDSTADDR;
+ ifrp = &ifr;
+#endif /* INET6 */
+
+ if (ioctl(s, srccmd, (caddr_t)ifrp) < 0)
+ return;
+#ifdef INET6
+ if (ifrp->ifr_addr.sa_family == AF_INET6)
+ in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr);
+#endif
+ getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
+ psrcaddr, sizeof(psrcaddr), 0, 0, niflag);
+#ifdef INET6
+ if (ifrp->ifr_addr.sa_family == AF_INET6)
+ ver = "6";
+#endif
+
+ if (ioctl(s, dstcmd, (caddr_t)ifrp) < 0)
+ return;
+#ifdef INET6
+ if (ifrp->ifr_addr.sa_family == AF_INET6)
+ in6_fillscopeid((struct sockaddr_in6 *)&ifrp->ifr_addr);
+#endif
+ getnameinfo(&ifrp->ifr_addr, ifrp->ifr_addr.sa_len,
+ pdstaddr, sizeof(pdstaddr), 0, 0, niflag);
+
+ printf("\ttunnel inet%s %s --> %s\n", ver,
+ psrcaddr, pdstaddr);
+}
+
+void
in_status(s, info)
int s __unused;
struct rt_addrinfo * info;
@@ -1050,6 +1240,19 @@ in_status(s, info)
#ifdef INET6
void
+in6_fillscopeid(sin6)
+ 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
+}
+
+void
in6_status(s, info)
int s __unused;
struct rt_addrinfo * info;
@@ -1146,16 +1349,20 @@ in6_status(s, info)
printf("prefixlen %d ", prefix(&sin->sin6_addr,
sizeof(struct in6_addr)));
- if (flags6 & IN6_IFF_ANYCAST)
+ if ((flags6 & IN6_IFF_ANYCAST) != 0)
printf("anycast ");
- if (flags6 & IN6_IFF_TENTATIVE)
+ if ((flags6 & IN6_IFF_TENTATIVE) != 0)
printf("tentative ");
- if (flags6 & IN6_IFF_DUPLICATED)
+ if ((flags6 & IN6_IFF_DUPLICATED) != 0)
printf("duplicated ");
- if (flags6 & IN6_IFF_DETACHED)
+ if ((flags6 & IN6_IFF_DETACHED) != 0)
printf("detached ");
- if (flags6 & IN6_IFF_DEPRECATED)
+ if ((flags6 & IN6_IFF_DEPRECATED) != 0)
printf("deprecated ");
+ if ((flags6 & IN6_IFF_AUTOCONF) != 0)
+ printf("autoconf ");
+ if ((flags6 & IN6_IFF_TEMPORARY) != 0)
+ printf("temporary ");
if (scopeid)
printf("scopeid 0x%x ", scopeid);
diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8
index 6f8855d..eb3251c 100644
--- a/sbin/ping6/ping6.8
+++ b/sbin/ping6/ping6.8
@@ -1,4 +1,4 @@
-.\" $KAME: ping6.8,v 1.22 2000/05/31 17:00:07 itojun Exp $
+.\" $KAME: ping6.8,v 1.39 2001/04/04 00:08:34 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -40,9 +40,9 @@ packets to network hosts
.Sh SYNOPSIS
.Nm
.\" without ipsec, or new ipsec
-.Op Fl dfHnNqRvw
+.Op Fl dfHnNqRtvw
.\" old ipsec
-.\" .Op Fl AdEfnNqRvw
+.\" .Op Fl AdEfnNqRtvw
.Bk -words
.Op Fl a Ar addrtype
.Ek
@@ -184,13 +184,13 @@ option.
If
.Ar preload
is specified,
-.Nm ping
+.Nm
sends that many packets as fast as possible before falling into its normal
mode of behavior.
Only the super-user may use this option.
.It Fl n
Numeric output only.
-No attempt will be made to lookup symbolic names for host addresses.
+No attempt will be made to lookup symbolic names from addresses in the reply.
.It Fl N
Probe node information multicast group
.Pq Li ff02::2:xxxx:xxxx .
@@ -213,11 +213,6 @@ For example,
.Dq Li \-p ff
will cause the sent packet to be filled with all
ones.
-.Fl Q
-flag,
-.Nm
-prints out any ICMP error messages caused by its own ECHO_REQUEST
-messages.
.\" new ipsec
.It Fl P Ar policy
.Ar policy
@@ -259,6 +254,13 @@ header data.
You may need to specify
.Fl b
as well to extend socket buffer size.
+.It Fl t
+Generate ICMPv6 Node Information supported query types query,
+rather than echo-request.
+.Fl s
+has no effect if
+.Fl t
+is specified.
.It Fl v
Verbose output.
.Tn ICMP
@@ -266,7 +268,7 @@ packets other than
.Tn ECHO_RESPONSE
that are received are listed.
.It Fl w
-Generate ICMPv6 Node Information FQDN query, rather than echo-request.
+Generate ICMPv6 Node Information DNS Name query, rather than echo-request.
.Fl s
has no effect if
.Fl w
@@ -335,7 +337,7 @@ during normal operations or from automated scripts.
.\" If less than eight bytes of pad are specified, no round trip times are
.\" given.
.Sh DUPLICATE AND DAMAGED PACKETS
-.Nm Ping6
+.Nm
will report duplicate and damaged packets.
Duplicate packets should never occur when pinging a unicast address,
and seem to be caused by
@@ -350,7 +352,7 @@ to the same request.
.Pp
Damaged packets are obviously serious cause for alarm and often
indicate broken hardware somewhere in the
-.Nm ping
+.Nm
packet's path
.Pq in the network or in the hosts .
.Sh TRYING DIFFERENT DATA PATTERNS
@@ -386,8 +388,39 @@ option of
.Nm
returns 0 on success (the host is alive),
and non-zero if the arguments are incorrect or the host is not responding.
+.Sh EXAMPLES
+Normally,
+.Xr ping6 8
+works just like
+.Xr ping 8
+would work; the following will send ICMPv6 echo request to
+.Li dst.foo.com .
+.Bd -literal -offset indent
+ping6 -n dst.foo.com
+.Ed
+.Pp
+The following will probe hostnames for all nodes on the network link attached to
+.Li wi0
+interface.
+The address
+.Li ff02::1
+is named the link-local all-node multicast address, and the packet would
+reach every node on the network link.
+.Bd -literal -offset indent
+ping6 -w ff02::1%wi0
+.Ed
+.Pp
+The following will probe addresses assigned to the destination node,
+.Li dst.foo.com .
+.Bd -literal -offset indent
+ping6 -a agl dst.foo.com
+.Ed
+.Pp
.Sh SEE ALSO
.Xr netstat 1 ,
+.Xr icmp6 4 ,
+.Xr inet6 4 ,
+.Xr ip6 4 ,
.Xr ifconfig 8 ,
.Xr ping 8 ,
.Xr routed 8 ,
@@ -403,8 +436,8 @@ and non-zero if the arguments are incorrect or the host is not responding.
.Rs
.%A Matt Crawford
.%T "IPv6 Node Information Queries"
-.%N draft-ietf-ipngwg-icmp-name-lookups-05.txt
-.%D October 22, 1999
+.%N draft-ietf-ipngwg-icmp-name-lookups-07.txt
+.%D August 2000
.%O work in progress material
.Re
.Sh BUGS
@@ -438,7 +471,7 @@ option (or something like those) to specify the particular address family.
This essentially means that we have two different commands.
.Sh HISTORY
The
-.Nm ping
+.Xr ping 8
command appeared in
.Bx 4.3 .
The
diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c
index 3d529b6..e7079a3 100644
--- a/sbin/ping6/ping6.c
+++ b/sbin/ping6/ping6.c
@@ -1,4 +1,4 @@
-/* $KAME: ping6.c,v 1.54 2000/06/12 16:16:44 itojun Exp $ */
+/* $KAME: ping6.c,v 1.126 2001/05/17 03:39:08 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -99,8 +99,8 @@ static const char rcsid[] =
/*
* NOTE:
* USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics
- * as IPV6_PKTINFO. Some people object it (sin6_scope_id specifies *link* while
- * IPV6_PKTINFO specifies *interface*. Link is defined as collection of
+ * as IPV6_PKTINFO. Some people object it (sin6_scope_id specifies *link*
+ * while IPV6_PKTINFO specifies *interface*. Link is defined as collection of
* network attached to 1 or more interfaces)
*/
@@ -116,12 +116,16 @@ static const char rcsid[] =
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>
+#include <arpa/nameser.h>
#include <netdb.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+#include <math.h>
+#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -144,7 +148,8 @@ static const char rcsid[] =
#define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */
#define ICMP6ECHOTMLEN sizeof(struct timeval)
#define ICMP6_NIQLEN (ICMP6ECHOLEN + 8)
-#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12) /* 64 bits of nonce + 32 bits ttl */
+/* FQDN case, 64 bits of nonce + 32 bits ttl */
+#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12)
#define EXTRA 256 /* for AH and various other headers. weird. */
#define DEFDATALEN ICMP6ECHOTMLEN
#define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
@@ -158,7 +163,6 @@ static const char rcsid[] =
#define F_FLOOD 0x0001
#define F_INTERVAL 0x0002
-#define F_NUMERIC 0x0004
#define F_PINGFILLED 0x0008
#define F_QUIET 0x0010
#define F_RROUTE 0x0020
@@ -182,13 +186,16 @@ static const char rcsid[] =
#define F_HOSTNAME 0x10000
#define F_FQDNOLD 0x20000
#define F_NIGROUP 0x40000
+#define F_SUPTYPES 0x80000
+#define F_NOMINMTU 0x100000
+#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
u_int options;
#define IN6LEN sizeof(struct in6_addr)
#define SA6LEN sizeof(struct sockaddr_in6)
-#define DUMMY_PORT 10101
+#define DUMMY_PORT 10101
-#define SIN6(s) ((struct sockaddr_in6 *)(s))
+#define SIN6(s) ((struct sockaddr_in6 *)(s))
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -199,9 +206,9 @@ u_int options;
int mx_dup_ck = MAX_DUP_CHK;
char rcvd_tbl[MAX_DUP_CHK / 8];
-struct addrinfo *res;
-struct sockaddr_in6 dst; /* who to ping6 */
-struct sockaddr_in6 src; /* src addr of this packet */
+struct addrinfo *res;
+struct sockaddr_in6 dst; /* who to ping6 */
+struct sockaddr_in6 src; /* src addr of this packet */
int datalen = DEFDATALEN;
int s; /* socket file descriptor */
u_char outpack[MAXPACKETLEN];
@@ -209,21 +216,26 @@ char BSPACE = '\b'; /* characters written for flood */
char DOT = '.';
char *hostname;
int ident; /* process id to identify our packets */
+u_int8_t nonce[8]; /* nonce field for node information */
struct in6_addr srcaddr;
+int hoplimit = -1; /* hoplimit */
+int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
/* counters */
long npackets; /* max packets to transmit */
long nreceived; /* # of packets we got back */
long nrepeats; /* number of duplicates */
long ntransmitted; /* sequence # for outbound packets = #sent */
-int interval = 1; /* interval between packets */
-int hoplimit = -1; /* hoplimit */
+struct timeval interval = {1, 0}; /* interval between packets */
/* timing */
int timing; /* flag to do timing */
double tmin = 999999999.0; /* minimum round trip time */
double tmax = 0.0; /* maximum round trip time */
double tsum = 0.0; /* sum of all times, for doing average */
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
+#endif
/* for node addresses */
u_short naflags;
@@ -233,22 +245,38 @@ struct msghdr smsghdr;
struct iovec smsgiov;
char *scmsg = 0;
+volatile int signo;
+volatile sig_atomic_t seenalrm;
+volatile sig_atomic_t seenint;
+#ifdef SIGINFO
+volatile sig_atomic_t seeninfo;
+#endif
+
int main __P((int, char *[]));
void fill __P((char *, char *));
int get_hoplim __P((struct msghdr *));
+int get_pathmtu __P((struct msghdr *));
+void set_pathmtu __P((int));
struct in6_pktinfo *get_rcvpktinfo __P((struct msghdr *));
-void onalrm __P((int));
-void oninfo __P((int));
+void onsignal __P((int));
+void retransmit __P((void));
void onint __P((int));
+size_t pingerlen __P((void));
void pinger __P((void));
-const char *pr_addr __P((struct sockaddr_in6 *));
+const char *pr_addr __P((struct sockaddr *, int));
void pr_icmph __P((struct icmp6_hdr *, u_char *));
void pr_iph __P((struct ip6_hdr *));
+void pr_suptypes __P((struct icmp6_nodeinfo *, size_t));
void pr_nodeaddr __P((struct icmp6_nodeinfo *, int));
+int myechoreply __P((const struct icmp6_hdr *));
+int mynireply __P((const struct icmp6_nodeinfo *));
+char *dnsdecode __P((const u_char **, const u_char *, const u_char *,
+ u_char *, size_t));
void pr_pack __P((u_char *, int, struct msghdr *));
void pr_exthdrs __P((struct msghdr *));
void pr_ip6opt __P((void *));
void pr_rthdr __P((void *));
+int pr_bitrange __P((u_int32_t, int, int));
void pr_retip __P((struct ip6_hdr *, u_char *));
void summary __P((void));
void tvsub __P((struct timeval *, struct timeval *));
@@ -263,7 +291,7 @@ main(argc, argv)
{
struct itimerval itimer;
struct sockaddr_in6 from;
- struct timeval timeout;
+ struct timeval timeout, *tv;
struct addrinfo hints;
fd_set *fdmaskp;
int fdmasks;
@@ -283,6 +311,8 @@ main(argc, argv)
char *policy_in = NULL;
char *policy_out = NULL;
#endif
+ double intval;
+ size_t rthlen;
/* just to be sure */
memset(&smsghdr, 0, sizeof(&smsghdr));
@@ -291,54 +321,62 @@ main(argc, argv)
preload = 0;
datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
#ifndef IPSEC
- while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwW")) != EOF)
+#define ADDOPTS
#else
#ifdef IPSEC_POLICY_IPSEC
- while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwWP:")) != EOF)
+#define ADDOPTS "P:"
#else
- while ((ch = getopt(argc, argv, "a:b:c:dfHh:I:i:l:nNp:qRS:s:vwWAE")) != EOF)
+#define ADDOPTS "AE"
#endif /*IPSEC_POLICY_IPSEC*/
#endif
- {
- switch(ch) {
- case 'a':
- {
- char *cp;
-
- options |= F_NODEADDR;
- datalen = 2048; /* XXX: enough? */
- for (cp = optarg; *cp != '\0'; cp++) {
- switch(*cp) {
- case 'a':
- naflags |= NI_NODEADDR_FLAG_ALL;
- break;
- case 'c':
- case 'C':
- naflags |= NI_NODEADDR_FLAG_COMPAT;
- break;
- case 'l':
- case 'L':
- naflags |= NI_NODEADDR_FLAG_LINKLOCAL;
- break;
- case 's':
- case 'S':
- naflags |= NI_NODEADDR_FLAG_SITELOCAL;
- break;
- case 'g':
- case 'G':
- naflags |= NI_NODEADDR_FLAG_GLOBAL;
- break;
- case 'A': /* experimental. not in the spec */
- naflags |= NI_NODEADDR_FLAG_ANYCAST;
- break;
- default:
- usage();
- /*NOTREACHED*/
- }
- }
- break;
- }
- case 'b':
+ while ((ch = getopt(argc, argv,
+ "a:b:c:dfHh:I:i:l:mnNp:qRS:s:tvwW" ADDOPTS)) != -1) {
+#undef ADDOPTS
+ switch (ch) {
+ case 'a':
+ {
+ char *cp;
+
+ options &= ~F_NOUSERDATA;
+ options |= F_NODEADDR;
+ for (cp = optarg; *cp != '\0'; cp++) {
+ switch (*cp) {
+ case 'a':
+ naflags |= NI_NODEADDR_FLAG_ALL;
+ break;
+ case 'c':
+ case 'C':
+ naflags |= NI_NODEADDR_FLAG_COMPAT;
+ break;
+ case 'l':
+ case 'L':
+ naflags |= NI_NODEADDR_FLAG_LINKLOCAL;
+ break;
+ case 's':
+ case 'S':
+ naflags |= NI_NODEADDR_FLAG_SITELOCAL;
+ break;
+ case 'g':
+ case 'G':
+ naflags |= NI_NODEADDR_FLAG_GLOBAL;
+ break;
+ case 'A': /* experimental. not in the spec */
+#ifdef NI_NODEADDR_FLAG_ANYCAST
+ naflags |= NI_NODEADDR_FLAG_ANYCAST;
+ break;
+#else
+ errx(1,
+"-a A is not supported on the platform");
+ /*NOTREACHED*/
+#endif
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ break;
+ }
+ case 'b':
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
sockbufsize = atoi(optarg);
#else
@@ -380,10 +418,23 @@ main(argc, argv)
#endif
break;
case 'i': /* wait between sending packets */
- interval = strtol(optarg, &e, 10);
- if (interval <= 0 || *optarg == '\0' || *e != '\0')
- errx(1,
- "illegal timing interval -- %s", optarg);
+ intval = strtod(optarg, &e);
+ if (*optarg == '\0' || *e != '\0')
+ errx(1, "illegal timing interval %s", optarg);
+ if (intval < 1 && getuid()) {
+ errx(1, "%s: only root may use interval < 1s",
+ strerror(EPERM));
+ }
+ interval.tv_sec = (long)intval;
+ interval.tv_usec =
+ (long)((intval - interval.tv_sec) * 1000000);
+ if (interval.tv_sec < 0)
+ errx(1, "illegal timing interval %s", optarg);
+ /* less than 1/hz does not make sense */
+ if (interval.tv_sec == 0 && interval.tv_usec < 10000) {
+ warnx("too small interval, raised to 0.01");
+ interval.tv_usec = 10000;
+ }
options |= F_INTERVAL;
break;
case 'l':
@@ -395,8 +446,16 @@ main(argc, argv)
if (preload < 0 || *optarg == '\0' || *e != '\0')
errx(1, "illegal preload value -- %s", optarg);
break;
+ case 'm':
+#ifdef IPV6_USE_MIN_MTU
+ options |= F_NOMINMTU;
+ break;
+#else
+ errx(1, "-%c is not supported on this platform", ch);
+ /*NOTREACHED*/
+#endif
case 'n':
- options |= F_NUMERIC;
+ options &= ~F_HOSTNAME;
break;
case 'N':
options |= F_NIGROUP;
@@ -426,18 +485,25 @@ main(argc, argv)
datalen = strtol(optarg, &e, 10);
if (datalen <= 0 || *optarg == '\0' || *e != '\0')
errx(1, "illegal datalen value -- %s", optarg);
- if (datalen > MAXDATALEN)
+ if (datalen > MAXDATALEN) {
errx(1,
"datalen value too large, maximum is %d",
MAXDATALEN);
+ }
+ break;
+ case 't':
+ options &= ~F_NOUSERDATA;
+ options |= F_SUPTYPES;
break;
case 'v':
options |= F_VERBOSE;
break;
case 'w':
+ options &= ~F_NOUSERDATA;
options |= F_FQDN;
break;
case 'W':
+ options &= ~F_NOUSERDATA;
options |= F_FQDNOLD;
break;
#ifdef IPSEC
@@ -476,11 +542,17 @@ main(argc, argv)
}
if (argc > 1) {
-#ifdef USE_SIN6_SCOPE_ID
- ip6optlen += CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1));
-#else /* old advanced API */
- ip6optlen += inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);
+#ifdef IPV6_RECVRTHDR /* 2292bis */
+ rthlen = CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0,
+ argc - 1));
+#else /* RFC2292 */
+ rthlen = inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);
#endif
+ if (rthlen == 0) {
+ errx(1, "too many intermediate hops");
+ /*NOTREACHED*/
+ }
+ ip6optlen += rthlen;
}
if (options & F_NIGROUP) {
@@ -494,8 +566,7 @@ main(argc, argv)
/* getaddrinfo */
bzero(&hints, sizeof(struct addrinfo));
- if ((options & F_NUMERIC) != 0)
- hints.ai_flags = AI_CANONNAME;
+ hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_ICMPV6;
@@ -509,28 +580,91 @@ main(argc, argv)
hostname = res->ai_canonname;
else
hostname = target;
-
+
if (!res->ai_addr)
errx(1, "getaddrinfo failed");
(void)memcpy(&dst, res->ai_addr, res->ai_addrlen);
+ if ((s = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol)) < 0)
+ err(1, "socket");
+
+ /*
+ * let the kerel pass extension headers of incoming packets,
+ * for privileged socket options
+ */
+ if ((options & F_VERBOSE) != 0) {
+ int opton = 1;
+
+#ifdef IPV6_RECVHOPOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVHOPOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_HOPOPTS)");
+#endif
+#ifdef IPV6_RECVDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVDSTOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_DSTOPTS)");
+#endif
+#ifdef IPV6_RECVRTHDRDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
+#endif
+ }
+
+ /* revoke root privilege */
+ seteuid(getuid());
+ setuid(getuid());
+
if (options & F_FLOOD && options & F_INTERVAL)
errx(1, "-f and -i incompatible options");
- if (datalen >= sizeof(struct timeval)) /* can we time transfer */
- timing = 1;
- packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ if ((options & F_NOUSERDATA) == 0) {
+ if (datalen >= sizeof(struct timeval)) {
+ /* we can time transfer */
+ timing = 1;
+ } else
+ timing = 0;
+ /* in F_VERBOSE case, we may get non-echoreply packets*/
+ if (options & F_VERBOSE)
+ packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ else
+ packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ } else {
+ /* suppress timing for node information query */
+ timing = 0;
+ datalen = 2048;
+ packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ }
+
if (!(packet = (u_char *)malloc((u_int)packlen)))
err(1, "Unable to allocate packet");
if (!(options & F_PINGFILLED))
- for (i = 8; i < datalen; ++i)
+ for (i = ICMP6ECHOLEN; i < packlen; ++i)
*datap++ = i;
ident = getpid() & 0xFFFF;
-
- if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
- err(1, "socket");
+#ifndef __OpenBSD__
+ gettimeofday(&timeout, NULL);
+ srand((unsigned int)(timeout.tv_sec ^ timeout.tv_usec ^ (long)ident));
+ memset(nonce, 0, sizeof(nonce));
+ for (i = 0; i < sizeof(nonce); i += sizeof(int))
+ *((int *)&nonce[i]) = rand();
+#else
+ memset(nonce, 0, sizeof(nonce));
+ for (i = 0; i < sizeof(nonce); i += sizeof(u_int32_t))
+ *((u_int32_t *)&nonce[i]) = arc4random();
+#endif
hold = 1;
@@ -540,8 +674,24 @@ main(argc, argv)
optval = IPV6_DEFHLIM;
if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &optval, sizeof(optval)) == -1)
+ &optval, sizeof(optval)) == -1)
err(1, "IPV6_MULTICAST_HOPS");
+#ifdef IPV6_USE_MIN_MTU
+ if ((options & F_NOMINMTU) == 0) {
+ optval = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_USE_MIN_MTU)");
+ }
+#ifdef IPV6_RECVPATHMTU
+ else {
+ optval = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_RECVPATHMTU)");
+ }
+#endif /* IPV6_RECVPATHMTU */
+#endif /* IPV6_USE_MIN_MTU */
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
@@ -556,18 +706,18 @@ main(argc, argv)
optval = IPSEC_LEVEL_REQUIRE;
#ifdef IPV6_AUTH_TRANS_LEVEL
if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
- &optval, sizeof(optval)) == -1)
+ &optval, sizeof(optval)) == -1)
err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)");
#else /* old def */
if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL,
- &optval, sizeof(optval)) == -1)
+ &optval, sizeof(optval)) == -1)
err(1, "setsockopt(IPV6_AUTH_LEVEL)");
#endif
}
if (options & F_ENCRYPT) {
optval = IPSEC_LEVEL_REQUIRE;
if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
- &optval, sizeof(optval)) == -1)
+ &optval, sizeof(optval)) == -1)
err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)");
}
#endif /*IPSEC_POLICY_IPSEC*/
@@ -579,7 +729,7 @@ main(argc, argv)
if (!(options & F_VERBOSE)) {
ICMP6_FILTER_SETBLOCKALL(&filt);
if ((options & F_FQDN) || (options & F_FQDNOLD) ||
- (options & F_NODEADDR))
+ (options & F_NODEADDR) || (options & F_SUPTYPES))
ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
else
ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
@@ -587,55 +737,31 @@ main(argc, argv)
ICMP6_FILTER_SETPASSALL(&filt);
}
if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
- sizeof(filt)) < 0)
+ sizeof(filt)) < 0)
err(1, "setsockopt(ICMP6_FILTER)");
}
#endif /*ICMP6_FILTER*/
/* let the kerel pass extension headers of incoming packets */
- /* TODO: implement parsing routine */
if ((options & F_VERBOSE) != 0) {
int opton = 1;
#ifdef IPV6_RECVRTHDR
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
- sizeof(opton)))
+ sizeof(opton)))
err(1, "setsockopt(IPV6_RECVRTHDR)");
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
- sizeof(opton)))
+ sizeof(opton)))
err(1, "setsockopt(IPV6_RTHDR)");
#endif
-#ifdef IPV6_RECVHOPOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVHOPOPTS)");
-#else /* old adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_HOPOPTS)");
-#endif
-#ifdef IPV6_RECVDSTOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVDSTOPTS)");
-#else /* olad adv. API */
- if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_DSTOPTS)");
-#endif
-#ifdef IPV6_RECVRTHDRDSTOPTS
- if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
- sizeof(opton)))
- err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
-#endif
}
/*
optval = 1;
if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
- &optval, sizeof(optval)) == -1)
+ &optval, sizeof(optval)) == -1)
err(1, "IPV6_MULTICAST_LOOP");
*/
@@ -673,7 +799,7 @@ main(argc, argv)
#ifndef USE_SIN6_SCOPE_ID
/* pktinfo must have already been allocated */
if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0)
- errx(1, "%s: invalid interface name", ifname);
+ errx(1, "%s: invalid interface name", ifname);
#else
if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0)
errx(1, "%s: invalid interface name", ifname);
@@ -714,34 +840,36 @@ main(argc, argv)
scmsgp->cmsg_type = IPV6_RTHDR;
rthdr = (struct ip6_rthdr *)CMSG_DATA(scmsgp);
rthdr = inet6_rth_init((void *)rthdr, rthdrlen,
- IPV6_RTHDR_TYPE_0, argc - 1);
+ IPV6_RTHDR_TYPE_0, argc - 1);
if (rthdr == NULL)
errx(1, "can't initialize rthdr");
#else /* old advanced API */
if ((scmsgp = (struct cmsghdr *)inet6_rthdr_init(scmsgp,
- IPV6_RTHDR_TYPE_0)) == 0)
+ IPV6_RTHDR_TYPE_0)) == 0)
errx(1, "can't initialize rthdr");
#endif /* USE_RFC2292BIS */
for (hops = 0; hops < argc - 1; hops++) {
struct addrinfo *iaip;
- if ((error = getaddrinfo(argv[hops], NULL, &hints, &iaip)))
+ if ((error = getaddrinfo(argv[hops], NULL, &hints,
+ &iaip)))
errx(1, "%s", gai_strerror(error));
- if (SIN6(res->ai_addr)->sin6_family != AF_INET6)
+ if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)
errx(1,
- "bad addr family of an intermediate addr");
+ "bad addr family of an intermediate addr");
#ifdef USE_RFC2292BIS
if (inet6_rth_add(rthdr,
- &(SIN6(iaip->ai_addr))->sin6_addr))
+ &(SIN6(iaip->ai_addr))->sin6_addr))
errx(1, "can't add an intermediate node");
#else /* old advanced API */
if (inet6_rthdr_add(scmsgp,
- &(SIN6(iaip->ai_addr))->sin6_addr,
- IPV6_RTHDR_LOOSE))
+ &(SIN6(iaip->ai_addr))->sin6_addr,
+ IPV6_RTHDR_LOOSE))
errx(1, "can't add an intermediate node");
#endif /* USE_RFC2292BIS */
+ freeaddrinfo(iaip);
}
#ifndef USE_RFC2292BIS
@@ -757,7 +885,7 @@ main(argc, argv)
* source selection
*/
int dummy, len = sizeof(src);
-
+
if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "UDP socket");
@@ -766,38 +894,31 @@ main(argc, argv)
src.sin6_port = ntohs(DUMMY_PORT);
src.sin6_scope_id = dst.sin6_scope_id;
-
-#ifdef USE_SIN6_SCOPE_ID
- src.sin6_scope_id = dst.sin6_scope_id;
-#endif
-
#ifdef USE_RFC2292BIS
if (pktinfo &&
setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,
- (void *)pktinfo, sizeof(*pktinfo)))
+ (void *)pktinfo, sizeof(*pktinfo)))
err(1, "UDP setsockopt(IPV6_PKTINFO)");
if (hoplimit != -1 &&
setsockopt(dummy, IPPROTO_IPV6, IPV6_HOPLIMIT,
- (void *)&hoplimit, sizeof(hoplimit)))
+ (void *)&hoplimit, sizeof(hoplimit)))
err(1, "UDP setsockopt(IPV6_HOPLIMIT)");
if (rthdr &&
setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR,
- (void *)rthdr, (rthdr->ip6r_len + 1) << 3))
+ (void *)rthdr, (rthdr->ip6r_len + 1) << 3))
err(1, "UDP setsockopt(IPV6_RTHDR)");
#else /* old advanced API */
if (smsghdr.msg_control &&
setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS,
- (void *)smsghdr.msg_control,
- smsghdr.msg_controllen)) {
+ (void *)smsghdr.msg_control, smsghdr.msg_controllen))
err(1, "UDP setsockopt(IPV6_PKTOPTIONS)");
- }
#endif
-
+
if (connect(dummy, (struct sockaddr *)&src, len) < 0)
err(1, "UDP connect");
-
+
if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0)
err(1, "getsockname");
@@ -809,10 +930,10 @@ main(argc, argv)
if (datalen > sockbufsize)
warnx("you need -b to increase socket buffer size");
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
- sizeof(sockbufsize)) < 0)
+ sizeof(sockbufsize)) < 0)
err(1, "setsockopt(SO_SNDBUF)");
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
- sizeof(sockbufsize)) < 0)
+ sizeof(sockbufsize)) < 0)
err(1, "setsockopt(SO_RCVBUF)");
}
else {
@@ -825,7 +946,8 @@ main(argc, argv)
* to get some stuff for /etc/ethers.
*/
hold = 48 * 1024;
- setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof(hold));
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
+ sizeof(hold));
}
#endif
@@ -833,64 +955,99 @@ main(argc, argv)
#ifndef USE_SIN6_SCOPE_ID
#ifdef IPV6_RECVPKTINFO
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
- sizeof(optval)) < 0)
+ sizeof(optval)) < 0)
warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval,
- sizeof(optval)) < 0)
+ sizeof(optval)) < 0)
warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */
#endif
#endif /* USE_SIN6_SCOPE_ID */
#ifdef IPV6_RECVHOPLIMIT
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,
- sizeof(optval)) < 0)
+ sizeof(optval)) < 0)
warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
#else /* old adv. API */
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,
- sizeof(optval)) < 0)
+ sizeof(optval)) < 0)
warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */
#endif
- printf("PING6(%d=40+8+%d bytes) ", datalen + 48, datalen);
- printf("%s --> ", pr_addr(&src));
- printf("%s\n", pr_addr(&dst));
+ printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
+ (unsigned long)(pingerlen() - 8));
+ printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
+ printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
while (preload--) /* Fire off them quickies. */
pinger();
- (void)signal(SIGINT, onint);
- (void)signal(SIGINFO, oninfo);
+ (void)signal(SIGINT, onsignal);
+#ifdef SIGINFO
+ (void)signal(SIGINFO, onsignal);
+#endif
if ((options & F_FLOOD) == 0) {
- (void)signal(SIGALRM, onalrm);
- itimer.it_interval.tv_sec = interval;
- itimer.it_interval.tv_usec = 0;
- itimer.it_value.tv_sec = 0;
- itimer.it_value.tv_usec = 1;
+ (void)signal(SIGALRM, onsignal);
+ itimer.it_interval = interval;
+ itimer.it_value = interval;
(void)setitimer(ITIMER_REAL, &itimer, NULL);
+ retransmit();
}
- fdmasks = howmany(s+1, NFDBITS);
+ fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
if ((fdmaskp = malloc(fdmasks)) == NULL)
err(1, "malloc");
+ signo = seenalrm = seenint = 0;
+#ifdef SIGINFO
+ seeninfo = 0;
+#endif
+
for (;;) {
struct msghdr m;
struct cmsghdr *cm;
u_char buf[1024];
struct iovec iov[2];
+ /* signal handling */
+ if (seenalrm) {
+ retransmit();
+ seenalrm = 0;
+ continue;
+ }
+ if (seenint) {
+ onint(SIGINT);
+ seenint = 0;
+ continue;
+ }
+#ifdef SIGINFO
+ if (seeninfo) {
+ summary();
+ seeninfo = 0;
+ continue;
+ }
+#endif
+
if (options & F_FLOOD) {
pinger();
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
- memset(fdmaskp, 0, fdmasks);
- FD_SET(s, fdmaskp);
- if (select(s + 1, fdmaskp, NULL, NULL, &timeout) < 1)
- continue;
- }
- fromlen = sizeof(from);
+ tv = &timeout;
+ } else
+ tv = NULL;
+ memset(fdmaskp, 0, fdmasks);
+ FD_SET(s, fdmaskp);
+ cc = select(s + 1, fdmaskp, NULL, NULL, tv);
+ if (cc < 0) {
+ if (errno != EINTR) {
+ warn("select");
+ sleep(1);
+ }
+ continue;
+ } else if (cc == 0)
+ continue;
+ fromlen = sizeof(from);
m.msg_name = (caddr_t)&from;
m.msg_namelen = sizeof(from);
memset(&iov, 0, sizeof(iov));
@@ -902,14 +1059,35 @@ main(argc, argv)
m.msg_control = (caddr_t)buf;
m.msg_controllen = sizeof(buf);
- if ((cc = recvmsg(s, &m, 0)) < 0) {
- if (errno == EINTR)
- continue;
- warn("recvfrom");
+ cc = recvmsg(s, &m, 0);
+ if (cc < 0) {
+ if (errno != EINTR) {
+ warn("recvmsg");
+ sleep(1);
+ }
+ continue;
+ } else if (cc == 0) {
+ int mtu;
+
+ /*
+ * receive control messages only. Process the
+ * exceptions (currently the only possiblity is
+ * a path MTU notification.)
+ */
+ if ((mtu = get_pathmtu(&m)) > 0) {
+ if ((options & F_VERBOSE) != 0) {
+ printf("new path MTU (%d) is "
+ "notified\n", mtu);
+ }
+ set_pathmtu(mtu);
+ }
continue;
+ } else {
+ /*
+ * an ICMPv6 message (probably an echoreply) arrived.
+ */
+ pr_pack(packet, cc, &m);
}
-
- pr_pack(packet, cc, &m);
if (npackets && nreceived >= npackets)
break;
}
@@ -917,14 +1095,32 @@ main(argc, argv)
exit(nreceived == 0);
}
+void
+onsignal(sig)
+ int sig;
+{
+ signo = sig;
+ switch (sig) {
+ case SIGALRM:
+ seenalrm++;
+ break;
+ case SIGINT:
+ seenint++;
+ break;
+#ifdef SIGINFO
+ case SIGINFO:
+ seeninfo++;
+ break;
+#endif
+ }
+}
+
/*
- * onalrm --
+ * retransmit --
* This routine transmits another ping6.
*/
-/* ARGSUSED */
void
-onalrm(signo)
- int signo;
+retransmit()
{
struct itimerval itimer;
@@ -961,32 +1157,51 @@ onalrm(signo)
* of the data portion are used to hold a UNIX "timeval" struct in VAX
* byte-order, to compute the round-trip time.
*/
+size_t
+pingerlen()
+{
+ size_t l;
+
+ if (options & F_FQDN)
+ l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ else if (options & F_FQDNOLD)
+ l = ICMP6_NIQLEN;
+ else if (options & F_NODEADDR)
+ l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ else if (options & F_SUPTYPES)
+ l = ICMP6_NIQLEN;
+ else
+ l = ICMP6ECHOLEN + datalen;
+
+ return l;
+}
+
void
pinger()
{
struct icmp6_hdr *icp;
struct iovec iov[2];
int i, cc;
+ struct icmp6_nodeinfo *nip;
+ int seq;
icp = (struct icmp6_hdr *)outpack;
+ nip = (struct icmp6_nodeinfo *)outpack;
memset(icp, 0, sizeof(*icp));
- icp->icmp6_code = 0;
icp->icmp6_cksum = 0;
- icp->icmp6_seq = ntransmitted++; /* htons later */
- icp->icmp6_id = htons(ident); /* ID */
-
- CLR(icp->icmp6_seq % mx_dup_ck);
- icp->icmp6_seq = htons(icp->icmp6_seq);
+ seq = ntransmitted++;
+ CLR(seq % mx_dup_ck);
if (options & F_FQDN) {
icp->icmp6_type = ICMP6_NI_QUERY;
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
- /* XXX: overwrite icmp6_id */
- ((struct icmp6_nodeinfo *)icp)->ni_qtype = htons(NI_QTYPE_FQDN);
- ((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
- if (timing)
- (void)gettimeofday((struct timeval *)
- &outpack[ICMP6ECHOLEN], NULL);
+ nip->ni_qtype = htons(NI_QTYPE_FQDN);
+ nip->ni_flags = htons(0);
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
sizeof(dst.sin6_addr));
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
@@ -994,39 +1209,58 @@ pinger()
} else if (options & F_FQDNOLD) {
/* packet format in 03 draft - no Subject data on queries */
icp->icmp6_type = ICMP6_NI_QUERY;
- /* code field is always 0 */
- /* XXX: overwrite icmp6_id */
- ((struct icmp6_nodeinfo *)icp)->ni_qtype = htons(NI_QTYPE_FQDN);
- ((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
- if (timing)
- (void)gettimeofday((struct timeval *)
- &outpack[ICMP6ECHOLEN], NULL);
+ icp->icmp6_code = 0; /* code field is always 0 */
+ nip->ni_qtype = htons(NI_QTYPE_FQDN);
+ nip->ni_flags = htons(0);
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
cc = ICMP6_NIQLEN;
datalen = 0;
} else if (options & F_NODEADDR) {
icp->icmp6_type = ICMP6_NI_QUERY;
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
- /* XXX: overwrite icmp6_id */
- ((struct icmp6_nodeinfo *)icp)->ni_qtype =
- htons(NI_QTYPE_NODEADDR);
- ((struct icmp6_nodeinfo *)icp)->ni_flags = htons(0);
- if (timing)
- (void)gettimeofday((struct timeval *)
- &outpack[ICMP6ECHOLEN], NULL);
+ nip->ni_qtype = htons(NI_QTYPE_NODEADDR);
+ nip->ni_flags = naflags;
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
sizeof(dst.sin6_addr));
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
datalen = 0;
- ((struct icmp6_nodeinfo *)icp)->ni_flags = naflags;
- }
- else {
+ } else if (options & F_SUPTYPES) {
+ icp->icmp6_type = ICMP6_NI_QUERY;
+ icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/
+ nip->ni_qtype = htons(NI_QTYPE_SUPTYPES);
+ /* we support compressed bitmap */
+ nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS;
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+ cc = ICMP6_NIQLEN;
+ datalen = 0;
+ } else {
icp->icmp6_type = ICMP6_ECHO_REQUEST;
+ icp->icmp6_code = 0;
+ icp->icmp6_id = htons(ident);
+ icp->icmp6_seq = ntohs(seq);
if (timing)
(void)gettimeofday((struct timeval *)
&outpack[ICMP6ECHOLEN], NULL);
cc = ICMP6ECHOLEN + datalen;
}
+#ifdef DIAGNOSTIC
+ if (pingerlen() != cc)
+ errx(1, "internal error; length mismatch");
+#endif
+
smsghdr.msg_name = (caddr_t)&dst;
smsghdr.msg_namelen = sizeof(dst);
memset(&iov, 0, sizeof(iov));
@@ -1047,6 +1281,91 @@ pinger()
(void)write(STDOUT_FILENO, &DOT, 1);
}
+int
+myechoreply(icp)
+ const struct icmp6_hdr *icp;
+{
+ if (ntohs(icp->icmp6_id) == ident)
+ return 1;
+ else
+ return 0;
+}
+
+int
+mynireply(nip)
+ const struct icmp6_nodeinfo *nip;
+{
+ if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t),
+ nonce + sizeof(u_int16_t),
+ sizeof(nonce) - sizeof(u_int16_t)) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+char *
+dnsdecode(sp, ep, base, buf, bufsiz)
+ const u_char **sp;
+ const u_char *ep;
+ const u_char *base; /*base for compressed name*/
+ u_char *buf;
+ size_t bufsiz;
+{
+ int i;
+ const u_char *cp;
+ char cresult[MAXDNAME + 1];
+ const u_char *comp;
+ int l;
+
+ cp = *sp;
+ *buf = '\0';
+
+ if (cp >= ep)
+ return NULL;
+ while (cp < ep) {
+ i = *cp;
+ if (i == 0 || cp != *sp) {
+ if (strlcat(buf, ".", bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ }
+ if (i == 0)
+ break;
+ cp++;
+
+ if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
+ /* DNS compression */
+ if (!base)
+ return NULL;
+
+ comp = base + (i & 0x3f);
+ if (dnsdecode(&comp, cp, base, cresult,
+ sizeof(cresult)) == NULL)
+ return NULL;
+ if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ break;
+ } else if ((i & 0x3f) == i) {
+ if (i > ep - cp)
+ return NULL; /*source overrun*/
+ while (i-- > 0 && cp < ep) {
+ l = snprintf(cresult, sizeof(cresult),
+ isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
+ if (l >= sizeof(cresult))
+ return NULL;
+ if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ cp++;
+ }
+ } else
+ return NULL; /*invalid label*/
+ }
+ if (i != 0)
+ return NULL; /*not terminated*/
+ cp++;
+ *sp = cp;
+ return buf;
+}
+
/*
* pr_pack --
* Print out the packet, if it came from us. This logic is necessary
@@ -1062,9 +1381,11 @@ pr_pack(buf, cc, mhdr)
{
#define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c)
struct icmp6_hdr *icp;
+ struct icmp6_nodeinfo *ni;
int i;
int hoplim;
- struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
+ struct sockaddr *from;
+ int fromlen;
u_char *cp = NULL, *dp, *end = buf + cc;
struct in6_pktinfo *pktinfo = NULL;
struct timeval tv, *tp;
@@ -1072,16 +1393,28 @@ pr_pack(buf, cc, mhdr)
int dupflag;
size_t off;
int oldfqdn;
+ u_int16_t seq;
+ char dnsname[MAXDNAME + 1];
(void)gettimeofday(&tv, NULL);
+ if (!mhdr || !mhdr->msg_name ||
+ mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
+ ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) {
+ if (options & F_VERBOSE)
+ warnx("invalid peername\n");
+ return;
+ }
+ from = (struct sockaddr *)mhdr->msg_name;
+ fromlen = mhdr->msg_namelen;
if (cc < sizeof(struct icmp6_hdr)) {
if (options & F_VERBOSE)
warnx("packet too short (%d bytes) from %s\n", cc,
- pr_addr(from));
+ pr_addr(from, fromlen));
return;
}
icp = (struct icmp6_hdr *)buf;
+ ni = (struct icmp6_nodeinfo *)buf;
off = 0;
if ((hoplim = get_hoplim(mhdr)) == -1) {
@@ -1093,11 +1426,8 @@ pr_pack(buf, cc, mhdr)
return;
}
- if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
- /* XXX the following line overwrites the original packet */
- icp->icmp6_seq = ntohs(icp->icmp6_seq);
- if (ntohs(icp->icmp6_id) != ident)
- return; /* It was not our ECHO */
+ if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
+ seq = ntohs(icp->icmp6_seq);
++nreceived;
if (timing) {
tp = (struct timeval *)(icp + 1);
@@ -1105,18 +1435,21 @@ pr_pack(buf, cc, mhdr)
triptime = ((double)tv.tv_sec) * 1000.0 +
((double)tv.tv_usec) / 1000.0;
tsum += triptime;
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ tsumsq += triptime * triptime;
+#endif
if (triptime < tmin)
tmin = triptime;
if (triptime > tmax)
tmax = triptime;
}
- if (TST(icp->icmp6_seq % mx_dup_ck)) {
+ if (TST(seq % mx_dup_ck)) {
++nrepeats;
--nreceived;
dupflag = 1;
} else {
- SET(icp->icmp6_seq % mx_dup_ck);
+ SET(seq % mx_dup_ck);
dupflag = 0;
}
@@ -1127,18 +1460,21 @@ pr_pack(buf, cc, mhdr)
(void)write(STDOUT_FILENO, &BSPACE, 1);
else {
(void)printf("%d bytes from %s, icmp_seq=%u", cc,
- pr_addr(from),
- icp->icmp6_seq);
+ pr_addr(from, fromlen), seq);
(void)printf(" hlim=%d", hoplim);
if ((options & F_VERBOSE) != 0) {
struct sockaddr_in6 dstsa;
memset(&dstsa, 0, sizeof(dstsa));
dstsa.sin6_family = AF_INET6;
+#ifdef SIN6_LEN
dstsa.sin6_len = sizeof(dstsa);
+#endif
dstsa.sin6_scope_id = pktinfo->ipi6_ifindex;
dstsa.sin6_addr = pktinfo->ipi6_addr;
- (void)printf(" dst=%s", pr_addr(&dstsa));
+ (void)printf(" dst=%s",
+ pr_addr((struct sockaddr *)&dstsa,
+ sizeof(dstsa)));
}
if (timing)
(void)printf(" time=%g ms", triptime);
@@ -1154,24 +1490,50 @@ pr_pack(buf, cc, mhdr)
}
}
}
- } else if (icp->icmp6_type == ICMP6_NI_REPLY) { /* ICMP6_NI_REPLY */
- struct icmp6_nodeinfo *ni = (struct icmp6_nodeinfo *)(buf + off);
-
- (void)printf("%d bytes from %s: ", cc,
- pr_addr(from));
-
- switch(ntohs(ni->ni_qtype)) {
- case NI_QTYPE_NOOP:
- printf("NodeInfo NOOP");
- break;
- case NI_QTYPE_SUPTYPES:
- printf("NodeInfo Supported Qtypes");
- break;
- case NI_QTYPE_NODEADDR:
- pr_nodeaddr(ni, end - (u_char *)ni);
- break;
- case NI_QTYPE_FQDN:
- default: /* XXX: for backward compatibility */
+ } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {
+ seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce);
+ ++nreceived;
+ if (TST(seq % mx_dup_ck)) {
+ ++nrepeats;
+ --nreceived;
+ dupflag = 1;
+ } else {
+ SET(seq % mx_dup_ck);
+ dupflag = 0;
+ }
+
+ if (options & F_QUIET)
+ return;
+
+ (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
+
+ switch (ntohs(ni->ni_code)) {
+ case ICMP6_NI_SUCCESS:
+ break;
+ case ICMP6_NI_REFUSED:
+ printf("refused, type 0x%x", ntohs(ni->ni_type));
+ goto fqdnend;
+ case ICMP6_NI_UNKNOWN:
+ printf("unknown, type 0x%x", ntohs(ni->ni_type));
+ goto fqdnend;
+ default:
+ printf("unknown code 0x%x, type 0x%x",
+ ntohs(ni->ni_code), ntohs(ni->ni_type));
+ goto fqdnend;
+ }
+
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ printf("NodeInfo NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ pr_suptypes(ni, end - (u_char *)ni);
+ break;
+ case NI_QTYPE_NODEADDR:
+ pr_nodeaddr(ni, end - (u_char *)ni);
+ break;
+ case NI_QTYPE_FQDN:
+ default: /* XXX: for backward compatibility */
cp = (u_char *)ni + ICMP6_NIRLEN;
if (buf[off + ICMP6_NIRLEN] ==
cc - off - ICMP6_NIRLEN - 1)
@@ -1179,38 +1541,31 @@ pr_pack(buf, cc, mhdr)
else
oldfqdn = 0;
if (oldfqdn) {
- cp++;
+ cp++; /* skip length */
while (cp < end) {
safeputc(*cp & 0xff);
cp++;
}
} else {
+ i = 0;
while (cp < end) {
- i = *cp++;
- if (i) {
- if (i > end - cp) {
- printf("???");
- break;
- }
- while (i-- && cp < end) {
- safeputc(*cp & 0xff);
- cp++;
- }
- if (cp + 1 < end && *cp)
- printf(".");
- } else {
- if (cp == end) {
- /* FQDN */
- printf(".");
- } else if (cp + 1 == end &&
- *cp == '\0') {
- /* truncated */
- } else {
- /* invalid */
- printf("???");
- }
+ if (dnsdecode((const u_char **)&cp, end,
+ (const u_char *)(ni + 1), dnsname,
+ sizeof(dnsname)) == NULL) {
+ printf("???");
break;
}
+ /*
+ * name-lookup special handling for
+ * truncated name
+ */
+ if (cp + 1 <= end && !*cp &&
+ strlen(dnsname) > 0) {
+ dnsname[strlen(dnsname) - 1] = '\0';
+ cp++;
+ }
+ printf("%s%s", i > 0 ? "," : "",
+ dnsname);
}
}
if (options & F_VERBOSE) {
@@ -1219,7 +1574,7 @@ pr_pack(buf, cc, mhdr)
(void)printf(" ("); /*)*/
- switch(ni->ni_code) {
+ switch (ni->ni_code) {
case ICMP6_NI_REFUSED:
(void)printf("refused");
comma++;
@@ -1231,19 +1586,21 @@ pr_pack(buf, cc, mhdr)
}
if ((end - (u_char *)ni) < ICMP6_NIRLEN) {
- /* case of refusion, unkown */
+ /* case of refusion, unknown */
+ /*(*/
+ putchar(')');
goto fqdnend;
}
ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]);
if (comma)
printf(",");
- if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL))
+ if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) {
(void)printf("TTL=%d:meaningless",
- (int)ttl);
- else {
+ (int)ttl);
+ } else {
if (ttl < 0) {
(void)printf("TTL=%d:invalid",
- ttl);
+ ttl);
} else
(void)printf("TTL=%d", ttl);
}
@@ -1269,22 +1626,21 @@ pr_pack(buf, cc, mhdr)
if (comma)
printf(",");
(void)printf("invalid namelen:%d/%lu",
- buf[off + ICMP6_NIRLEN],
- (u_long)cc - off - ICMP6_NIRLEN - 1);
+ buf[off + ICMP6_NIRLEN],
+ (u_long)cc - off - ICMP6_NIRLEN - 1);
comma++;
}
/*(*/
putchar(')');
}
- fqdnend:
+ fqdnend:
;
}
} else {
/* We've got something other than an ECHOREPLY */
if (!(options & F_VERBOSE))
return;
- (void)printf("%d bytes from %s: ", cc,
- pr_addr(from));
+ (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
pr_icmph(icp, end);
}
@@ -1308,7 +1664,7 @@ pr_exthdrs(mhdr)
if (cm->cmsg_level != IPPROTO_IPV6)
continue;
- switch(cm->cmsg_type) {
+ switch (cm->cmsg_type) {
case IPV6_HOPOPTS:
printf(" HbH Options: ");
pr_ip6opt(CMSG_DATA(cm));
@@ -1343,13 +1699,13 @@ pr_ip6opt(void *extbuf)
ext = (struct ip6_hbh *)extbuf;
extlen = (ext->ip6h_len + 1) * 8;
- printf("nxt %u, len %u (%d bytes)\n", ext->ip6h_nxt,
- ext->ip6h_len, extlen);
+ printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
+ (unsigned int)ext->ip6h_len, (unsigned long)extlen);
currentlen = 0;
while (1) {
currentlen = inet6_opt_next(extbuf, extlen, currentlen,
- &type, &len, &databuf);
+ &type, &len, &databuf);
if (currentlen == -1)
break;
switch (type) {
@@ -1360,19 +1716,20 @@ pr_ip6opt(void *extbuf)
case IP6OPT_JUMBO:
offset = 0;
offset = inet6_opt_get_val(databuf, offset,
- &value4, sizeof(value4));
+ &value4, sizeof(value4));
printf(" Jumbo Payload Opt: Length %u\n",
- (unsigned int)ntohl(value4));
+ (u_int32_t)ntohl(value4));
break;
case IP6OPT_ROUTER_ALERT:
offset = 0;
offset = inet6_opt_get_val(databuf, offset,
&value2, sizeof(value2));
printf(" Router Alert Opt: Type %u\n",
- ntohs(value2));
+ ntohs(value2));
break;
default:
- printf(" Received Opt %u len %u\n", type, len);
+ printf(" Received Opt %u len %lu\n",
+ type, (unsigned long)len);
break;
}
}
@@ -1399,7 +1756,7 @@ pr_rthdr(void *extbuf)
/* print fixed part of the header */
printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
- rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
+ rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
if ((segments = inet6_rth_segments(extbuf)) >= 0)
printf("%d segments, ", segments);
else
@@ -1410,15 +1767,18 @@ pr_rthdr(void *extbuf)
in6 = inet6_rth_getaddr(extbuf, i);
if (in6 == NULL)
printf(" [%d]<NULL>\n", i);
- else
- printf(" [%d]%s\n", i,
- inet_ntop(AF_INET6, in6,
- ntopbuf, sizeof(ntopbuf)));
+ else {
+ if (!inet_ntop(AF_INET6, in6, ntopbuf,
+ sizeof(ntopbuf)))
+ strncpy(ntopbuf, "?", sizeof(ntopbuf));
+ printf(" [%d]%s\n", i, ntopbuf);
+ }
}
return;
-
+
}
+
#else /* !USE_RFC2292BIS */
/* ARGSUSED */
void
@@ -1429,35 +1789,186 @@ pr_rthdr(void *extbuf)
}
#endif /* USE_RFC2292BIS */
+int
+pr_bitrange(v, s, ii)
+ u_int32_t v;
+ int s;
+ int ii;
+{
+ int off;
+ int i;
+
+ off = 0;
+ while (off < 32) {
+ /* shift till we have 0x01 */
+ if ((v & 0x01) == 0) {
+ if (ii > 1)
+ printf("-%u", s + off - 1);
+ ii = 0;
+ switch (v & 0x0f) {
+ case 0x00:
+ v >>= 4;
+ off += 4;
+ continue;
+ case 0x08:
+ v >>= 3;
+ off += 3;
+ continue;
+ case 0x04: case 0x0c:
+ v >>= 2;
+ off += 2;
+ continue;
+ default:
+ v >>= 1;
+ off += 1;
+ continue;
+ }
+ }
+
+ /* we have 0x01 with us */
+ for (i = 0; i < 32 - off; i++) {
+ if ((v & (0x01 << i)) == 0)
+ break;
+ }
+ if (!ii)
+ printf(" %u", s + off);
+ ii += i;
+ v >>= i; off += i;
+ }
+ return ii;
+}
+
+void
+pr_suptypes(ni, nilen)
+ struct icmp6_nodeinfo *ni; /* ni->qtype must be SUPTYPES */
+ size_t nilen;
+{
+ size_t clen;
+ u_int32_t v;
+ const u_char *cp, *end;
+ u_int16_t cur;
+ struct cbit {
+ u_int16_t words; /*32bit count*/
+ u_int16_t skip;
+ } cbit;
+#define MAXQTYPES (1 << 16)
+ size_t off;
+ int b;
+
+ cp = (u_char *)(ni + 1);
+ end = ((u_char *)ni) + nilen;
+ cur = 0;
+ b = 0;
+
+ printf("NodeInfo Supported Qtypes");
+ if (options & F_VERBOSE) {
+ if (ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS)
+ printf(", compressed bitmap");
+ else
+ printf(", raw bitmap");
+ }
+
+ while (cp < end) {
+ clen = (size_t)(end - cp);
+ if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) == 0) {
+ if (clen == 0 || clen > MAXQTYPES / 8 ||
+ clen % sizeof(v)) {
+ printf("???");
+ return;
+ }
+ } else {
+ if (clen < sizeof(cbit) || clen % sizeof(v))
+ return;
+ memcpy(&cbit, cp, sizeof(cbit));
+ if (sizeof(cbit) + ntohs(cbit.words) * sizeof(v) >
+ clen)
+ return;
+ cp += sizeof(cbit);
+ clen = ntohs(cbit.words) * sizeof(v);
+ if (cur + clen * 8 + (u_long)ntohs(cbit.skip) * 32 >
+ MAXQTYPES)
+ return;
+ }
+
+ for (off = 0; off < clen; off += sizeof(v)) {
+ memcpy(&v, cp + off, sizeof(v));
+ v = (u_int32_t)ntohl(v);
+ b = pr_bitrange(v, (int)(cur + off * 8), b);
+ }
+ /* flush the remaining bits */
+ b = pr_bitrange(0, (int)(cur + off * 8), b);
+
+ cp += clen;
+ cur += clen * 8;
+ if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0)
+ cur += ntohs(cbit.skip) * 32;
+ }
+}
void
pr_nodeaddr(ni, nilen)
struct icmp6_nodeinfo *ni; /* ni->qtype must be NODEADDR */
int nilen;
{
- struct in6_addr *ia6 = (struct in6_addr *)(ni + 1);
+ u_char *cp = (u_char *)(ni + 1);
char ntop_buf[INET6_ADDRSTRLEN];
+ int withttl = 0;
nilen -= sizeof(struct icmp6_nodeinfo);
if (options & F_VERBOSE) {
- switch(ni->ni_code) {
- case ICMP6_NI_REFUSED:
- (void)printf("refused");
- break;
- case ICMP6_NI_UNKNOWN:
- (void)printf("unknown qtype");
- break;
+ switch (ni->ni_code) {
+ case ICMP6_NI_REFUSED:
+ (void)printf("refused");
+ break;
+ case ICMP6_NI_UNKNOWN:
+ (void)printf("unknown qtype");
+ break;
}
- if (ni->ni_flags & NI_NODEADDR_FLAG_ALL)
+ if (ni->ni_flags & NI_NODEADDR_FLAG_TRUNCATE)
(void)printf(" truncated");
}
putchar('\n');
if (nilen <= 0)
printf(" no address\n");
- for (; nilen > 0; nilen -= sizeof(*ia6), ia6 += 1) {
- printf(" %s\n",
- inet_ntop(AF_INET6, ia6, ntop_buf, sizeof(ntop_buf)));
+
+ /*
+ * In icmp-name-lookups 05 and later, TTL of each returned address
+ * is contained in the resposne. We try to detect the version
+ * by the length of the data, but note that the detection algorithm
+ * is incomplete. We assume the latest draft by default.
+ */
+ if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0)
+ withttl = 1;
+ while (nilen > 0) {
+ u_int32_t ttl;
+
+ if (withttl) {
+ /* XXX: alignment? */
+ ttl = (u_int32_t)ntohl(*(u_int32_t *)cp);
+ cp += sizeof(u_int32_t);
+ nilen -= sizeof(u_int32_t);
+ }
+
+ if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) ==
+ NULL)
+ strncpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf(" %s", ntop_buf);
+ if (withttl) {
+ if (ttl == 0xffffffff) {
+ /*
+ * XXX: can this convention be applied to all
+ * type of TTL (i.e. non-ND TTL)?
+ */
+ printf("(TTL=infty)");
+ }
+ else
+ printf("(TTL=%u)", ttl);
+ }
+ putchar('\n');
+
+ nilen -= sizeof(struct in6_addr);
+ cp += sizeof(struct in6_addr);
}
}
@@ -1469,6 +1980,9 @@ get_hoplim(mhdr)
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(-1);
+
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_HOPLIMIT &&
cm->cmsg_len == CMSG_LEN(sizeof(int)))
@@ -1486,6 +2000,9 @@ get_rcvpktinfo(mhdr)
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(NULL);
+
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_PKTINFO &&
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
@@ -1495,6 +2012,116 @@ get_rcvpktinfo(mhdr)
return(NULL);
}
+int
+get_pathmtu(mhdr)
+ struct msghdr *mhdr;
+{
+#ifdef IPV6_RECVPATHMTU
+ struct cmsghdr *cm;
+ struct ip6_mtuinfo *mtuctl = NULL;
+
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(0);
+
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_PATHMTU &&
+ cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {
+ mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm);
+
+ /*
+ * If the notified destination is different from
+ * the one we are pinging, just ignore the info.
+ * We check the scope ID only when both notified value
+ * and our own value have non-0 values, because we may
+ * have used the default scope zone ID for sending,
+ * in which case the scope ID value is 0.
+ */
+ if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr,
+ &dst.sin6_addr) ||
+ (mtuctl->ip6m_addr.sin6_scope_id &&
+ dst.sin6_scope_id &&
+ mtuctl->ip6m_addr.sin6_scope_id !=
+ dst.sin6_scope_id)) {
+ if ((options & F_VERBOSE) != 0) {
+ printf("path MTU for %s is notified. "
+ "(ignored)\n",
+ pr_addr((struct sockaddr *)&mtuctl->ip6m_addr,
+ sizeof(mtuctl->ip6m_addr)));
+ }
+ return(0);
+ }
+
+ /*
+ * Ignore an invalid MTU. XXX: can we just believe
+ * the kernel check?
+ */
+ if (mtuctl->ip6m_mtu < IPV6_MMTU)
+ return(0);
+
+ /* notification for our destination. return the MTU. */
+ return((int)mtuctl->ip6m_mtu);
+ }
+ }
+#endif
+ return(0);
+}
+
+void
+set_pathmtu(mtu)
+ int mtu;
+{
+#ifdef IPV6_USE_MTU
+ static int firsttime = 1;
+ struct cmsghdr *cm;
+
+ if (firsttime) {
+ int oldlen = smsghdr.msg_controllen;
+ char *oldbuf = smsghdr.msg_control;
+
+ /* XXX: We need to enlarge control message buffer */
+ firsttime = 0; /* prevent further enlargement */
+
+ smsghdr.msg_controllen = oldlen + CMSG_SPACE(sizeof(int));
+ if ((smsghdr.msg_control =
+ (char *)malloc(smsghdr.msg_controllen)) == NULL)
+ err(1, "set_pathmtu: malloc");
+ cm = (struct cmsghdr *)CMSG_FIRSTHDR(&smsghdr);
+ cm->cmsg_len = CMSG_LEN(sizeof(int));
+ cm->cmsg_level = IPPROTO_IPV6;
+ cm->cmsg_type = IPV6_USE_MTU;
+
+ cm = (struct cmsghdr *)CMSG_NXTHDR(&smsghdr, cm);
+ if (oldlen)
+ memcpy((void *)cm, (void *)oldbuf, oldlen);
+
+ free(oldbuf);
+ }
+
+ /*
+ * look for a cmsgptr that points MTU structure.
+ * XXX: this procedure seems redundant at this moment, but we'd better
+ * keep the code generic enough for future extensions.
+ */
+ for (cm = CMSG_FIRSTHDR(&smsghdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(&smsghdr, cm)) {
+ if (cm->cmsg_len == 0) /* XXX: paranoid check */
+ errx(1, "set_pathmtu: internal error");
+
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_USE_MTU &&
+ cm->cmsg_len == CMSG_LEN(sizeof(int)))
+ break;
+ }
+
+ if (cm == NULL)
+ errx(1, "set_pathmtu: internal error: no space for path MTU");
+
+ *(int *)CMSG_DATA(cm) = mtu;
+#endif
+}
+
/*
* tvsub --
* Subtract 2 timeval structs: out = out - in. Out is assumed to
@@ -1512,18 +2139,6 @@ tvsub(out, in)
}
/*
- * oninfo --
- * SIGINFO handler.
- */
-/* ARGSUSED */
-void
-oninfo(notused)
- int notused;
-{
- summary();
-}
-
-/*
* onint --
* SIGINT handler.
*/
@@ -1548,7 +2163,6 @@ onint(notused)
void
summary()
{
- register int i;
(void)printf("\n--- %s ping6 statistics ---\n", hostname);
(void)printf("%ld packets transmitted, ", ntransmitted);
@@ -1566,28 +2180,35 @@ summary()
(void)putchar('\n');
if (nreceived && timing) {
/* Only display average to microseconds */
- i = 1000.0 * tsum / (nreceived + nrepeats);
- (void)printf("round-trip min/avg/max = %g/%g/%g ms\n",
- tmin, ((double)i) / 1000.0, tmax);
+ double num = nreceived + nrepeats;
+ double avg = tsum / num;
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ double dev = sqrt(tsumsq / num - avg * avg);
+ (void)printf(
+ "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax, dev);
+#else
+ (void)printf(
+ "round-trip min/avg/max = %.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax);
+#endif
(void)fflush(stdout);
}
+ (void)fflush(stdout);
}
-#ifdef notdef
-static char *ttab[] = {
- "Echo Reply", /* ip + seq + udata */
- "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */
- "Source Quench", /* IP */
- "Redirect", /* redirect type, gateway, + IP */
- "Echo",
- "Time Exceeded", /* transit, frag reassem + IP */
- "Parameter Problem", /* pointer + IP */
- "Timestamp", /* id + seq + three timestamps */
- "Timestamp Reply", /* " */
- "Info Request", /* id + sq */
- "Info Reply" /* " */
+/*subject type*/
+static char *niqcode[] = {
+ "IPv6 address",
+ "DNS label", /*or empty*/
+ "IPv4 address",
};
-#endif
+
+/*result code*/
+static char *nircode[] = {
+ "Success", "Refused", "Unknown",
+};
+
/*
* pr_icmph --
@@ -1599,16 +2220,21 @@ pr_icmph(icp, end)
u_char *end;
{
char ntop_buf[INET6_ADDRSTRLEN];
+ struct nd_redirect *red;
+ struct icmp6_nodeinfo *ni;
+ char dnsname[MAXDNAME + 1];
+ const u_char *cp;
+ size_t l;
- switch(icp->icmp6_type) {
+ switch (icp->icmp6_type) {
case ICMP6_DST_UNREACH:
- switch(icp->icmp6_code) {
+ switch (icp->icmp6_code) {
case ICMP6_DST_UNREACH_NOROUTE:
(void)printf("No Route to Destination\n");
break;
case ICMP6_DST_UNREACH_ADMIN:
(void)printf("Destination Administratively "
- "Unreachable\n");
+ "Unreachable\n");
break;
case ICMP6_DST_UNREACH_BEYONDSCOPE:
(void)printf("Destination Unreachable Beyond Scope\n");
@@ -1629,11 +2255,11 @@ pr_icmph(icp, end)
break;
case ICMP6_PACKET_TOO_BIG:
(void)printf("Packet too big mtu = %d\n",
- (int)ntohl(icp->icmp6_mtu));
+ (int)ntohl(icp->icmp6_mtu));
pr_retip((struct ip6_hdr *)(icp + 1), end);
break;
case ICMP6_TIME_EXCEEDED:
- switch(icp->icmp6_code) {
+ switch (icp->icmp6_code) {
case ICMP6_TIME_EXCEED_TRANSIT:
(void)printf("Time to live exceeded\n");
break;
@@ -1649,22 +2275,22 @@ pr_icmph(icp, end)
break;
case ICMP6_PARAM_PROB:
(void)printf("Parameter problem: ");
- switch(icp->icmp6_code) {
- case ICMP6_PARAMPROB_HEADER:
- (void)printf("Erroneous Header ");
- break;
- case ICMP6_PARAMPROB_NEXTHEADER:
- (void)printf("Unknown Nextheader ");
- break;
- case ICMP6_PARAMPROB_OPTION:
- (void)printf("Unrecognized Option ");
- break;
- default:
- (void)printf("Bad code(%d) ", icp->icmp6_code);
- break;
+ switch (icp->icmp6_code) {
+ case ICMP6_PARAMPROB_HEADER:
+ (void)printf("Erroneous Header ");
+ break;
+ case ICMP6_PARAMPROB_NEXTHEADER:
+ (void)printf("Unknown Nextheader ");
+ break;
+ case ICMP6_PARAMPROB_OPTION:
+ (void)printf("Unrecognized Option ");
+ break;
+ default:
+ (void)printf("Bad code(%d) ", icp->icmp6_code);
+ break;
}
(void)printf("pointer = 0x%02x\n",
- (int)ntohl(icp->icmp6_pptr));
+ (u_int32_t)ntohl(icp->icmp6_pptr));
pr_retip((struct ip6_hdr *)(icp + 1), end);
break;
case ICMP6_ECHO_REQUEST:
@@ -1697,25 +2323,119 @@ pr_icmph(icp, end)
(void)printf("Neighbor Advertisement");
break;
case ND_REDIRECT:
- {
- struct nd_redirect *red = (struct nd_redirect *)icp;
-
+ red = (struct nd_redirect *)icp;
(void)printf("Redirect\n");
- (void)printf("Destination: %s",
- inet_ntop(AF_INET6, &red->nd_rd_dst,
- ntop_buf, sizeof(ntop_buf)));
- (void)printf("New Target: %s",
- inet_ntop(AF_INET6, &red->nd_rd_target,
- ntop_buf, sizeof(ntop_buf)));
+ if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf,
+ sizeof(ntop_buf)))
+ strncpy(ntop_buf, "?", sizeof(ntop_buf));
+ (void)printf("Destination: %s", ntop_buf);
+ if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf,
+ sizeof(ntop_buf)))
+ strncpy(ntop_buf, "?", sizeof(ntop_buf));
+ (void)printf(" New Target: %s", ntop_buf);
break;
- }
case ICMP6_NI_QUERY:
(void)printf("Node Information Query");
/* XXX ID + Seq + Data */
+ ni = (struct icmp6_nodeinfo *)icp;
+ l = end - (u_char *)(ni + 1);
+ printf(", ");
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ (void)printf("NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ (void)printf("Supported qtypes");
+ break;
+ case NI_QTYPE_FQDN:
+ (void)printf("DNS name");
+ break;
+ case NI_QTYPE_NODEADDR:
+ (void)printf("nodeaddr");
+ break;
+ case NI_QTYPE_IPV4ADDR:
+ (void)printf("IPv4 nodeaddr");
+ break;
+ default:
+ (void)printf("unknown qtype");
+ break;
+ }
+ if (options & F_VERBOSE) {
+ switch (ni->ni_code) {
+ case ICMP6_NI_SUBJ_IPV6:
+ if (l == sizeof(struct in6_addr) &&
+ inet_ntop(AF_INET6, ni + 1, ntop_buf,
+ sizeof(ntop_buf)) != NULL) {
+ (void)printf(", subject=%s(%s)",
+ niqcode[ni->ni_code], ntop_buf);
+ } else {
+#if 1
+ /* backward compat to -W */
+ (void)printf(", oldfqdn");
+#else
+ (void)printf(", invalid");
+#endif
+ }
+ break;
+ case ICMP6_NI_SUBJ_FQDN:
+ if (end == (u_char *)(ni + 1)) {
+ (void)printf(", no subject");
+ break;
+ }
+ printf(", subject=%s", niqcode[ni->ni_code]);
+ cp = (const u_char *)(ni + 1);
+ if (dnsdecode(&cp, end, NULL, dnsname,
+ sizeof(dnsname)) != NULL)
+ printf("(%s)", dnsname);
+ else
+ printf("(invalid)");
+ break;
+ case ICMP6_NI_SUBJ_IPV4:
+ if (l == sizeof(struct in_addr) &&
+ inet_ntop(AF_INET, ni + 1, ntop_buf,
+ sizeof(ntop_buf)) != NULL) {
+ (void)printf(", subject=%s(%s)",
+ niqcode[ni->ni_code], ntop_buf);
+ } else
+ (void)printf(", invalid");
+ break;
+ default:
+ (void)printf(", invalid");
+ break;
+ }
+ }
break;
case ICMP6_NI_REPLY:
(void)printf("Node Information Reply");
/* XXX ID + Seq + Data */
+ ni = (struct icmp6_nodeinfo *)icp;
+ printf(", ");
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ (void)printf("NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ (void)printf("Supported qtypes");
+ break;
+ case NI_QTYPE_FQDN:
+ (void)printf("DNS name");
+ break;
+ case NI_QTYPE_NODEADDR:
+ (void)printf("nodeaddr");
+ break;
+ case NI_QTYPE_IPV4ADDR:
+ (void)printf("IPv4 nodeaddr");
+ break;
+ default:
+ (void)printf("unknown qtype");
+ break;
+ }
+ if (options & F_VERBOSE) {
+ if (ni->ni_code > sizeof(nircode) / sizeof(nircode[0]))
+ printf(", invalid");
+ else
+ printf(", %s", nircode[ni->ni_code]);
+ }
break;
default:
(void)printf("Bad ICMP type: %d", icp->icmp6_type);
@@ -1740,13 +2460,14 @@ pr_iph(ip6)
printf("Vr TC Flow Plen Nxt Hlim\n");
printf(" %1x %02x %05x %04x %02x %02x\n",
- (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (int)ntohl(flow),
- ntohs(ip6->ip6_plen),
- ip6->ip6_nxt, ip6->ip6_hlim);
- printf("%s->", inet_ntop(AF_INET6, &ip6->ip6_src,
- ntop_buf, sizeof(ntop_buf)));
- printf("%s\n", inet_ntop(AF_INET6, &ip6->ip6_dst,
- ntop_buf, sizeof(ntop_buf)));
+ (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow),
+ ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim);
+ if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf)))
+ strncpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf("%s->", ntop_buf);
+ if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf)))
+ strncpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf("%s\n", ntop_buf);
}
/*
@@ -1755,22 +2476,25 @@ pr_iph(ip6)
* a hostname.
*/
const char *
-pr_addr(addr)
- struct sockaddr_in6 *addr;
+pr_addr(addr, addrlen)
+ struct sockaddr *addr;
+ int addrlen;
{
- static char buf[MAXHOSTNAMELEN];
- int flag = 0;
+ static char buf[NI_MAXHOST];
+ int flag;
+#ifdef NI_WITHSCOPEID
+ flag = NI_WITHSCOPEID;
+#else
+ flag = 0;
+#endif
if ((options & F_HOSTNAME) == 0)
flag |= NI_NUMERICHOST;
-#ifdef KAME_SCOPEID
- flag |= NI_WITHSCOPEID;
-#endif
-
- getnameinfo((struct sockaddr *)addr, addr->sin6_len, buf, sizeof(buf),
- NULL, 0, flag);
- return (buf);
+ if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0)
+ return (buf);
+ else
+ return "?";
}
/*
@@ -1796,53 +2520,53 @@ pr_retip(ip6, end)
cp += hlen;
while (end - cp >= 8) {
switch (nh) {
- case IPPROTO_HOPOPTS:
- printf("HBH ");
- hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
- nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
- break;
- case IPPROTO_DSTOPTS:
- printf("DSTOPT ");
- hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
- nh = ((struct ip6_dest *)cp)->ip6d_nxt;
- break;
- case IPPROTO_FRAGMENT:
- printf("FRAG ");
- hlen = sizeof(struct ip6_frag);
- nh = ((struct ip6_frag *)cp)->ip6f_nxt;
- break;
- case IPPROTO_ROUTING:
- printf("RTHDR ");
- hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
- nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
- break;
+ case IPPROTO_HOPOPTS:
+ printf("HBH ");
+ hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
+ nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
+ break;
+ case IPPROTO_DSTOPTS:
+ printf("DSTOPT ");
+ hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
+ nh = ((struct ip6_dest *)cp)->ip6d_nxt;
+ break;
+ case IPPROTO_FRAGMENT:
+ printf("FRAG ");
+ hlen = sizeof(struct ip6_frag);
+ nh = ((struct ip6_frag *)cp)->ip6f_nxt;
+ break;
+ case IPPROTO_ROUTING:
+ printf("RTHDR ");
+ hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
+ nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
+ break;
#ifdef IPSEC
- case IPPROTO_AH:
- printf("AH ");
- hlen = (((struct ah *)cp)->ah_len+2) << 2;
- nh = ((struct ah *)cp)->ah_nxt;
- break;
+ case IPPROTO_AH:
+ printf("AH ");
+ hlen = (((struct ah *)cp)->ah_len+2) << 2;
+ nh = ((struct ah *)cp)->ah_nxt;
+ break;
#endif
- case IPPROTO_ICMPV6:
- printf("ICMP6: type = %d, code = %d\n",
- *cp, *(cp + 1));
- return;
- case IPPROTO_ESP:
- printf("ESP\n");
- return;
- case IPPROTO_TCP:
- printf("TCP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)),
- (*(cp + 2) * 256 + *(cp + 3)));
- return;
- case IPPROTO_UDP:
- printf("UDP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)),
- (*(cp + 2) * 256 + *(cp + 3)));
- return;
- default:
- printf("Unknown Header(%d)\n", nh);
- return;
+ case IPPROTO_ICMPV6:
+ printf("ICMP6: type = %d, code = %d\n",
+ *cp, *(cp + 1));
+ return;
+ case IPPROTO_ESP:
+ printf("ESP\n");
+ return;
+ case IPPROTO_TCP:
+ printf("TCP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)),
+ (*(cp + 2) * 256 + *(cp + 3)));
+ return;
+ case IPPROTO_UDP:
+ printf("UDP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)),
+ (*(cp + 2) * 256 + *(cp + 3)));
+ return;
+ default:
+ printf("Unknown Header(%d)\n", nh);
+ return;
}
if ((cp += hlen) >= end)
@@ -1876,7 +2600,7 @@ fill(bp, patp)
&pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
&pat[13], &pat[14], &pat[15]);
-/* xxx */
+/* xxx */
if (ii > 0)
for (kk = 0;
kk <= MAXDATALEN - (8 + sizeof(struct timeval) + ii);
@@ -1906,8 +2630,8 @@ setpolicy(so, policy)
buf = ipsec_set_policy(policy, strlen(policy));
if (buf == NULL)
errx(1, "%s", ipsec_strerror());
- if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
- buf, ipsec_get_policylen(buf)) < 0)
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf,
+ ipsec_get_policylen(buf)) < 0)
warnx("Unable to set IPSec policy");
free(buf);
@@ -1921,30 +2645,38 @@ nigroup(name)
char *name;
{
char *p;
+ unsigned char *q;
MD5_CTX ctxt;
u_int8_t digest[16];
- char l;
+ u_int8_t c;
+ size_t l;
char hbuf[NI_MAXHOST];
struct in6_addr in6;
- p = name;
- while (p && *p && *p != '.')
- p++;
- if (p - name > 63)
- return NULL; /*label too long*/
+ p = strchr(name, '.');
+ if (!p)
+ p = name + strlen(name);
l = p - name;
+ if (l > 63 || l > sizeof(hbuf) - 1)
+ return NULL; /*label too long*/
+ strncpy(hbuf, name, l);
+ hbuf[(int)l] = '\0';
+
+ for (q = name; *q; q++) {
+ if (isupper(*q))
+ *q = tolower(*q);
+ }
/* generate 8 bytes of pseudo-random value. */
bzero(&ctxt, sizeof(ctxt));
MD5Init(&ctxt);
- MD5Update(&ctxt, &l, sizeof(l));
- MD5Update(&ctxt, name, p - name);
+ c = l & 0xff;
+ MD5Update(&ctxt, &c, sizeof(c));
+ MD5Update(&ctxt, name, l);
MD5Final(digest, &ctxt);
- bzero(&in6, sizeof(in6));
- in6.s6_addr[0] = 0xff;
- in6.s6_addr[1] = 0x02;
- in6.s6_addr[11] = 0x02;
+ if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1)
+ return NULL; /*XXX*/
bcopy(digest, &in6.s6_addr[12], 4);
if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL)
@@ -1957,19 +2689,20 @@ void
usage()
{
(void)fprintf(stderr,
-"usage: ping6 [-dfHnNqvwW"
+ "usage: ping6 [-dfHmnNqvwW"
#ifdef IPV6_REACHCONF
- "R"
+ "R"
#endif
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
- "] [-P policy"
+ "] [-P policy"
#else
- "AE"
+ "AE"
+#endif
#endif
-#endif
- "] [-a [aAclsg]] [-b sockbufsiz] [-c count] \n\
- [-I interface] [-i wait] [-l preload] [-p pattern] [-S sourceaddr]\n\
- [-s packetsize] [-h hoplimit] [hops...] host\n");
+ "] [-a [aAclsg]] [-b sockbufsiz] [-c count] \n"
+ "\t[-I interface] [-i wait] [-l preload] [-p pattern] "
+ "[-S sourceaddr]\n"
+ "\t[-s packetsize] [-h hoplimit] [hops...] host\n");
exit(1);
}
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 2b7d246..46d61c2 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -72,11 +72,7 @@ static const char rcsid[] =
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
-
-/* wrapper for KAME-special getnameinfo() */
-#ifndef NI_WITHSCOPEID
-#define NI_WITHSCOPEID 0
-#endif
+#include <ifaddrs.h>
struct keytab {
char *kt_cp;
@@ -98,6 +94,7 @@ union sockunion {
struct sockaddr_ns sns;
#endif
struct sockaddr_dl sdl;
+ struct sockaddr_storage ss; /* added to avoid memory overrun */
} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
typedef union sockunion *sup;
@@ -110,10 +107,7 @@ struct rt_metrics rt_metrics;
u_long rtm_inits;
int atalk_aton __P((const char *, struct at_addr *));
char *atalk_ntoa __P((struct at_addr));
-#ifdef INET6
-char *inet6_ntoa __P((struct sockaddr *sa));
-#endif
-char *routename(), *netname();
+const 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();
@@ -122,10 +116,6 @@ extern char *iso_ntoa();
void usage __P((const char *)) __dead2;
-#ifdef INET6
-char name_buf[MAXHOSTNAMELEN * 2 + 1]; /*for getnameinfo()*/
-#endif
-
void
usage(cp)
const char *cp;
@@ -303,14 +293,14 @@ bad: usage(*argv);
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
(void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
routename(sa) : netname(sa));
- sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
+ sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
(void) printf("%-20.20s ", routename(sa));
(void) printf("done\n");
}
}
}
-char *
+const char *
routename(sa)
struct sockaddr *sa;
{
@@ -364,8 +354,36 @@ routename(sa)
#ifdef INET6
case AF_INET6:
- (void) snprintf(line, sizeof(line), "%s", inet6_ntoa(sa));
- break;
+ {
+ struct sockaddr_in6 sin6; /* use static var for safety */
+ int niflags = 0;
+#ifdef NI_WITHSCOPEID
+ niflags = NI_WITHSCOPEID;
+#endif
+
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6, sa, sa->sa_len);
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+#ifdef __KAME__
+ if (sa->sa_len == sizeof(struct sockaddr_in6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ sin6.sin6_scope_id == 0) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+ if (nflag)
+ niflags |= NI_NUMERICHOST;
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ line, sizeof(line), NULL, 0, niflags) != 0)
+ strncpy(line, "invalid", sizeof(line));
+
+ return(line);
+ }
#endif
case AF_APPLETALK:
@@ -399,7 +417,7 @@ routename(sa)
* Return the name of the network whose address is given.
* The address is assumed to be that of a net or subnet, not a host.
*/
-char *
+const char *
netname(sa)
struct sockaddr *sa;
{
@@ -469,8 +487,36 @@ netname(sa)
#ifdef INET6
case AF_INET6:
- (void) snprintf(line, sizeof(line), "%s", inet6_ntoa(sa));
- break;
+ {
+ struct sockaddr_in6 sin6; /* use static var for safety */
+ int niflags = 0;
+#ifdef NI_WITHSCOPEID
+ niflags = NI_WITHSCOPEID;
+#endif
+
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6, sa, sa->sa_len);
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+#ifdef __KAME__
+ if (sa->sa_len == sizeof(struct sockaddr_in6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ sin6.sin6_scope_id == 0) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+ if (nflag)
+ niflags |= NI_NUMERICHOST;
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ line, sizeof(line), NULL, 0, niflags) != 0)
+ strncpy(line, "invalid", sizeof(line));
+
+ return(line);
+ }
#endif
case AF_APPLETALK:
@@ -827,47 +873,35 @@ getaddr(which, s, hpp)
case RTA_GATEWAY:
su = &so_gate;
if (iflag) {
- #define MAX_IFACES 400
- int sock;
- struct ifreq iflist[MAX_IFACES];
- struct ifconf ifconf;
- struct ifreq *ifr, *ifr_end;
- struct sockaddr_dl *dl, *sdl = NULL;
-
- /* Get socket */
- if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
- err(1, "socket");
-
- /* Get interface list */
- ifconf.ifc_req = iflist;
- ifconf.ifc_len = sizeof(iflist);
- if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0)
- err(1, "ioctl(SIOCGIFCONF)");
- close(sock);
-
- /* Look for this interface in the list */
- for (ifr = ifconf.ifc_req,
- ifr_end = (struct ifreq *)
- (ifconf.ifc_buf + ifconf.ifc_len);
- ifr < ifr_end;
- ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
- + MAX(ifr->ifr_addr.sa_len,
- sizeof(ifr->ifr_addr)))) {
- dl = (struct sockaddr_dl *)&ifr->ifr_addr;
- if (ifr->ifr_addr.sa_family == AF_LINK
- && (ifr->ifr_flags & IFF_POINTOPOINT)
- && !strncmp(s, dl->sdl_data, dl->sdl_nlen)
- && s[dl->sdl_nlen] == 0) {
- sdl = dl;
- break;
- }
- }
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_dl *sdl = NULL;
+
+ if (getifaddrs(&ifap))
+ err(1, "getifaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+
+ if (strcmp(s, ifa->ifa_name) ||
+ (ifa->ifa_flags & IFF_POINTOPOINT) == 0)
+ continue;
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ }
/* If we found it, then use it */
if (sdl) {
- su->sdl = *sdl;
- return(1);
+ /*
+ * Copy is safe since we have a
+ * sockaddr_storage member in sockunion{}.
+ * Note that we need to copy before calling
+ * freeifaddrs().
+ */
+ memcpy(&su->sdl, sdl, sdl->sdl_len);
}
+ freeifaddrs(ifap);
+ if (sdl)
+ return(1);
}
break;
case RTA_NETMASK:
@@ -908,31 +942,33 @@ getaddr(which, s, hpp)
switch (afamily) {
#ifdef INET6
case AF_INET6:
- {
+ {
struct addrinfo hints, *res;
- int error;
-
- bzero(&hints, sizeof(struct addrinfo));
- hints.ai_family = AF_INET6;
-
- error = getaddrinfo(s, NULL, &hints, &res);
- if (error != 0) {
- (void) fprintf(stderr, "%s: bad value\n",
- gai_strerror(error));
- if (error == EAI_SYSTEM)
- (void) fprintf(stderr, "%s\n",
- strerror(errno));
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = afamily; /*AF_INET6*/
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ if (getaddrinfo(s, "0", &hints, &res) != 0 ||
+ res->ai_family != AF_INET6 ||
+ res->ai_addrlen != sizeof(su->sin6)) {
+ (void) fprintf(stderr, "%s: bad value\n", s);
exit(1);
}
- bcopy(res->ai_addr, &su->sa, res->ai_addrlen);
- /* XXX: embedded link local addr check */
- if (IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr))
- *(u_short *)&su->sin6.sin6_addr.s6_addr[2] =
- ntohs(su->sin6.sin6_scope_id);
- su->sin6.sin6_scope_id = 0;
- return 0;
- }
+ memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
+#ifdef __KAME__
+ if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) ||
+ IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr)) &&
+ su->sin6.sin6_scope_id) {
+ *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
+ htons(su->sin6.sin6_scope_id);
+ su->sin6.sin6_scope_id = 0;
+ }
#endif
+ freeaddrinfo(res);
+ return (0);
+ }
+#endif /* INET6 */
#ifdef NS
case AF_NS:
@@ -1624,45 +1660,3 @@ atalk_ntoa(struct at_addr at)
(void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
return(buf);
}
-
-#ifdef INET6
-char *
-inet6_ntoa(struct sockaddr *sa)
-{
- char *cp;
- struct sockaddr_in6 *sin6;
- int error = -1, gap;
-
- cp = NULL;
- sin6 = (struct sockaddr_in6 *)sa;
- gap = sizeof(struct sockaddr_in6) - sin6->sin6_len;
- if (gap > 0)
- bzero((char *)(sin6) + sin6->sin6_len, gap);
-
- /* XXX: embedded link local addr check */
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
- *(u_short *)&sin6->sin6_addr.s6_addr[2] != 0) {
- u_short index;
-
- index = *(u_short *)&sin6->sin6_addr.s6_addr[2];
- *(u_short *)&sin6->sin6_addr.s6_addr[2] = 0;
- if (sin6->sin6_scope_id == 0)
- sin6->sin6_scope_id = ntohs(index);
- }
-
- if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || sa->sa_len < 4)
- cp = "default";
- if (cp == 0 && !nflag)
- error = getnameinfo(sa, sa->sa_len, name_buf, sizeof(name_buf),
- NULL, 0, NI_NAMEREQD);
- if (error != 0)
- error = getnameinfo(sa, sa->sa_len, name_buf,
- sizeof(name_buf), NULL, 0,
- NI_NUMERICHOST|NI_WITHSCOPEID);
- if (error != 0)
- inet_ntop(AF_INET6, &sin6->sin6_addr, name_buf,
- sizeof(name_buf));
-
- return (cp != NULL) ? cp : name_buf;
-}
-#endif
diff --git a/sbin/rtsol/Makefile b/sbin/rtsol/Makefile
index 4926191..f533ed8 100644
--- a/sbin/rtsol/Makefile
+++ b/sbin/rtsol/Makefile
@@ -16,11 +16,9 @@
SRCDIR= ${.CURDIR}/../../usr.sbin/rtsold
PROG= rtsol
-SRCS= rtsold.c rtsol.c if.c probe.c dump.c
+SRCS= rtsold.c rtsol.c if.c probe.c dump.c rtsock.c
CFLAGS+=-DINET6 -DHAVE_GETIFADDRS
-LDADD= -lkvm
-DPADD= ${LIBKVM}
NOMAN= yes
diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y
index 0eea4c1..1d43dc4 100644
--- a/sbin/setkey/parse.y
+++ b/sbin/setkey/parse.y
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: parse.y,v 1.29 2000/06/10 14:17:44 sakane Exp $ */
+/* $KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 sakane Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -57,6 +57,7 @@
u_int p_type;
u_int32_t p_spi;
+int p_no_spi;
struct sockaddr *p_src, *p_dst;
u_int p_prefs, p_prefd, p_upper;
u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
@@ -79,7 +80,6 @@ extern int m_len;
extern char cmdarg[8192];
extern int f_debug;
-int setkeymsg __P((void));
static struct addrinfo *parse_addr __P((char *, char *, int));
static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
void parse_init __P((void));
@@ -107,7 +107,7 @@ extern void yyerror __P((const char *));
%token F_EXT EXTENSION NOCYCLICSEQ
%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
%token F_LIFETIME_HARD F_LIFETIME_SOFT
-%token DECSTRING QUOTEDSTRING HEXSTRING ANY
+%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
/* SPD management */
%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
%token F_POLICY PL_REQUESTS
@@ -118,7 +118,7 @@ extern void yyerror __P((const char *));
%type <num> DECSTRING
%type <val> ADDRESS PL_REQUESTS
%type <val> key_string policy_requests
-%type <val> QUOTEDSTRING HEXSTRING
+%type <val> QUOTEDSTRING HEXSTRING STRING
%%
commands
@@ -140,6 +140,7 @@ command
: add_command
| get_command
| delete_command
+ | deleteall_command
| flush_command
| dump_command
| spdadd_command
@@ -166,6 +167,16 @@ delete_command
EOT
;
+ /* deleteall command */
+deleteall_command
+ : DELETEALL { p_type = SADB_DELETE; }
+ ipaddress { p_src = pp_addr; }
+ ipaddress { p_dst = pp_addr; }
+ protocol_spec
+ { p_no_spi = 1; }
+ EOT
+ ;
+
/* get command */
get_command
: GET { p_type = SADB_GET; }
@@ -327,7 +338,7 @@ auth_alg
auth_key
: /*NOTHING*/
{
- if (p_alg_auth != SADB_AALG_NULL) {
+ if (p_alg_auth != SADB_X_AALG_NULL) {
yyerror("no key found.");
return -1;
}
@@ -541,10 +552,27 @@ port
upper_spec
: DECSTRING { p_upper = $1; }
| UP_PROTO { p_upper = $1; }
- | PR_ESP { p_upper = IPPROTO_ESP; };
- | PR_AH { p_upper = IPPROTO_AH; };
- | PR_IPCOMP { p_upper = IPPROTO_IPCOMP; };
| ANY { p_upper = IPSEC_ULPROTO_ANY; }
+ | STRING
+ {
+ struct protoent *ent;
+
+ ent = getprotobyname($1.buf);
+ if (ent)
+ p_upper = ent->p_proto;
+ else {
+ if (strcmp("icmp6", $1.buf) == 0) {
+ p_upper = IPPROTO_ICMPV6;
+ } else if(strcmp("ip4", $1.buf) == 0) {
+ p_upper = IPPROTO_IPV4;
+ } else {
+ yyerror("invalid upper layer protocol");
+ free($1.buf);
+ return -1;
+ }
+ }
+ free($1.buf);
+ }
;
policy_spec
@@ -665,27 +693,29 @@ setkeymsg()
struct sadb_address m_addr;
u_int len;
- len = sizeof(struct sadb_sa);
- m_sa.sadb_sa_len = PFKEY_UNIT64(len);
- m_sa.sadb_sa_exttype = SADB_EXT_SA;
- m_sa.sadb_sa_spi = htonl(p_spi);
- m_sa.sadb_sa_replay = p_replay;
- m_sa.sadb_sa_state = 0;
- m_sa.sadb_sa_auth = p_alg_auth;
- m_sa.sadb_sa_encrypt = p_alg_enc;
- m_sa.sadb_sa_flags = p_ext;
-
- memcpy(m_buf + m_len, &m_sa, len);
- m_len += len;
+ if (p_no_spi == 0) {
+ len = sizeof(struct sadb_sa);
+ m_sa.sadb_sa_len = PFKEY_UNIT64(len);
+ m_sa.sadb_sa_exttype = SADB_EXT_SA;
+ m_sa.sadb_sa_spi = htonl(p_spi);
+ m_sa.sadb_sa_replay = p_replay;
+ m_sa.sadb_sa_state = 0;
+ m_sa.sadb_sa_auth = p_alg_auth;
+ m_sa.sadb_sa_encrypt = p_alg_enc;
+ m_sa.sadb_sa_flags = p_ext;
+
+ memcpy(m_buf + m_len, &m_sa, len);
+ m_len += len;
- len = sizeof(struct sadb_x_sa2);
- m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
- m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
- m_sa2.sadb_x_sa2_mode = p_mode;
- m_sa2.sadb_x_sa2_reqid = p_reqid;
+ len = sizeof(struct sadb_x_sa2);
+ m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
+ m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ m_sa2.sadb_x_sa2_mode = p_mode;
+ m_sa2.sadb_x_sa2_reqid = p_reqid;
- memcpy(m_buf + m_len, &m_sa2, len);
- m_len += len;
+ memcpy(m_buf + m_len, &m_sa2, len);
+ m_len += len;
+ }
/* set src */
m_addr.sadb_address_len =
@@ -864,6 +894,7 @@ parse_init()
{
p_type = 0;
p_spi = 0;
+ p_no_spi = 0;
p_src = 0, p_dst = 0;
pp_prefix = p_prefs = p_prefd = ~0;
diff --git a/sbin/setkey/scriptdump.pl b/sbin/setkey/scriptdump.pl
index aa36544..33907dc 100644
--- a/sbin/setkey/scriptdump.pl
+++ b/sbin/setkey/scriptdump.pl
@@ -33,11 +33,11 @@ foreach $_ (<IN>) {
$akey =~ s/\s//g;
$akey =~ s/^/0x/g;
} elsif (/^\treplay=(\d+) flags=(0x\d+) state=/) {
- print "$mode $src $dst $proto $spi -m $ipsecmode";
+ print "$mode $src $dst $proto $spi";
$replay = $1;
print " -u $reqid" if $reqid;
if ($mode eq 'add') {
- print " -r $replay" if $replay;
+ print " -m $ipsecmode -r $replay" if $replay;
if ($proto eq 'esp') {
print " -E $ealgo $ekey" if $ealgo;
print " -A $aalgo $akey" if $aalgo;
diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
index 7921800..368fc5d 100644
--- a/sbin/setkey/setkey.8
+++ b/sbin/setkey/setkey.8
@@ -1,5 +1,5 @@
-.\" $FreeBSD$
-.\" $KAME: setkey.8,v 1.28 2000/06/16 12:03:46 sakane Exp $
+.\" $KAME: setkey.8,v 1.49 2001/05/18 05:49:51 sakane Exp $
+.\" $FreeBSD$
.\"
.\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
.\" All rights reserved.
@@ -28,9 +28,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 17, 1998
+.Dd November 20, 2000
.Dt SETKEY 8
-.Os KAME
+.Os
.\"
.Sh NAME
.Nm setkey
@@ -55,7 +55,7 @@
.\"
.Sh DESCRIPTION
.Nm
-addes, updates, dumpes, or flushes
+adds, updates, dumps, or flushes
Security Association Database (SAD) entries
as well as Security Policy Database (SPD) entries in the kernel.
.Pp
@@ -94,11 +94,14 @@ it has been expired but remains
because it is referenced by SPD entries.
.It Fl d
Enable to print debugging messages for command parser,
-without talking to kernel. It is not used usually.
+without talking to kernel.
+It is not used usually.
.It Fl x
Loop forever and dump all the messages transmitted to
.Dv PF_KEY
socket.
+.Fl xx
+makes each timestamps unformatted.
.It Fl h
Add hexadecimal dump on
.Fl x
@@ -108,14 +111,13 @@ Loop forever with short output on
.Fl D .
.It Fl v
Be verbose.
+The program will dump messages exchanged on
.Dv PF_KEY
-socket
-.Po
-including messages sent from other processes
-.Pc .
+socket, including messages sent from other processes to the kernel.
.El
.Pp
-Operations have the following grammar. Note that lines starting with
+Operations have the following grammar.
+Note that lines starting with
hashmarks ('#') are treated as comment lines.
.Bl -tag -width Ds
.It Xo
@@ -142,6 +144,13 @@ Show an SAD entry.
Remove an SAD entry.
.\"
.It Xo
+.Li deleteall
+.Ar src Ar dst Ar protocol
+.Li ;
+.Xc
+Remove all SAD entries that match the specification.
+.\"
+.It Xo
.Li flush
.Op Ar protocol
.Li ;
@@ -227,7 +236,7 @@ attached
.\"
.Pp
.It Ar extensions
-take some of the following:
+takes some of the following:
.Bl -tag -width Fl -compact
.\"
.It Fl m Ar mode
@@ -243,39 +252,49 @@ The default value is
.It Fl r Ar size
Specify window size of bytes for replay prevention.
.Ar size
-must be decimal number in 32-bit word. If
+must be decimal number in 32-bit word.
+If
.Ar size
is zero or not specified, replay check don't take place.
.\"
.It Fl u Ar id
-Specify the identifier of policy. See also
-.Xr ipsec_set_policy 3 .
+Specify the identifier of the policy entry in SPD.
+See
+.Ar policy .
.\"
.It Fl f Ar pad_option
+defines the content of the ESP padding.
.Ar pad_option
is one of following:
-.Li zero-pad , random-pad
-or
-.Li seq-pad
+.Bl -tag -width random-pad -compact
+.It Li zero-pad
+All of the padding are zero.
+.It Li random-pad
+A series of randomized values are set.
+.It Li seq-pad
+A series of sequential increasing numbers started from 1 are set.
+.El
.\"
.It Fl f Li nocyclic-seq
Don't allow cyclic sequence number.
.\"
.It Fl lh Ar time
.It Fl ls Ar time
-Specify hard/soft lifetime.
+Specify hard/soft life time duration of the SA.
.El
.\"
.Pp
.It Ar algorithm
.Bl -tag -width Fl -compact
.It Fl E Ar ealgo Ar key
-Specify encryption algorithm.
+Specify a encryption algorithm.
.It Fl A Ar aalgo Ar key
-Specify authentication algorithm.
+Specify a authentication algorithm.
If
.Fl A
-is used for esp, it will be treated as ESP payload authentication algorithm.
+is used with
+.Ar protocol Li esp ,
+it will be treated as ESP payload authentication algorithm.
.It Fl C Ar calgo Op Fl R
Specify compression algorithm.
If
@@ -302,23 +321,23 @@ field needs to be smaller than
in this case.
.El
.Pp
-.Li esp
-SAs accept
+.Ar protocol Li esp
+accepts
.Fl E
and
.Fl A .
-.Li esp-old
-SAs accept
+.Ar protocol Li esp-old
+accepts
.Fl E
only.
-.Li ah
+.Ar protocol Li ah
and
.Li ah-old
-SAs accept
+accept
.Fl A
only.
-.Li ipcomp
-SAs accept
+.Ar protocol Li ipcomp
+accepts
.Fl C
only.
.Pp
@@ -365,45 +384,57 @@ They must be in numeric form.
.Pp
.It Ar upperspec
Upper-layer protocol to be used.
-Currently
-.Li icmp ,
+You can use one of words in
+.Pa /etc/protocols
+as
+.Ar upperspec .
+Or
.Li icmp6 ,
.Li ip4 ,
-.Li tcp ,
-.Li udp
and
.Li any
can be specified.
.Li any
stands for
.Dq any protocol .
+Also you can use the protocol number.
.Pp
NOTE:
.Ar upperspec
does not work against forwarding case at this moment,
as it requires extra reassembly at forwarding node
.Pq not implemented at this moment .
+We have many protocols in
+.Pa /etc/protocols ,
+but protocols except of TCP, UDP and ICMP may not be suitable to use with IPSec.
+You have to consider and be careful to use them.
+.Li icmp
+.Li tcp
+.Li udp
+all protocols
.\"
.Pp
.It Ar policy
.Ar policy
is the one of following:
-.Pp
-.Bl -item -compact
-.It
+.Bd -literal -offset
+.Xo
.Fl P
.Ar direction
.Li discard
-.It
+.Xc
+.Xo
.Fl P
.Ar direction
.Li none
-.It
+.Xc
+.Xo
.Fl P
.Ar direction
.Li ipsec
.Ar protocol/mode/src-dst/level
-.El
+.Xc
+.Ed
.Pp
You must specify the direction of its policy as
.Ar direction .
@@ -430,18 +461,33 @@ is either
.Li transport
or
.Li tunnel .
-You must specify the end-points addresses of the SA as
+If
+.Ar mode
+is
+.Li tunnel ,
+you must specify the end-points addresses of the SA as
.Ar src
and
.Ar dst
with
.Sq -
between these addresses which is used to specify the SA to use.
+If
+.Ar mode
+is
+.Li transport ,
+both
+.Ar src
+and
+.Ar dst
+can be omited.
.Ar level
is to be one of the following:
-.Li default , use
+.Li default , use , require
or
-.Li require .
+.Li unique .
+If the SA is not available in every level, the kernel will request
+getting SA to the key exchange daemon.
.Li default
means the kernel consults to the system wide default against protocol you
specified, e.g.
@@ -451,7 +497,23 @@ sysctl variable, when the kernel processes the packet.
means that the kernel use a SA if it's available,
otherwise the kernel keeps normal operation.
.Li require
-means SA is required whenever the kernel deals with the packet.
+means SA is required whenever the kernel sends a packet matched
+with the policy.
+.Li unique
+is the same to require.
+In addition, it allows the policy to bind with the unique out-bound SA.
+If you use the SA by manual keying,
+you can put the decimal number as the policy identifier after
+.Li unique
+separated by colon
+.Sq \:
+like the following;
+.Li unique:number .
+.Li number
+must be between 1 and 32767.
+It corresponds to
+.Ar extensions Fl u .
+.Pp
Note that
.Dq Li discard
and
@@ -491,6 +553,12 @@ keyed-md5 128 ah: 96bit ICV (no document)
keyed-sha1 160 ah: 96bit ICV (no document)
160 ah-old: 128bit ICV (no document)
null 0 to 2048 for debugging
+hmac-sha2-256 256 ah: 96bit ICV (no document)
+ 256 ah-old: 128bit ICV (no document)
+hmac-sha2-384 384 ah: 96bit ICV (no document)
+ 384 ah-old: 128bit ICV (no document)
+hmac-sha2-512 512 ah: 96bit ICV (no document)
+ 512 ah-old: 128bit ICV (no document)
.Ed
.Pp
Followings are the list of encryption algorithms that can be used as
@@ -508,9 +576,9 @@ des-cbc 64 esp-old: rfc1829, esp: rfc2405
simple 0 to 2048 rfc2410
blowfish-cbc 40 to 448 rfc2451
cast128-cbc 40 to 128 rfc2451
-rc5-cbc 40 to 2040 rfc2451
des-deriv 64 ipsec-ciph-des-derived-01 (expired)
3des-deriv 192 no document
+rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00
.Ed
.Pp
Followings are the list of compression algorithms that can be used as
@@ -555,7 +623,8 @@ The command exits with 0 on success, and non-zero on errors.
.\"
.Sh SEE ALSO
.Xr ipsec_set_policy 3 ,
-.Xr sysctl 8
+.Xr sysctl 8 ,
+.Xr racoon 8
.\"
.Sh HISTORY
The
diff --git a/sbin/setkey/setkey.c b/sbin/setkey/setkey.c
index b1e1c1e..e729e7d 100644
--- a/sbin/setkey/setkey.c
+++ b/sbin/setkey/setkey.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: setkey.c,v 1.14 2000/06/10 06:47:09 sakane Exp $ */
+/* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -63,6 +63,8 @@ int postproc __P((struct sadb_msg *, int));
const char *numstr __P((int));
void shortdump_hdr __P((void));
void shortdump __P((struct sadb_msg *));
+static void printdate __P((void));
+static int32_t gmt2local __P((time_t));
#define MODE_SCRIPT 1
#define MODE_CMDDUMP 2
@@ -79,11 +81,14 @@ int f_mode = 0;
int f_cmddump = 0;
int f_policy = 0;
int f_hexdump = 0;
+int f_tflag = 0;
char *pname;
u_char m_buf[BUFSIZ];
u_int m_len;
+static time_t thiszone;
+
extern int lineno;
extern int parse __P((FILE **));
@@ -112,7 +117,9 @@ main(ac, av)
if (ac == 1) Usage();
- while ((c = getopt(ac, av, "acdf:hlvxDFP")) != EOF) {
+ thiszone = gmt2local(0);
+
+ while ((c = getopt(ac, av, "acdf:hlvxDFP")) != -1) {
switch (c) {
case 'c':
f_mode = MODE_SCRIPT;
@@ -142,6 +149,7 @@ main(ac, av)
break;
case 'x':
f_mode = MODE_PROMISC;
+ f_tflag++;
break;
case 'P':
f_policy = 1;
@@ -199,7 +207,7 @@ get_supported()
if (f_debug)
return 0;
- if (pfkey_send_register(so, PF_UNSPEC) < 0)
+ if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
return -1;
if (pfkey_recv_register(so) < 0)
@@ -275,6 +283,7 @@ promisc()
err(1, "recv");
/*NOTREACHED*/
}
+ printdate();
if (f_hexdump) {
int i;
for (i = 0; i < len; i++) {
@@ -541,7 +550,7 @@ shortdump(msg)
snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
printf("%s", buf);
} else
- printf(" ???/???");
+ printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
printf(" ");
@@ -576,3 +585,64 @@ shortdump(msg)
printf("\n");
}
+
+/* From: tcpdump(1):gmt2local.c and util.c */
+/*
+ * Print the timestamp
+ */
+static void
+printdate()
+{
+ struct timeval tp;
+ int s;
+
+ if (gettimeofday(&tp, NULL) == -1) {
+ perror("gettimeofday");
+ return;
+ }
+
+ if (f_tflag == 1) {
+ /* Default */
+ s = (tp.tv_sec + thiszone ) % 86400;
+ (void)printf("%02d:%02d:%02d.%06u ",
+ s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
+ } else if (f_tflag > 1) {
+ /* Unix timeval style */
+ (void)printf("%u.%06u ",
+ (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
+ }
+
+ printf("\n");
+}
+
+/*
+ * Returns the difference between gmt and local time in seconds.
+ * Use gmtime() and localtime() to keep things simple.
+ */
+int32_t
+gmt2local(time_t t)
+{
+ register int dt, dir;
+ register struct tm *gmt, *loc;
+ struct tm sgmt;
+
+ if (t == 0)
+ t = time(NULL);
+ gmt = &sgmt;
+ *gmt = *gmtime(&t);
+ loc = localtime(&t);
+ dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
+ (loc->tm_min - gmt->tm_min) * 60;
+
+ /*
+ * If the year or julian day is different, we span 00:00 GMT
+ * and must add or subtract a day. Check the year first to
+ * avoid problems when the julian day wraps.
+ */
+ dir = loc->tm_year - gmt->tm_year;
+ if (dir == 0)
+ dir = loc->tm_yday - gmt->tm_yday;
+ dt += dir * 24 * 60 * 60;
+
+ return (dt);
+}
diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
index c2eaad5..208196e 100644
--- a/sbin/setkey/token.l
+++ b/sbin/setkey/token.l
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: token.l,v 1.13 2000/06/07 00:29:14 itojun Exp $ */
+/* $KAME: token.l,v 1.21 2001/05/18 05:35:01 sakane Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
@@ -47,7 +47,11 @@
#include <unistd.h>
#include <errno.h>
#include "vchar.h"
+#ifdef __NetBSD__
+#include "parse.h"
+#else
#include "y.tab.h"
+#endif
#define DECHO \
if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); }
@@ -121,6 +125,7 @@ hostname {name}(({dot}{name})+{dot}?)?
add { PREPROC; return(ADD); }
delete { PREPROC; return(DELETE); }
+deleteall { PREPROC; return(DELETEALL); }
get { PREPROC; return(GET); }
flush { PREPROC; return(FLUSH); }
dump { PREPROC; return(DUMP); }
@@ -160,20 +165,23 @@ ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); }
{hyphen}A { PREPROC; return(F_AUTH); }
hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); }
hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); }
-keyed-md5 { PREPROC; yylval.num = SADB_AALG_MD5; return(ALG_AUTH); }
-keyed-sha1 { PREPROC; yylval.num = SADB_AALG_SHA; return(ALG_AUTH); }
-null { PREPROC; yylval.num = SADB_AALG_NULL; return(ALG_AUTH); }
+keyed-md5 { PREPROC; yylval.num = SADB_X_AALG_MD5; return(ALG_AUTH); }
+keyed-sha1 { PREPROC; yylval.num = SADB_X_AALG_SHA; return(ALG_AUTH); }
+hmac-sha2-256 { PREPROC; yylval.num = SADB_X_AALG_SHA2_256; return(ALG_AUTH); }
+hmac-sha2-384 { PREPROC; yylval.num = SADB_X_AALG_SHA2_384; return(ALG_AUTH); }
+hmac-sha2-512 { PREPROC; yylval.num = SADB_X_AALG_SHA2_512; return(ALG_AUTH); }
+null { PREPROC; yylval.num = SADB_X_AALG_NULL; return(ALG_AUTH); }
/* encryption alogorithm */
{hyphen}E { PREPROC; return(F_ENC); }
des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); }
3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); }
simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); }
-blowfish-cbc { PREPROC; yylval.num = SADB_EALG_BLOWFISHCBC; return(ALG_ENC); }
-cast128-cbc { PREPROC; yylval.num = SADB_EALG_CAST128CBC; return(ALG_ENC); }
-rc5-cbc { PREPROC; yylval.num = SADB_EALG_RC5CBC; return(ALG_ENC); }
+blowfish-cbc { PREPROC; yylval.num = SADB_X_EALG_BLOWFISHCBC; return(ALG_ENC); }
+cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); }
des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); }
des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); }
+rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); }
/* compression algorithms */
{hyphen}C { PREPROC; return(F_COMP); }
@@ -196,14 +204,6 @@ nocyclic-seq { PREPROC; return(NOCYCLICSEQ); }
{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); }
{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); }
-
- /* upper layer protocols */
-icmp { PREPROC; yylval.num = IPPROTO_ICMP; return(UP_PROTO); }
-icmp6 { PREPROC; yylval.num = IPPROTO_ICMPV6; return(UP_PROTO); }
-ip4 { PREPROC; yylval.num = IPPROTO_IPV4; return(UP_PROTO); }
-tcp { PREPROC; yylval.num = IPPROTO_TCP; return(UP_PROTO); }
-udp { PREPROC; yylval.num = IPPROTO_UDP; return(UP_PROTO); }
-
/* ... */
any { PREPROC; return(ANY); }
{ws} { PREPROC; }
@@ -277,6 +277,12 @@ any { PREPROC; return(ANY); }
return(QUOTEDSTRING);
}
+[a-z0-9.\-]* {
+ yylval.val.len = yyleng;
+ yylval.val.buf = strdup(yytext);
+ return(STRING);
+ }
+
. {
yyfatal("Syntax error");
/*NOTREACHED*/
OpenPOWER on IntegriCloud