sync with latest libipsec and kernel.
This commit is contained in:
parent
6b2922d06b
commit
62e82d7e0c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ping.c,v 1.54 2000/01/20 01:04:41 mycroft Exp $ */
|
||||
/* $NetBSD: ping.c,v 1.55 2000/01/31 14:24:23 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ping.c,v 1.54 2000/01/20 01:04:41 mycroft Exp $");
|
||||
__RCSID("$NetBSD: ping.c,v 1.55 2000/01/31 14:24:23 itojun Exp $");
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -255,7 +255,8 @@ main(int argc, char *argv[])
|
|||
#endif
|
||||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
char *policy = NULL;
|
||||
char *policy_in = NULL;
|
||||
char *policy_out = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -377,7 +378,12 @@ main(int argc, char *argv[])
|
|||
#ifdef IPSEC_POLICY_IPSEC
|
||||
case 'E':
|
||||
pingflags |= F_POLICY;
|
||||
policy = strdup(optarg);
|
||||
if (!strncmp("in", optarg, 2))
|
||||
policy_in = strdup(optarg);
|
||||
else if (!strncmp("out", optarg, 3))
|
||||
policy_out = strdup(optarg);
|
||||
else
|
||||
errx(1, "invalid security policy");
|
||||
break;
|
||||
#else
|
||||
case 'A':
|
||||
|
@ -536,26 +542,34 @@ main(int argc, char *argv[])
|
|||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
{
|
||||
int len;
|
||||
char *buf;
|
||||
if (pingflags & F_POLICY) {
|
||||
if ((len = ipsec_get_policylen(policy)) < 0)
|
||||
errx(1, ipsec_strerror());
|
||||
if ((buf = malloc(len)) == NULL)
|
||||
err(1, "malloc");
|
||||
if ((len = ipsec_set_policy(buf, len, policy)) < 0)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, buf, len) < 0)
|
||||
err(1, "ipsec policy cannot be configured");
|
||||
free(buf);
|
||||
if (policy_in != NULL) {
|
||||
buf = ipsec_set_policy(policy_in, strlen(policy_in));
|
||||
if (buf == NULL)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
|
||||
buf, ipsec_get_policylen(buf)) < 0) {
|
||||
err(1, "ipsec policy cannot be configured");
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
if (policy_out != NULL) {
|
||||
buf = ipsec_set_policy(policy_out, strlen(policy_out));
|
||||
if (buf == NULL)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
|
||||
buf, ipsec_get_policylen(buf)) < 0) {
|
||||
err(1, "ipsec policy cannot be configured");
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
if ((len = ipsec_get_policylen("bypass")) < 0)
|
||||
buf = ipsec_set_policy("out bypass", strlen("out bypass"));
|
||||
if (buf == NULL)
|
||||
errx(1, ipsec_strerror());
|
||||
if ((buf = malloc(len)) == NULL)
|
||||
err(1, "malloc");
|
||||
if ((len = ipsec_set_policy(buf, len, "bypass")) < 0)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(sloop, IPPROTO_IP, IP_IPSEC_POLICY, buf, len) < 0) {
|
||||
if (setsockopt(sloop, IPPROTO_IP, IP_IPSEC_POLICY,
|
||||
buf, ipsec_get_policylen(buf)) < 0) {
|
||||
#if 0
|
||||
warnx("ipsec is not configured");
|
||||
#else
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $NetBSD: ping6.8,v 1.4 1999/12/15 05:02:39 itojun Exp $
|
||||
.\" KAME Id: ping6.8,v 1.7 1999/12/15 04:59:13 itojun Exp
|
||||
.\" $NetBSD: ping6.8,v 1.5 2000/01/31 14:24:24 itojun Exp $
|
||||
.\" KAME Id: ping6.8,v 1.11 1999/12/23 17:39:45 itojun Exp
|
||||
.\"
|
||||
.Dd May 17, 1998
|
||||
.Dt PING6 8
|
||||
|
@ -39,9 +39,9 @@ packets to network hosts
|
|||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.\" without ipsec, or new ipsec
|
||||
.Op Fl dfnqRrvw
|
||||
.Op Fl dfnqRvw
|
||||
.\" old ipsec
|
||||
.\" .Op Fl AdEfnqRrvw
|
||||
.\" .Op Fl AdEfnqRvw
|
||||
.Op Fl a Ar addrtype
|
||||
.Op Fl b Ar bufsiz
|
||||
.Op Fl c Ar count
|
||||
|
@ -54,6 +54,7 @@ packets to network hosts
|
|||
.Op Fl P Ar policy
|
||||
.Op Fl S Ar sourceaddr
|
||||
.Op Fl s Ar packetsize
|
||||
.Op Ar hops...
|
||||
.Ar host
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
|
@ -175,31 +176,19 @@ Quiet output.
|
|||
Nothing is displayed except the summary lines at startup time and
|
||||
when finished.
|
||||
.It Fl R
|
||||
Record route.
|
||||
Includes the
|
||||
.Tn RECORD_ROUTE
|
||||
option in the
|
||||
.Tn ECHO_REQUEST
|
||||
packet and displays
|
||||
the route buffer on returned packets.
|
||||
Note that the IP header is only large enough for nine such routes;
|
||||
the
|
||||
.Xr traceroute 8
|
||||
command is usually better at determining the route packets take to a
|
||||
particular destination.
|
||||
Many hosts ignore or discard the
|
||||
.Tn RECORD_ROUTE
|
||||
option.
|
||||
.It Fl r
|
||||
Bypass the normal routing tables and send directly to a host on an attached
|
||||
network.
|
||||
If the host is not on a directly-attached network, an error is returned.
|
||||
This option can be used to ping a local host through an interface
|
||||
that has no route through it
|
||||
Make the kernel believe that the target
|
||||
.Ar host
|
||||
.Po
|
||||
e.g., after the interface was dropped by
|
||||
.Xr routed 8
|
||||
.Pc .
|
||||
or the first
|
||||
.Ar hop
|
||||
if you specify
|
||||
.Ar hops
|
||||
.Pc
|
||||
is reachable, by injecting upper-layer reachability confirmation hint.
|
||||
The option is meaningful only if the target
|
||||
.Ar host
|
||||
.Pq or the first hop
|
||||
is a neighbor.
|
||||
.It Fl S Ar sourceaddr
|
||||
Specifies the source address of request packets.
|
||||
The source address must be one of the unicast addresses of the sending
|
||||
|
@ -238,6 +227,11 @@ This option was remained for backward compatibility.
|
|||
has no effect if
|
||||
.Fl w
|
||||
is specified.
|
||||
.It Ar hops
|
||||
IPv6 addresses for intermediate nodes,
|
||||
which will be put into type 0 routing header.
|
||||
.It Ar host
|
||||
IPv6 adddress of the final destination node.
|
||||
.El
|
||||
.Pp
|
||||
When using
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ping6.c,v 1.10 2000/01/22 10:01:41 tron Exp $ */
|
||||
/* $NetBSD: ping6.c,v 1.11 2000/01/31 14:24:25 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -80,7 +80,7 @@ static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
|
|||
#else
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ping6.c,v 1.10 2000/01/22 10:01:41 tron Exp $");
|
||||
__RCSID("$NetBSD: ping6.c,v 1.11 2000/01/31 14:24:25 itojun Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -102,7 +102,7 @@ __RCSID("$NetBSD: ping6.c,v 1.10 2000/01/22 10:01:41 tron Exp $");
|
|||
/*
|
||||
* NOTE:
|
||||
* USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics
|
||||
* as IPV6_PKTINFO. Some objects it (sin6_scope_id specifies *link* while
|
||||
* 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)
|
||||
*/
|
||||
|
@ -176,6 +176,9 @@ __RCSID("$NetBSD: ping6.c,v 1.10 2000/01/22 10:01:41 tron Exp $");
|
|||
#define F_FQDN 0x1000
|
||||
#define F_INTERFACE 0x2000
|
||||
#define F_SRCADDR 0x4000
|
||||
#ifdef IPV6_REACHCONF
|
||||
#define F_REACHCONF 0x8000
|
||||
#endif
|
||||
u_int options;
|
||||
|
||||
#define IN6LEN sizeof(struct in6_addr)
|
||||
|
@ -233,6 +236,7 @@ char *scmsg = 0;
|
|||
int main __P((int, char *[]));
|
||||
void fill __P((char *, char *));
|
||||
int get_hoplim __P((struct msghdr *));
|
||||
struct in6_pktinfo *get_rcvpktinfo __P((struct msghdr *));
|
||||
void onalrm __P((int));
|
||||
void oninfo __P((int));
|
||||
void onint __P((int));
|
||||
|
@ -242,9 +246,13 @@ void pr_icmph __P((struct icmp6_hdr *, u_char *));
|
|||
void pr_iph __P((struct ip6_hdr *));
|
||||
void pr_nodeaddr __P((struct icmp6_nodeinfo *, int));
|
||||
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 *));
|
||||
void pr_retip __P((struct ip6_hdr *, u_char *));
|
||||
void summary __P((void));
|
||||
void tvsub __P((struct timeval *, struct timeval *));
|
||||
int setpolicy __P((int, char *));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
|
@ -266,8 +274,12 @@ main(argc, argv)
|
|||
int sockbufsize = 0;
|
||||
int usepktinfo = 0;
|
||||
struct in6_pktinfo *pktinfo = NULL;
|
||||
#ifdef USE_RFC2292BIS
|
||||
struct ip6_rthdr *rthdr = NULL;
|
||||
#endif
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
char *policy = NULL;
|
||||
char *policy_in = NULL;
|
||||
char *policy_out = NULL;
|
||||
#endif
|
||||
|
||||
/* just to be sure */
|
||||
|
@ -277,12 +289,12 @@ main(argc, argv)
|
|||
preload = 0;
|
||||
datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
|
||||
#ifndef IPSEC
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qRrS:s:vwW")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qS:s:vwW")) != EOF)
|
||||
#else
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qRrS:s:vwWP:")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qS:s:vwWP:")) != EOF)
|
||||
#else
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qRrS:s:vwWAE")) != EOF)
|
||||
while ((ch = getopt(argc, argv, "a:b:c:dfh:I:i:l:np:qS:s:vwWAE")) != EOF)
|
||||
#endif /*IPSEC_POLICY_IPSEC*/
|
||||
#endif
|
||||
switch(ch) {
|
||||
|
@ -364,6 +376,10 @@ main(argc, argv)
|
|||
options |= F_INTERVAL;
|
||||
break;
|
||||
case 'l':
|
||||
if (getuid()) {
|
||||
errno = EPERM;
|
||||
errx(1, "Must be superuser to preload");
|
||||
}
|
||||
preload = strtol(optarg, &e, 10);
|
||||
if (preload < 0 || *optarg == '\0' || *e != '\0')
|
||||
errx(1, "illegal preload value -- %s", optarg);
|
||||
|
@ -378,9 +394,11 @@ main(argc, argv)
|
|||
case 'q':
|
||||
options |= F_QUIET;
|
||||
break;
|
||||
#ifdef IPV6_REACHCONF
|
||||
case 'R':
|
||||
options |= F_RROUTE;
|
||||
options |= F_REACHCONF;
|
||||
break;
|
||||
#endif
|
||||
case 'S':
|
||||
/* XXX: use getaddrinfo? */
|
||||
if (inet_pton(AF_INET6, optarg, (void *)&srcaddr) != 1)
|
||||
|
@ -408,7 +426,12 @@ main(argc, argv)
|
|||
#ifdef IPSEC_POLICY_IPSEC
|
||||
case 'P':
|
||||
options |= F_POLICY;
|
||||
policy = strdup(optarg);
|
||||
if (!strncmp("in", optarg, 2))
|
||||
policy_in = strdup(optarg);
|
||||
else if (!strncmp("out", optarg, 3))
|
||||
policy_out = strdup(optarg);
|
||||
else
|
||||
errx(1, "invalid security policy");
|
||||
break;
|
||||
#else
|
||||
case 'A':
|
||||
|
@ -428,8 +451,13 @@ main(argc, argv)
|
|||
if (argc < 1)
|
||||
usage();
|
||||
|
||||
if (argc > 1)
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
target = argv[argc - 1];
|
||||
|
||||
|
@ -470,9 +498,8 @@ main(argc, argv)
|
|||
|
||||
ident = getpid() & 0xFFFF;
|
||||
|
||||
if ((s = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol)) < 0)
|
||||
err(1, "socket");
|
||||
if ((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
|
||||
err(1, "socket");
|
||||
|
||||
hold = 1;
|
||||
|
||||
|
@ -488,17 +515,10 @@ main(argc, argv)
|
|||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
if (options & F_POLICY) {
|
||||
int len;
|
||||
char *buf;
|
||||
if ((len = ipsec_get_policylen(policy)) < 0)
|
||||
if (setpolicy(s, policy_in) < 0)
|
||||
errx(1, ipsec_strerror());
|
||||
if ((buf = malloc(len)) == NULL)
|
||||
err(1, "malloc");
|
||||
if ((len = ipsec_set_policy(buf, len, policy)) < 0)
|
||||
if (setpolicy(s, policy_out) < 0)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, len) < 0)
|
||||
warnx("Unable to set IPSec policy");
|
||||
free(buf);
|
||||
}
|
||||
#else
|
||||
if (options & F_AUTHHDR) {
|
||||
|
@ -540,6 +560,45 @@ main(argc, argv)
|
|||
}
|
||||
#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)))
|
||||
err(1, "setsockopt(IPV6_RECVRTHDR)");
|
||||
#else /* old adv. API */
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &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))
|
||||
|
@ -547,9 +606,6 @@ main(argc, argv)
|
|||
&optval, sizeof(optval)) == -1)
|
||||
err(1, "IPV6_MULTICAST_LOOP");
|
||||
*/
|
||||
/* record route option */
|
||||
if (options & F_RROUTE)
|
||||
errx(1, "record route not available in this implementation");
|
||||
|
||||
/* Specify the outgoing interface and/or the source address */
|
||||
if (usepktinfo)
|
||||
|
@ -558,6 +614,11 @@ main(argc, argv)
|
|||
if (hoplimit != -1)
|
||||
ip6optlen += CMSG_SPACE(sizeof(int));
|
||||
|
||||
#ifdef IPV6_REACHCONF
|
||||
if (options & F_REACHCONF)
|
||||
ip6optlen += CMSG_SPACE(0);
|
||||
#endif
|
||||
|
||||
/* set IP6 packet options */
|
||||
if (ip6optlen) {
|
||||
if ((scmsg = (char *)malloc(ip6optlen)) == 0)
|
||||
|
@ -598,12 +659,37 @@ main(argc, argv)
|
|||
|
||||
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
|
||||
}
|
||||
#ifdef IPV6_REACHCONF
|
||||
if (options & F_REACHCONF) {
|
||||
scmsgp->cmsg_len = CMSG_LEN(0);
|
||||
scmsgp->cmsg_level = IPPROTO_IPV6;
|
||||
scmsgp->cmsg_type = IPV6_REACHCONF;
|
||||
|
||||
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc > 1) { /* some intermediate addrs are specified */
|
||||
int hops, error;
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
int rthdrlen;
|
||||
#endif
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1);
|
||||
scmsgp->cmsg_len = CMSG_LEN(rthdrlen);
|
||||
scmsgp->cmsg_level = IPPROTO_IPV6;
|
||||
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);
|
||||
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)
|
||||
errx(1, "can't initialize rthdr");
|
||||
#endif /* USE_RFC2292BIS */
|
||||
|
||||
for (hops = 0; hops < argc - 1; hops++) {
|
||||
struct addrinfo *iaip;
|
||||
|
@ -614,14 +700,22 @@ main(argc, argv)
|
|||
errx(1,
|
||||
"bad addr family of an intermediate addr");
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
if (inet6_rth_add(rthdr,
|
||||
&(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))
|
||||
errx(1, "can't add an intermediate node");
|
||||
#endif /* USE_RFC2292BIS */
|
||||
}
|
||||
|
||||
#ifndef USE_RFC2292BIS
|
||||
if (inet6_rthdr_lasthop(scmsgp, IPV6_RTHDR_LOOSE))
|
||||
errx(1, "can't set the last flag");
|
||||
#endif
|
||||
|
||||
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
|
||||
}
|
||||
|
@ -640,15 +734,34 @@ main(argc, argv)
|
|||
src.sin6_port = ntohs(DUMMY_PORT);
|
||||
src.sin6_scope_id = dst.sin6_scope_id;
|
||||
|
||||
#ifndef USE_SIN6_SCOPE_ID
|
||||
if (setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS,
|
||||
|
||||
#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)))
|
||||
err(1, "UDP setsockopt(IPV6_PKTINFO)");
|
||||
|
||||
if (hoplimit != -1 &&
|
||||
setsockopt(dummy, IPPROTO_IPV6, IPV6_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))
|
||||
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)) {
|
||||
err(1, "UDP setsockopt(IPV6_PKTOPTIONS)");
|
||||
}
|
||||
#else
|
||||
src.sin6_scope_id = dst.sin6_scope_id;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (connect(dummy, (struct sockaddr *)&src, len) < 0)
|
||||
err(1, "UDP connect");
|
||||
|
@ -686,9 +799,25 @@ main(argc, argv)
|
|||
|
||||
optval = 1;
|
||||
#ifndef USE_SIN6_SCOPE_ID
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval, sizeof(optval));
|
||||
#endif
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval, sizeof(optval));
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
|
||||
sizeof(optval)) < 0)
|
||||
warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
|
||||
#else /* old adv. API */
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval,
|
||||
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)
|
||||
warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
|
||||
#else /* old adv. API */
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,
|
||||
sizeof(optval)) < 0)
|
||||
warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */
|
||||
#endif
|
||||
|
||||
printf("PING6(%d=40+8+%d bytes) ", datalen + 48, datalen);
|
||||
printf("%s --> ", inet_ntop(AF_INET6, &src.sin6_addr, ntop_buf, sizeof(ntop_buf)));
|
||||
|
@ -715,7 +844,7 @@ main(argc, argv)
|
|||
for (;;) {
|
||||
struct msghdr m;
|
||||
struct cmsghdr *cm;
|
||||
u_char buf[256];
|
||||
u_char buf[1024];
|
||||
struct iovec iov[2];
|
||||
|
||||
if (options & F_FLOOD) {
|
||||
|
@ -756,6 +885,7 @@ main(argc, argv)
|
|||
* onalrm --
|
||||
* This routine transmits another ping6.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
void
|
||||
onalrm(signo)
|
||||
int signo;
|
||||
|
@ -879,9 +1009,7 @@ pr_pack(buf, cc, mhdr)
|
|||
int hoplim;
|
||||
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
|
||||
u_char *cp = NULL, *dp, *end = buf + cc;
|
||||
#ifdef OLD_RAWSOCKET
|
||||
struct ip6_hdr *ip;
|
||||
#endif
|
||||
struct in6_pktinfo *pktinfo = NULL;
|
||||
struct timeval tv, *tp;
|
||||
double triptime = 0;
|
||||
int dupflag;
|
||||
|
@ -889,57 +1017,6 @@ pr_pack(buf, cc, mhdr)
|
|||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
|
||||
#ifdef OLD_RAWSOCKET
|
||||
/* Check the IP header */
|
||||
ip = (struct ip6_hdr *)buf;
|
||||
if (cc < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("packet too short (%d bytes) from %s\n", cc,
|
||||
inet_ntop(AF_INET6, (void *)&from->sin6_addr,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
return;
|
||||
}
|
||||
|
||||
/* chase nexthdr link */
|
||||
{
|
||||
u_int8_t nh;
|
||||
struct ah *ah;
|
||||
struct ip6_ext *ip6e;
|
||||
|
||||
off = IP6LEN;
|
||||
nh = ip->ip6_nxt;
|
||||
while (nh != IPPROTO_ICMPV6) {
|
||||
if (options & F_VERBOSE)
|
||||
fprintf(stderr, "header chain: type=0x%x\n", nh);
|
||||
|
||||
switch (nh) {
|
||||
#ifdef IPSEC
|
||||
case IPPROTO_AH:
|
||||
ah = (struct ah *)(buf + off);
|
||||
off += sizeof(struct ah);
|
||||
off += (ah->ah_len << 2);
|
||||
nh = ah->ah_nxt;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IPPROTO_HOPOPTS:
|
||||
ip6e = (struct ip6_ext *)(buf + off);
|
||||
off += (ip6e->ip6e_len + 1) << 3;
|
||||
nh = ip6e->ip6e_nxt;
|
||||
break;
|
||||
default:
|
||||
if (options & F_VERBOSE) {
|
||||
fprintf(stderr,
|
||||
"unknown header type=0x%x: drop it\n",
|
||||
nh);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Now the ICMP part */
|
||||
icp = (struct icmp6_hdr *)(buf + off);
|
||||
#else
|
||||
if (cc < sizeof(struct icmp6_hdr)) {
|
||||
if (options & F_VERBOSE)
|
||||
warnx("packet too short (%d bytes) from %s\n", cc,
|
||||
|
@ -949,12 +1026,15 @@ pr_pack(buf, cc, mhdr)
|
|||
}
|
||||
icp = (struct icmp6_hdr *)buf;
|
||||
off = 0;
|
||||
#endif
|
||||
|
||||
if ((hoplim = get_hoplim(mhdr)) == -1) {
|
||||
warnx("failed to get receiving hop limit");
|
||||
return;
|
||||
}
|
||||
if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) {
|
||||
warnx("failed to get receiving pakcet information");
|
||||
return;
|
||||
}
|
||||
|
||||
if (icp->icmp6_type == ICMP6_ECHO_REPLY) {
|
||||
/* XXX the following line overwrites the original packet */
|
||||
|
@ -993,6 +1073,16 @@ pr_pack(buf, cc, mhdr)
|
|||
pr_addr(from),
|
||||
icp->icmp6_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;
|
||||
dstsa.sin6_len = sizeof(dstsa);
|
||||
dstsa.sin6_scope_id = pktinfo->ipi6_ifindex;
|
||||
dstsa.sin6_addr = pktinfo->ipi6_addr;
|
||||
(void)printf(" dst=%s", pr_addr(&dstsa));
|
||||
}
|
||||
if (timing)
|
||||
(void)printf(" time=%g ms", triptime);
|
||||
if (dupflag)
|
||||
|
@ -1086,10 +1176,145 @@ pr_pack(buf, cc, mhdr)
|
|||
|
||||
if (!(options & F_FLOOD)) {
|
||||
(void)putchar('\n');
|
||||
if (options & F_VERBOSE)
|
||||
pr_exthdrs(mhdr);
|
||||
(void)fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pr_exthdrs(mhdr)
|
||||
struct msghdr *mhdr;
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
|
||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
|
||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
|
||||
if (cm->cmsg_level != IPPROTO_IPV6)
|
||||
continue;
|
||||
|
||||
switch(cm->cmsg_type) {
|
||||
case IPV6_HOPOPTS:
|
||||
printf(" HbH Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
break;
|
||||
case IPV6_DSTOPTS:
|
||||
#ifdef IPV6_RTHDRDSTOPTS
|
||||
case IPV6_RTHDRDSTOPTS:
|
||||
#endif
|
||||
printf(" Dst Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
break;
|
||||
case IPV6_RTHDR:
|
||||
printf(" Routing: ");
|
||||
pr_rthdr(CMSG_DATA(cm));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
void
|
||||
pr_ip6opt(void *extbuf)
|
||||
{
|
||||
struct ip6_hbh *ext;
|
||||
int currentlen;
|
||||
u_int8_t type;
|
||||
size_t extlen, len;
|
||||
void *databuf;
|
||||
size_t offset;
|
||||
u_int16_t value2;
|
||||
u_int32_t value4;
|
||||
|
||||
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);
|
||||
|
||||
currentlen = 0;
|
||||
while (1) {
|
||||
currentlen = inet6_opt_next(extbuf, extlen, currentlen,
|
||||
&type, &len, &databuf);
|
||||
if (currentlen == -1)
|
||||
break;
|
||||
switch (type) {
|
||||
/*
|
||||
* Note that inet6_opt_next automatically skips any padding
|
||||
* optins.
|
||||
*/
|
||||
case IP6OPT_JUMBO:
|
||||
offset = 0;
|
||||
offset = inet6_opt_get_val(databuf, offset,
|
||||
&value4, sizeof(value4));
|
||||
printf(" Jumbo Payload Opt: Length %u\n",
|
||||
(unsigned int)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));
|
||||
break;
|
||||
default:
|
||||
printf(" Received Opt %u len %u\n", type, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else /* !USE_RFC2292BIS */
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pr_ip6opt(void *extbuf)
|
||||
{
|
||||
putchar('\n');
|
||||
return;
|
||||
}
|
||||
#endif /* USE_RFC2292BIS */
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
void
|
||||
pr_rthdr(void *extbuf)
|
||||
{
|
||||
struct in6_addr *in6;
|
||||
char ntopbuf[INET6_ADDRSTRLEN];
|
||||
struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
|
||||
int i, segments;
|
||||
|
||||
/* 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);
|
||||
if ((segments = inet6_rth_segments(extbuf)) >= 0)
|
||||
printf("%d segments, ", segments);
|
||||
else
|
||||
printf("segments unknown, ");
|
||||
printf("%d left\n", rh->ip6r_segleft);
|
||||
|
||||
for (i = 0; i < segments; i++) {
|
||||
in6 = inet6_rth_getaddr(extbuf, i);
|
||||
if (in6 == NULL)
|
||||
printf(" [%d]<NULL>\n", i);
|
||||
else
|
||||
printf(" [%d]%s\n", i,
|
||||
inet_ntop(AF_INET6, (void *)in6->s6_addr,
|
||||
ntopbuf, sizeof(ntopbuf)));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
#else /* !USE_RFC2292BIS */
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pr_rthdr(void *extbuf)
|
||||
{
|
||||
putchar('\n');
|
||||
return;
|
||||
}
|
||||
#endif /* USE_RFC2292BIS */
|
||||
|
||||
|
||||
void
|
||||
pr_nodeaddr(ni, nilen)
|
||||
struct icmp6_nodeinfo *ni; /* ni->qtype must be NODEADDR */
|
||||
|
@ -1137,6 +1362,23 @@ get_hoplim(mhdr)
|
|||
return(-1);
|
||||
}
|
||||
|
||||
struct in6_pktinfo *
|
||||
get_rcvpktinfo(mhdr)
|
||||
struct msghdr *mhdr;
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
|
||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
|
||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
|
||||
if (cm->cmsg_level == IPPROTO_IPV6 &&
|
||||
cm->cmsg_type == IPV6_PKTINFO &&
|
||||
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
|
||||
return((struct in6_pktinfo *)CMSG_DATA(cm));
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* tvsub --
|
||||
* Subtract 2 timeval structs: out = out - in. Out is assumed to
|
||||
|
@ -1157,6 +1399,7 @@ tvsub(out, in)
|
|||
* oninfo --
|
||||
* SIGINFO handler.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
void
|
||||
oninfo(notused)
|
||||
int notused;
|
||||
|
@ -1168,6 +1411,7 @@ oninfo(notused)
|
|||
* onint --
|
||||
* SIGINT handler.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
void
|
||||
onint(notused)
|
||||
int notused;
|
||||
|
@ -1268,6 +1512,7 @@ pr_icmph(icp, end)
|
|||
case ICMP6_PACKET_TOO_BIG:
|
||||
(void)printf("Packet too big mtu = %d\n",
|
||||
(int)ntohl(icp->icmp6_mtu));
|
||||
pr_retip((struct ip6_hdr *)(icp + 1), end);
|
||||
break;
|
||||
case ICMP6_TIME_EXCEEDED:
|
||||
switch(icp->icmp6_code) {
|
||||
|
@ -1305,57 +1550,57 @@ pr_icmph(icp, end)
|
|||
pr_retip((struct ip6_hdr *)(icp + 1), end);
|
||||
break;
|
||||
case ICMP6_ECHO_REQUEST:
|
||||
(void)printf("Echo Request\n");
|
||||
(void)printf("Echo Request");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
case ICMP6_ECHO_REPLY:
|
||||
(void)printf("Echo Reply\n");
|
||||
(void)printf("Echo Reply");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
case ICMP6_MEMBERSHIP_QUERY:
|
||||
(void)printf("Membership Query\n");
|
||||
(void)printf("Listener Query");
|
||||
break;
|
||||
case ICMP6_MEMBERSHIP_REPORT:
|
||||
(void)printf("Membership Report\n");
|
||||
(void)printf("Listener Report");
|
||||
break;
|
||||
case ICMP6_MEMBERSHIP_REDUCTION:
|
||||
(void)printf("Membership Reduction\n");
|
||||
(void)printf("Listener Done");
|
||||
break;
|
||||
case ND_ROUTER_SOLICIT:
|
||||
(void)printf("Router Solicitation\n");
|
||||
(void)printf("Router Solicitation");
|
||||
break;
|
||||
case ND_ROUTER_ADVERT:
|
||||
(void)printf("Router Advertisement\n");
|
||||
(void)printf("Router Advertisement");
|
||||
break;
|
||||
case ND_NEIGHBOR_SOLICIT:
|
||||
(void)printf("Neighbor Solicitation\n");
|
||||
(void)printf("Neighbor Solicitation");
|
||||
break;
|
||||
case ND_NEIGHBOR_ADVERT:
|
||||
(void)printf("Neighbor Advertisement\n");
|
||||
(void)printf("Neighbor Advertisement");
|
||||
break;
|
||||
case ND_REDIRECT:
|
||||
{
|
||||
struct nd_redirect *red = (struct nd_redirect *)icp;
|
||||
|
||||
(void)printf("Redirect\n");
|
||||
(void)printf("Destination: %s\n",
|
||||
(void)printf("Destination: %s",
|
||||
inet_ntop(AF_INET6, &red->nd_rd_dst,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
(void)printf("New Target: %s\n",
|
||||
(void)printf("New Target: %s",
|
||||
inet_ntop(AF_INET6, &red->nd_rd_target,
|
||||
ntop_buf, sizeof(ntop_buf)));
|
||||
break;
|
||||
}
|
||||
case ICMP6_NI_QUERY:
|
||||
(void)printf("Node Information Query\n");
|
||||
(void)printf("Node Information Query");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
case ICMP6_NI_REPLY:
|
||||
(void)printf("Node Information Reply\n");
|
||||
(void)printf("Node Information Reply");
|
||||
/* XXX ID + Seq + Data */
|
||||
break;
|
||||
default:
|
||||
(void)printf("Bad ICMP type: %d\n", icp->icmp6_type);
|
||||
(void)printf("Bad ICMP type: %d", icp->icmp6_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1527,11 +1772,36 @@ fill(bp, patp)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
int
|
||||
setpolicy(so, policy)
|
||||
int so;
|
||||
char *policy;
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (policy == NULL)
|
||||
return 0; /* ignore */
|
||||
|
||||
buf = ipsec_set_policy(policy, strlen(policy));
|
||||
if (buf == NULL)
|
||||
errx(1, ipsec_strerror());
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
|
||||
buf, ipsec_get_policylen(buf)) < 0)
|
||||
warnx("Unable to set IPSec policy");
|
||||
free(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: ping6 [-dfnqRrvwW"
|
||||
"usage: ping6 [-dfnqvwW"
|
||||
#ifdef IPSEC
|
||||
#ifdef IPSEC_POLICY_IPSEC
|
||||
"] [-P policy"
|
||||
|
@ -1541,6 +1811,6 @@ usage()
|
|||
#endif
|
||||
"] [-a [alsg]] [-b sockbufsiz] [-c count] [-I interface]\n\
|
||||
[-i wait] [-l preload] [-p pattern] [-S sourceaddr]\n\
|
||||
[-s packetsize] [-h hoplimit] host [hosts...]\n");
|
||||
[-s packetsize] [-h hoplimit] [hops...] host\n");
|
||||
exit(1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue