Sync with latest KAME code.

Obtained from:	KAME
This commit is contained in:
Kris Kennaway 2000-07-05 11:00:58 +00:00
parent afc3b53891
commit de68a0dac8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=62637
2 changed files with 387 additions and 135 deletions

View File

@ -25,7 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id: traceroute6.8,v 1.1.1.1 1999/08/08 23:32:38 itojun Exp $
.\" $FreeBSD$
.\"
.Dd May 17, 1998
@ -37,18 +36,48 @@
.Nd "print the route IPv6 packets will take to the destination"
.\"
.Sh SYNOPSIS
.Nm
.Nm traceroute6
.Bk -words
.Op Fl dlnrv
.Ek
.Bk -words
.Op Fl f Ar firsthop
.Ek
.Bk -words
.Op Fl g Ar gateway
.Ek
.Bk -words
.Op Fl m Ar hoplimit
.Ek
.Bk -words
.Op Fl p Ar port
.Ek
.Bk -words
.Op Fl q Ar probes
.Ek
.Bk -words
.Op Fl s Ar src
.Ek
.Bk -words
.Op Fl w Ar waittime
.Ek
.Bk -words
.Ar target
.Op Ar datalen
.Ek
.\"
.Sh DESCRIPTION
.Bl -tag -width Ds
.It Fl d
Debug mode.
.It Fl f Ar firsthop
Specify how many hops to skip in trace.
.It Fl g Ar gateway
Specify intermediate gateway
.Po
.Nm
uses routing header
.Pc .
.It Fl m Ar hoplimit
Specify maximum hoplimit.
.It Fl l
@ -92,7 +121,3 @@ command will exit with 0 on success, and non-zero on errors.
The
.Nm
command first appeared in WIDE hydrangea IPv6 protocol stack kit.
.Pp
IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack
was initially integrated into
.Fx 4.0

View File

@ -1,3 +1,5 @@
/* $KAME: traceroute6.c,v 1.29 2000/06/12 16:29:18 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@ -25,8 +27,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*-
@ -72,7 +72,11 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/*
@ -274,26 +278,30 @@ static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
#include <netinet6/ipsec.h>
#endif
#define freehostent(hp)
#define DUMMY_PORT 10010
#define DUMMY_PORT 10010
#define MAXPACKET 65535 /* max ip packet size */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#define MAXHOSTNAMELEN 64
#endif
#ifndef FD_SET
#define NFDBITS (8*sizeof(fd_set))
#define FD_SETSIZE NFDBITS
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#define NFDBITS (8*sizeof(fd_set))
#define FD_SETSIZE NFDBITS
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#endif
#define Fprintf (void)fprintf
#define Sprintf (void)sprintf
#define Printf (void)printf
#define Fprintf (void)fprintf
#define Sprintf (void)sprintf
#define Printf (void)printf
#ifndef HAVE_GETIPNODEBYNAME
#define getipnodebyname(x, y, z, u) gethostbyname2((x), (y))
#define freehostent(x)
#endif
/*
* format of a (udp) probe packet.
@ -309,7 +317,11 @@ struct opacket *outpacket; /* last output (udp) packet */
int main __P((int, char *[]));
int wait_for_reply __P((int, struct msghdr *));
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
int setpolicy __P((int so, char *policy));
#endif
#endif
void send_probe __P((int, int));
struct udphdr *get_udphdr __P((struct ip6_hdr *, u_char *));
int get_hoplim __P((struct msghdr *));
@ -318,7 +330,7 @@ char *pr_type __P((int));
int packet_ok __P((struct msghdr *, int, int));
void print __P((struct msghdr *, int));
void tvsub __P((struct timeval *, struct timeval *));
char *inetname __P((struct in6_addr *));
const char *inetname __P((struct sockaddr *));
void usage __P((void));
int rcvsock; /* receive (icmp) socket file descriptor */
@ -331,15 +343,19 @@ int rcvhlim;
struct in6_pktinfo *rcvpktinfo;
struct sockaddr_in6 Src, Dst, Rcv;
struct sockaddr_in6 *src = &Src, *dst = &Dst, *rcv = &Rcv;
int datalen; /* How much data */
char rtbuf[1024]; /*XXX*/
/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
char rtbuf[2064];
#ifdef USE_RFC2292BIS
struct ip6_rthdr *rth;
#endif
struct cmsghdr *cmsg;
char *source = 0;
char *hostname;
int nprobes = 3;
int first_hop = 1;
int max_hops = 30;
u_short ident;
u_short port = 32768+666; /* start udp dest port # for probe packets */
@ -349,41 +365,74 @@ int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
int lflag; /* print both numerical address & hostname */
char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
#ifdef KAME_SCOPEID
const int niflag = NI_WITHSCOPEID;
#else
const int niflag = 0;
#endif
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
struct hostent *hp;
struct addrinfo hints, *res;
int error;
int ch, i, on, probe, seq, hops;
static u_char rcvcmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))
+ CMSG_SPACE(sizeof(int))];
struct addrinfo hints, *res;
int ch, i, on, probe, seq, hops, rcvcmsglen;
static u_char *rcvcmsgbuf;
char hbuf[NI_MAXHOST], src0[NI_MAXHOST];
/*
* Receive ICMP
*/
if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
perror("traceroute6: icmp socket");
perror("socket(ICMPv6)");
exit(5);
}
/* set a minimum set of socket options */
on = 1;
/* specify to tell receiving interface */
#ifdef IPV6_RECVPKTINFO
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_RECVPKTINFO)");
#else /* old adv. API */
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_PKTINFO)");
#endif
/* specify to tell value of hoplimit field of received IP6 hdr */
#ifdef IPV6_RECVHOPLIMIT
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
#else /* old adv. API */
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_HOPLIMIT)");
#endif
/* revoke privs */
seteuid(getuid());
setuid(getuid());
on = 1;
seq = 0;
while ((ch = getopt(argc, argv, "dlm:np:q:rs:w:vg:")) != EOF)
while ((ch = getopt(argc, argv, "df:g:lm:np:q:rs:w:v")) != EOF)
switch(ch) {
case 'd':
options |= SO_DEBUG;
break;
case 'l':
lflag++;
case 'f':
first_hop = atoi(optarg);
if (first_hop > max_hops) {
Fprintf(stderr,
"traceroute6: min hoplimit must be <= %d.\n", max_hops);
exit(1);
}
break;
case 'g':
hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
@ -392,15 +441,43 @@ main(argc, argv)
"traceroute6: unknown host %s\n", optarg);
exit(1);
}
#ifdef USE_RFC2292BIS
if (rth == NULL) {
/*
* XXX: We can't detect the number of
* intermediate nodes yet.
*/
if ((rth = inet6_rth_init((void *)rtbuf,
sizeof(rtbuf),
IPV6_RTHDR_TYPE_0,
0)) == NULL) {
Fprintf(stderr,
"inet6_rth_init failed.\n");
exit(1);
}
}
if (inet6_rth_add((void *)rth,
(struct in6_addr *)hp->h_addr)) {
Fprintf(stderr,
"inet6_rth_add failed for %s\n",
optarg);
exit(1);
}
#else /* old advanced API */
if (cmsg == NULL)
cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0);
inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr, IPV6_RTHDR_LOOSE);
#endif
freehostent(hp);
break;
case 'l':
lflag++;
break;
case 'm':
max_hops = atoi(optarg);
if (max_hops <= 1) {
if (max_hops < first_hop) {
Fprintf(stderr,
"traceroute6: max hoplimit must be >1.\n");
"traceroute6: max hoplimit must be >= %d.\n", first_hop);
exit(1);
}
break;
@ -453,7 +530,11 @@ main(argc, argv)
if (argc < 1)
usage();
#if 1
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
#else
setlinebuf (stdout);
#endif
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
@ -464,16 +545,15 @@ main(argc, argv)
if (error) {
(void)fprintf(stderr,
"traceroute6: %s\n", gai_strerror(error));
if (error == EAI_SYSTEM)
(void)fprintf(stderr,
"traceroute6: %s\n", strerror(errno));
exit(1);
}
if (!res->ai_addr)
errx(1, "getaddrinfo failed");
if (res->ai_addrlen != sizeof(Dst)) {
(void)fprintf(stderr,
"traceroute6: size of sockaddr mismatch\n");
exit(1);
}
memcpy(&Dst, res->ai_addr, res->ai_addrlen);
hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
freeaddrinfo(res);
if (*++argv)
datalen = atoi(*argv);
@ -486,7 +566,7 @@ main(argc, argv)
datalen += sizeof(struct opacket);
outpacket = (struct opacket *)malloc((unsigned)datalen);
if (! outpacket) {
perror("traceroute6: malloc");
perror("malloc");
exit(1);
}
(void) bzero((char *)outpacket, datalen);
@ -494,22 +574,18 @@ main(argc, argv)
/* initialize msghdr for receiving packets */
rcviov[0].iov_base = (caddr_t)packet;
rcviov[0].iov_len = sizeof(packet);
rcvmhdr.msg_name = (caddr_t)rcv;
rcvmhdr.msg_namelen = sizeof(*rcv);
rcvmhdr.msg_name = (caddr_t)&Rcv;
rcvmhdr.msg_namelen = sizeof(Rcv);
rcvmhdr.msg_iov = rcviov;
rcvmhdr.msg_iovlen = 1;
rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo))
+ CMSG_SPACE(sizeof(int));
if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
Fprintf(stderr, "traceroute6: malloc failed\n");
exit(1);
}
rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
rcvmhdr.msg_controllen = sizeof(rcvcmsgbuf);
/* specify to tell receiving interface */
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_PKTINFO)");
/* specify to tell value of hoplimit field of received IP6 hdr */
if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
sizeof(on)) < 0)
err(1, "setsockopt(IPV6_HOPLIMIT)");
rcvmhdr.msg_controllen = rcvcmsglen;
if (options & SO_DEBUG)
(void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
@ -527,6 +603,26 @@ main(argc, argv)
errx(1, ipsec_strerror());
if (setpolicy(rcvsock, "out bypass") < 0)
errx(1, ipsec_strerror());
#else
{
int level = IPSEC_LEVEL_NONE;
(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
sizeof(level));
(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
sizeof(level));
#ifdef IP_AUTH_TRANS_LEVEL
(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
sizeof(level));
#else
(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
sizeof(level));
#endif
#ifdef IP_AUTH_NETWORK_LEVEL
(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
sizeof(level));
#endif
}
#endif /*IPSEC_POLICY_IPSEC*/
#endif /*IPSEC*/
@ -534,25 +630,43 @@ main(argc, argv)
* Send UDP
*/
if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
perror("traceroute6: udp socket");
perror("socket(SOCK_DGRAM)");
exit(5);
}
#ifdef SO_SNDBUF
if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
sizeof(datalen)) < 0) {
perror("traceroute6: SO_SNDBUF");
perror("setsockopt(SO_SNDBUF)");
exit(6);
}
#endif /* SO_SNDBUF */
if (options & SO_DEBUG)
(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
(char *)&on, sizeof(on));
if (options & SO_DONTROUTE)
(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
(char *)&on, sizeof(on));
#ifdef USE_RFC2292BIS
if (rth) {/* XXX: there is no library to finalize the header... */
rth->ip6r_len = rth->ip6r_segleft * 2;
if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
(void *)rth, (rth->ip6r_len + 1) << 3)) {
Fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
strerror(errno));
exit(1);
}
}
#else /* old advanced API */
if (cmsg != NULL) {
inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
(void) setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
rtbuf, cmsg->cmsg_len);
if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
rtbuf, cmsg->cmsg_len) < 0) {
Fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n",
strerror(errno));
exit(1);
}
}
#endif /* USE_RFC2292BIS */
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
/*
@ -563,62 +677,130 @@ main(argc, argv)
errx(1, ipsec_strerror());
if (setpolicy(sndsock, "out bypass") < 0)
errx(1, ipsec_strerror());
#else
{
int level = IPSEC_LEVEL_BYPASS;
(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
sizeof(level));
(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
sizeof(level));
#ifdef IP_AUTH_TRANS_LEVEL
(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
sizeof(level));
#else
(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
sizeof(level));
#endif
#ifdef IP_AUTH_NETWORK_LEVEL
(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
sizeof(level));
#endif
}
#endif /*IPSEC_POLICY_IPSEC*/
#endif /*IPSEC*/
/*
* Source selection
*/
bzero((char *)src, sizeof(Src));
bzero(&Src, sizeof(Src));
if (source) {
if (inet_pton(AF_INET6, source, &Src.sin6_addr) != 1) {
Printf("traceroute6: unknown host %s\n", source);
struct addrinfo hints, *res;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
error = getaddrinfo(source, "0", &hints, &res);
if (error) {
Printf("traceroute6: %s: %s\n", source,
gai_strerror(error));
exit(1);
}
if (res->ai_addrlen > sizeof(Src)) {
Printf("traceroute6: %s: %s\n", source,
gai_strerror(error));
exit(1);
}
memcpy(&Src, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
} else {
struct sockaddr_in6 Nxt;
int dummy, len;
len = sizeof(Src);
Nxt = Dst;
Nxt.sin6_port = htons(DUMMY_PORT);
if (cmsg != NULL)
bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
sizeof(Nxt.sin6_addr));
if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
perror("socket") ;
perror("socket");
exit(1);
}
if(-1 == connect(dummy, (struct sockaddr *)&Nxt, sizeof(Nxt)))
if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
perror("connect");
if(-1 == getsockname(dummy, (struct sockaddr *)src, &len)) {
perror("getsockname");
printf("%d\n", errno);
exit(1);
}
close(dummy) ;
len = sizeof(Src);
if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
perror("getsockname");
exit(1);
}
if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len,
src0, sizeof(src0), NULL, 0,
NI_NUMERICHOST | niflag)) {
Fprintf(stderr, "getnameinfo failed for source\n");
exit(1);
}
source = src0;
close(dummy);
}
#if 1
ident = (getpid() & 0xffff) | 0x8000;
Src.sin6_family = AF_INET6;
#else
ident = 0; /*let the kernel pick one*/
#endif
Src.sin6_port = htons(ident);
if (bind(sndsock, (struct sockaddr *)src, sizeof(Src)) < 0){
perror ("traceroute6: bind:");
exit (1);
if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
perror("bind");
exit(1);
}
if (ident == 0) {
int len;
len = sizeof(Src);
if (getsockname(sndsock, (struct sockaddr *)&Src, &i) < 0) {
perror("getsockname");
exit(1);
}
ident = ntohs(Src.sin6_port);
}
/*
* Message to users
*/
Fprintf(stderr, "traceroute to %s (%s)", hostname,
inet_ntop(AF_INET6, &Dst.sin6_addr,
ntop_buf, sizeof(ntop_buf)));
if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
sizeof(hbuf), NULL, 0, NI_NUMERICHOST | niflag))
strcpy(hbuf, "(invalid)");
Fprintf(stderr, "traceroute6");
Fprintf(stderr, " to %s (%s)", hostname, hbuf);
if (source)
Fprintf(stderr, " from %s", source);
Fprintf(stderr, ", %d hops max, %d byte packets\n", max_hops, datalen);
Fprintf(stderr,
", %d hops max, %d byte packets\n",
max_hops, datalen);
(void) fflush(stderr);
if (first_hop > 1)
Printf("Skipping %d intermediate hops\n", first_hop - 1);
/*
* Main loop
*/
for (hops = 1; hops <= max_hops; ++hops) {
for (hops = first_hop; hops <= max_hops; ++hops) {
struct in6_addr lastaddr;
int got_there = 0;
int unreachable = 0;
@ -712,7 +894,7 @@ setpolicy(so, policy)
buf = ipsec_set_policy(policy, strlen(policy));
if (buf == NULL) {
warnx(ipsec_strerror());
warnx("%s", ipsec_strerror());
return -1;
}
(void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
@ -744,7 +926,7 @@ send_probe(seq, hops)
(void) gettimeofday(&op->tv, &tz);
i = sendto(sndsock, (char *)outpacket, datalen , 0,
(struct sockaddr *)dst, sizeof(Dst));
(struct sockaddr *)&Dst, Dst.sin6_len);
if (i < 0 || i != datalen) {
if (i<0)
perror("sendto");
@ -834,7 +1016,7 @@ pr_type(t0)
cp = "Neighbor Advertisement";
break;
case ND_REDIRECT:
cp = "Ridirect";
cp = "Redirect";
break;
default:
cp = "Unknown";
@ -856,15 +1038,42 @@ packet_ok(mhdr, cc, seq)
char *buf = (char *)mhdr->msg_iov[0].iov_base;
struct cmsghdr *cm;
int *hlimp;
char hbuf[NI_MAXHOST];
#ifdef OLDRAWSOCKET
int hlen;
struct ip6_hdr *ip;
#endif
#ifdef OLDRAWSOCKET
ip = (struct ip6_hdr *) buf;
hlen = sizeof(struct ip6_hdr);
if (cc < hlen + sizeof(struct icmp6_hdr)) {
if (verbose) {
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
strcpy(hbuf, "invalid");
Printf("packet too short (%d bytes) from %s\n", cc,
hbuf);
}
return (0);
}
cc -= hlen;
icp = (struct icmp6_hdr *)(buf + hlen);
#else
if (cc < sizeof(struct icmp6_hdr)) {
if (verbose)
Printf("data too short (%d bytes) from %s\n", cc,
inet_ntop(AF_INET6, &from->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
if (verbose) {
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
strcpy(hbuf, "invalid");
Printf("data too short (%d bytes) from %s\n", cc, hbuf);
}
return(0);
}
icp = (struct icmp6_hdr *)buf;
#endif
/* get optional information via advanced API */
rcvpktinfo = NULL;
hlimp = NULL;
@ -883,9 +1092,14 @@ packet_ok(mhdr, cc, seq)
}
if (rcvpktinfo == NULL || hlimp == NULL) {
warnx("failed to get received hop limit or packet info");
#if 0
return(0);
#else
rcvhlim = 0; /*XXX*/
#endif
}
rcvhlim = *hlimp;
else
rcvhlim = *hlimp;
type = icp->icmp6_type;
code = icp->icmp6_code;
@ -906,18 +1120,31 @@ packet_ok(mhdr, cc, seq)
}
if (verbose) {
int i;
u_long *lp = (u_long *)(icp + 1);
char sbuf[INET6_ADDRSTRLEN+1], dbuf[INET6_ADDRSTRLEN];
u_int8_t *p;
char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
Printf("\n%d bytes from %s to %s", cc,
inet_ntop(AF_INET6, &from->sin6_addr,
sbuf, sizeof(sbuf)),
inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
dbuf, sizeof(dbuf)));
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST | niflag) != 0)
strcpy(sbuf, "invalid");
Printf("\n%d bytes from %s to %s", cc, sbuf,
rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
dbuf, sizeof(dbuf))
: "?");
Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
icp->icmp6_code);
for (i = 4; i < cc ; i += sizeof(long))
Printf("%2d: %8.8x\n", i, (u_int32_t)ntohl(*lp++));
p = (u_int8_t *)(icp + 1);
#define WIDTH 16
for (i = 0; i < cc; i++) {
if (i % WIDTH == 0)
Printf("%04x:", i);
if (i % 4 == 0)
Printf(" ");
Printf("%02x", p[i]);
if (i % WIDTH == WIDTH - 1)
Printf("\n");
}
if (cc % WIDTH != 0)
Printf("\n");
}
return(0);
}
@ -973,24 +1200,30 @@ print(mhdr, cc)
int cc;
{
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
char hbuf[NI_MAXHOST];
if (nflag) {
Printf(" %s", inet_ntop(AF_INET6, &from->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
}
else if (lflag) {
Printf(" %s (%s)", inetname(&from->sin6_addr),
inet_ntop(AF_INET6, &from->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
}
else {
Printf(" %s", inetname(&from->sin6_addr));
}
if (getnameinfo((struct sockaddr *)from, from->sin6_len,
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST | niflag) != 0)
strcpy(hbuf, "invalid");
if (nflag)
Printf(" %s", hbuf);
else if (lflag)
Printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
else
Printf(" %s", inetname((struct sockaddr *)from));
if (verbose) {
#ifdef OLDRAWSOCKET
Printf(" %d bytes to %s", cc,
rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
hbuf, sizeof(hbuf))
: "?");
#else
Printf(" %d bytes of data to %s", cc,
inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
ntop_buf, sizeof(ntop_buf)));
rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
hbuf, sizeof(hbuf))
: "?");
#endif
}
}
@ -1015,16 +1248,14 @@ tvsub(out, in)
* If the nflag has been supplied, give
* numeric value, otherwise try for symbolic name.
*/
char *
inetname(in)
struct in6_addr *in;
const char *
inetname(sa)
struct sockaddr *sa;
{
register char *cp;
static char line[50];
struct hostent *hp;
static char line[NI_MAXHOST];
static char domain[MAXHOSTNAMELEN + 1];
static int first = 1;
int herr;
if (first && !nflag) {
first = 0;
@ -1034,34 +1265,30 @@ inetname(in)
else
domain[0] = 0;
}
cp = 0;
cp = NULL;
if (!nflag) {
/* hp = (struct hostent *)addr2hostname(in, sizeof(*in), AF_INET6, &herr); */
hp = (struct hostent *)getipnodebyaddr((const char *)in, sizeof(*in),
AF_INET6, &herr);
if (hp) {
if ((cp = index(hp->h_name, '.')) &&
if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
NI_NAMEREQD) == 0) {
if ((cp = index(line, '.')) &&
!strcmp(cp + 1, domain))
*cp = 0;
cp = hp->h_name;
#undef freehostent(hp)
freehostent(hp);
#define freehostent(hp)
cp = line;
}
}
if (cp)
(void) strcpy(line, cp);
else {
(void)inet_ntop(AF_INET6, in, line, sizeof(line));
}
return (line);
return cp;
if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
NI_NUMERICHOST | niflag) != 0)
strcpy(line, "invalid");
return line;
}
void
usage()
{
(void)fprintf(stderr,
"usage: traceroute6 [-dlnrv] [-m max_hops] [-p port#] [-q nqueries]\n\t\
[-s src_addr] [-g gateway] [-w wait] host [data size]\n");
"usage: traceroute6 [-dlnrv] [-f first_hop] [-m max_hops] [-p port#] \n"
" [-q nqueries] [-s src_addr] [-g gateway] [-w wait] host [data size]\n");
exit(1);
}