summaryrefslogtreecommitdiffstats
path: root/usr.sbin/traceroute6/traceroute6.c
diff options
context:
space:
mode:
authorkris <kris@FreeBSD.org>2000-07-05 11:00:58 +0000
committerkris <kris@FreeBSD.org>2000-07-05 11:00:58 +0000
commit4bf2ee28177f0ea34186c988894ee9ad966de5e4 (patch)
tree3ba57e895670bc0af72845589028d843c795659a /usr.sbin/traceroute6/traceroute6.c
parentb896bc0c0513fa1d75c808180485c48463cab2a1 (diff)
downloadFreeBSD-src-4bf2ee28177f0ea34186c988894ee9ad966de5e4.zip
FreeBSD-src-4bf2ee28177f0ea34186c988894ee9ad966de5e4.tar.gz
Sync with latest KAME code.
Obtained from: KAME
Diffstat (limited to 'usr.sbin/traceroute6/traceroute6.c')
-rw-r--r--usr.sbin/traceroute6/traceroute6.c487
1 files changed, 357 insertions, 130 deletions
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);
}
OpenPOWER on IntegriCloud