diff options
Diffstat (limited to 'usr.sbin/traceroute6')
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.8 | 37 | ||||
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.c | 487 |
2 files changed, 388 insertions, 136 deletions
diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8 index 575c86c..38d1714 100644 --- a/usr.sbin/traceroute6/traceroute6.8 +++ b/usr.sbin/traceroute6/traceroute6.8 @@ -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 diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c index 65f80e7..163cf0c 100644 --- a/usr.sbin/traceroute6/traceroute6.c +++ b/usr.sbin/traceroute6/traceroute6.c @@ -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); } - setuid(getuid()); + /* set a minimum set of socket options */ on = 1; - seq = 0; + /* 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 - while ((ch = getopt(argc, argv, "dlm:np:q:rs:w:vg:")) != EOF) + /* revoke privs */ + seteuid(getuid()); + setuid(getuid()); + + seq = 0; + + 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)) { + exit(1); + } + len = sizeof(Src); + if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { perror("getsockname"); - printf("%d\n", errno); + 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); } - close(dummy) ; + 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]; - - 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))); + u_int8_t *p; + char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; + + 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; - - 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)); - } + char hbuf[NI_MAXHOST]; + + 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); } |