traceroute6.c revision 308714
1/*	$KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz Exp $	*/
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*-
33 * Copyright (c) 1990, 1993
34 *	The Regents of the University of California.  All rights reserved.
35 *
36 * This code is derived from software contributed to Berkeley by
37 * Van Jacobson.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 *    notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 *    notice, this list of conditions and the following disclaimer in the
46 *    documentation and/or other materials provided with the distribution.
47 * 4. Neither the name of the University nor the names of its contributors
48 *    may be used to endorse or promote products derived from this software
49 *    without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 */
63
64#ifndef lint
65static const char copyright[] =
66"@(#) Copyright (c) 1990, 1993\n\
67	The Regents of the University of California.  All rights reserved.\n";
68#endif /* not lint */
69
70#ifndef lint
71#if 0
72static char sccsid[] = "@(#)traceroute.c	8.1 (Berkeley) 6/6/93";
73#endif
74static const char rcsid[] =
75  "$FreeBSD: stable/11/usr.sbin/traceroute6/traceroute6.c 308714 2016-11-16 03:51:05Z hrs $";
76#endif /* not lint */
77
78/*
79 * traceroute host  - trace the route ip packets follow going to "host".
80 *
81 * Attempt to trace the route an ip packet would follow to some
82 * internet host.  We find out intermediate hops by launching probe
83 * packets with a small ttl (time to live) then listening for an
84 * icmp "time exceeded" reply from a gateway.  We start our probes
85 * with a ttl of one and increase by one until we get an icmp "port
86 * unreachable" (which means we got to "host") or hit a max (which
87 * defaults to 30 hops & can be changed with the -m flag).  Three
88 * probes (change with -q flag) are sent at each ttl setting and a
89 * line is printed showing the ttl, address of the gateway and
90 * round trip time of each probe.  If the probe answers come from
91 * different gateways, the address of each responding system will
92 * be printed.  If there is no response within a 5 sec. timeout
93 * interval (changed with the -w flag), a "*" is printed for that
94 * probe.
95 *
96 * Probe packets are UDP format.  We don't want the destination
97 * host to process them so the destination port is set to an
98 * unlikely value (if some clod on the destination is using that
99 * value, it can be changed with the -p flag).
100 *
101 * A sample use might be:
102 *
103 *     [yak 71]% traceroute nis.nsf.net.
104 *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
105 *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
106 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
107 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
108 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
109 *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
110 *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
111 *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
112 *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
113 *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
114 *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
115 *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
116 *
117 * Note that lines 2 & 3 are the same.  This is due to a buggy
118 * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
119 * packets with a zero ttl.
120 *
121 * A more interesting example is:
122 *
123 *     [yak 72]% traceroute allspice.lcs.mit.edu.
124 *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
125 *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
126 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
127 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
128 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
129 *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
130 *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
131 *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
132 *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
133 *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
134 *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
135 *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
136 *     12  * * *
137 *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
138 *     14  * * *
139 *     15  * * *
140 *     16  * * *
141 *     17  * * *
142 *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
143 *
144 * (I start to see why I'm having so much trouble with mail to
145 * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
146 * either don't send ICMP "time exceeded" messages or send them
147 * with a ttl too small to reach us.  14 - 17 are running the
148 * MIT C Gateway code that doesn't send "time exceeded"s.  God
149 * only knows what's going on with 12.
150 *
151 * The silent gateway 12 in the above may be the result of a bug in
152 * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
153 * sends an unreachable message using whatever ttl remains in the
154 * original datagram.  Since, for gateways, the remaining ttl is
155 * zero, the icmp "time exceeded" is guaranteed to not make it back
156 * to us.  The behavior of this bug is slightly more interesting
157 * when it appears on the destination system:
158 *
159 *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
160 *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
161 *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
162 *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
163 *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
164 *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
165 *      7  * * *
166 *      8  * * *
167 *      9  * * *
168 *     10  * * *
169 *     11  * * *
170 *     12  * * *
171 *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
172 *
173 * Notice that there are 12 "gateways" (13 is the final
174 * destination) and exactly the last half of them are "missing".
175 * What's really happening is that rip (a Sun-3 running Sun OS3.5)
176 * is using the ttl from our arriving datagram as the ttl in its
177 * icmp reply.  So, the reply will time out on the return path
178 * (with no notice sent to anyone since icmp's aren't sent for
179 * icmp's) until we probe with a ttl that's at least twice the path
180 * length.  I.e., rip is really only 7 hops away.  A reply that
181 * returns with a ttl of 1 is a clue this problem exists.
182 * Traceroute prints a "!" after the time if the ttl is <= 1.
183 * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
184 * non-standard (HPUX) software, expect to see this problem
185 * frequently and/or take care picking the target host of your
186 * probes.
187 *
188 * Other possible annotations after the time are !H, !N, !P (got a host,
189 * network or protocol unreachable, respectively), !S or !F (source
190 * route failed or fragmentation needed -- neither of these should
191 * ever occur and the associated gateway is busted if you see one).  If
192 * almost all the probes result in some kind of unreachable, traceroute
193 * will give up and exit.
194 *
195 * Notes
196 * -----
197 * This program must be run by root or be setuid.  (I suggest that
198 * you *don't* make it setuid -- casual use could result in a lot
199 * of unnecessary traffic on our poor, congested nets.)
200 *
201 * This program requires a kernel mod that does not appear in any
202 * system available from Berkeley:  A raw ip socket using proto
203 * IPPROTO_RAW must interpret the data sent as an ip datagram (as
204 * opposed to data to be wrapped in an ip datagram).  See the README
205 * file that came with the source to this program for a description
206 * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
207 * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
208 * MODIFIED TO RUN THIS PROGRAM.
209 *
210 * The udp port usage may appear bizarre (well, ok, it is bizarre).
211 * The problem is that an icmp message only contains 8 bytes of
212 * data from the original datagram.  8 bytes is the size of a udp
213 * header so, if we want to associate replies with the original
214 * datagram, the necessary information must be encoded into the
215 * udp header (the ip id could be used but there's no way to
216 * interlock with the kernel's assignment of ip id's and, anyway,
217 * it would have taken a lot more kernel hacking to allow this
218 * code to set the ip id).  So, to allow two or more users to
219 * use traceroute simultaneously, we use this task's pid as the
220 * source port (the high bit is set to move the port number out
221 * of the "likely" range).  To keep track of which probe is being
222 * replied to (so times and/or hop counts don't get confused by a
223 * reply that was delayed in transit), we increment the destination
224 * port number before each probe.
225 *
226 * Don't use this as a coding example.  I was trying to find a
227 * routing problem and this code sort-of popped out after 48 hours
228 * without sleep.  I was amazed it ever compiled, much less ran.
229 *
230 * I stole the idea for this program from Steve Deering.  Since
231 * the first release, I've learned that had I attended the right
232 * IETF working group meetings, I also could have stolen it from Guy
233 * Almes or Matt Mathis.  I don't know (or care) who came up with
234 * the idea first.  I envy the originators' perspicacity and I'm
235 * glad they didn't keep the idea a secret.
236 *
237 * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
238 * enhancements to the original distribution.
239 *
240 * I've hacked up a round-trip-route version of this that works by
241 * sending a loose-source-routed udp datagram through the destination
242 * back to yourself.  Unfortunately, SO many gateways botch source
243 * routing, the thing is almost worthless.  Maybe one day...
244 *
245 *  -- Van Jacobson (van@helios.ee.lbl.gov)
246 *     Tue Dec 20 03:50:13 PST 1988
247 */
248
249#include <sys/param.h>
250#include <sys/time.h>
251#include <sys/socket.h>
252#include <sys/uio.h>
253#include <sys/file.h>
254#include <sys/ioctl.h>
255#include <sys/sysctl.h>
256
257#include <netinet/in.h>
258
259#include <arpa/inet.h>
260
261#include <netdb.h>
262#include <stdio.h>
263#include <err.h>
264#ifdef HAVE_POLL
265#include <poll.h>
266#endif
267#include <errno.h>
268#include <stdlib.h>
269#include <string.h>
270#include <unistd.h>
271
272#include <netinet/ip6.h>
273#include <netinet/icmp6.h>
274#include <netinet/udp.h>
275
276#ifdef IPSEC
277#include <net/route.h>
278#include <netipsec/ipsec.h>
279#endif
280
281#include "as.h"
282
283#define DUMMY_PORT 10010
284
285#define	MAXPACKET	65535	/* max ip packet size */
286
287#ifndef HAVE_GETIPNODEBYNAME
288#define getipnodebyname(x, y, z, u)	gethostbyname2((x), (y))
289#define freehostent(x)
290#endif
291
292/*
293 * format of a (udp) probe packet.
294 */
295struct tv32 {
296	u_int32_t tv32_sec;
297	u_int32_t tv32_usec;
298};
299
300struct opacket {
301	u_char seq;		/* sequence number of this packet */
302	u_char hops;		/* hop limit of the packet */
303	u_char pad[2];
304	struct tv32 tv;		/* time packet left */
305} __attribute__((__packed__));
306
307u_char	packet[512];		/* last inbound (icmp) packet */
308struct opacket	*outpacket;	/* last output (udp) packet */
309
310int	main(int, char *[]);
311int	wait_for_reply(int, struct msghdr *);
312#ifdef IPSEC
313#ifdef IPSEC_POLICY_IPSEC
314int	setpolicy(int so, char *policy);
315#endif
316#endif
317void	send_probe(int, u_long);
318void	*get_uphdr(struct ip6_hdr *, u_char *);
319int	get_hoplim(struct msghdr *);
320double	deltaT(struct timeval *, struct timeval *);
321const char *pr_type(int);
322int	packet_ok(struct msghdr *, int, int);
323void	print(struct msghdr *, int);
324const char *inetname(struct sockaddr *);
325void	usage(void);
326
327int rcvsock;			/* receive (icmp) socket file descriptor */
328int sndsock;			/* send (udp) socket file descriptor */
329
330struct msghdr rcvmhdr;
331struct iovec rcviov[2];
332int rcvhlim;
333struct in6_pktinfo *rcvpktinfo;
334
335struct sockaddr_in6 Src, Dst, Rcv;
336u_long datalen;			/* How much data */
337#define	ICMP6ECHOLEN	8
338/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
339char rtbuf[2064];
340#ifdef USE_RFC2292BIS
341struct ip6_rthdr *rth;
342#endif
343struct cmsghdr *cmsg;
344
345char *source = NULL;
346char *hostname;
347
348u_long nprobes = 3;
349u_long first_hop = 1;
350u_long max_hops = 30;
351u_int16_t srcport;
352u_int16_t port = 32768+666;	/* start udp dest port # for probe packets */
353u_int16_t ident;
354int options;			/* socket options */
355int verbose;
356int waittime = 5;		/* time to wait for response (in seconds) */
357int nflag;			/* print addresses numerically */
358int useproto = IPPROTO_UDP;	/* protocol to use to send packet */
359int lflag;			/* print both numerical address & hostname */
360int as_path;			/* print as numbers for each hop */
361char *as_server = NULL;
362void *asn;
363
364int
365main(argc, argv)
366	int argc;
367	char *argv[];
368{
369	int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
370	char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
371	int ch, i, on = 1, seq, rcvcmsglen, error;
372	struct addrinfo hints, *res;
373	static u_char *rcvcmsgbuf;
374	u_long probe, hops, lport;
375	struct hostent *hp;
376	size_t size, minlen;
377	uid_t uid;
378
379	/*
380	 * Receive ICMP
381	 */
382	if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
383		perror("socket(ICMPv6)");
384		exit(5);
385	}
386
387	size = sizeof(i);
388	(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0);
389	max_hops = i;
390
391	/* specify to tell receiving interface */
392#ifdef IPV6_RECVPKTINFO
393	if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
394	    sizeof(on)) < 0)
395		err(1, "setsockopt(IPV6_RECVPKTINFO)");
396#else  /* old adv. API */
397	if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
398	    sizeof(on)) < 0)
399		err(1, "setsockopt(IPV6_PKTINFO)");
400#endif
401
402	/* specify to tell value of hoplimit field of received IP6 hdr */
403#ifdef IPV6_RECVHOPLIMIT
404	if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
405	    sizeof(on)) < 0)
406		err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
407#else  /* old adv. API */
408	if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
409	    sizeof(on)) < 0)
410		err(1, "setsockopt(IPV6_HOPLIMIT)");
411#endif
412
413	seq = 0;
414
415	while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:Uvw:")) != -1)
416		switch (ch) {
417		case 'a':
418			as_path = 1;
419			break;
420		case 'A':
421			as_path = 1;
422			as_server = optarg;
423			break;
424		case 'd':
425			options |= SO_DEBUG;
426			break;
427		case 'f':
428			ep = NULL;
429			errno = 0;
430			first_hop = strtoul(optarg, &ep, 0);
431			if (errno || !*optarg || *ep || first_hop > 255) {
432				fprintf(stderr,
433				    "traceroute6: invalid min hoplimit.\n");
434				exit(1);
435			}
436			break;
437		case 'g':
438			hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
439			if (hp == NULL) {
440				fprintf(stderr,
441				    "traceroute6: unknown host %s\n", optarg);
442				exit(1);
443			}
444#ifdef USE_RFC2292BIS
445			if (rth == NULL) {
446				/*
447				 * XXX: We can't detect the number of
448				 * intermediate nodes yet.
449				 */
450				if ((rth = inet6_rth_init((void *)rtbuf,
451				    sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
452				    0)) == NULL) {
453					fprintf(stderr,
454					    "inet6_rth_init failed.\n");
455					exit(1);
456				}
457			}
458			if (inet6_rth_add((void *)rth,
459			    (struct in6_addr *)hp->h_addr)) {
460				fprintf(stderr,
461				    "inet6_rth_add failed for %s\n",
462				    optarg);
463				exit(1);
464			}
465#else  /* old advanced API */
466			if (cmsg == NULL)
467				cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0);
468			inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr,
469			    IPV6_RTHDR_LOOSE);
470#endif
471			freehostent(hp);
472			break;
473		case 'I':
474			useproto = IPPROTO_ICMPV6;
475			ident = htons(getpid() & 0xffff); /* same as ping6 */
476			break;
477		case 'l':
478			lflag++;
479			break;
480		case 'm':
481			ep = NULL;
482			errno = 0;
483			max_hops = strtoul(optarg, &ep, 0);
484			if (errno || !*optarg || *ep || max_hops > 255) {
485				fprintf(stderr,
486				    "traceroute6: invalid max hoplimit.\n");
487				exit(1);
488			}
489			break;
490		case 'n':
491			nflag++;
492			break;
493		case 'N':
494			useproto = IPPROTO_NONE;
495			break;
496		case 'p':
497			ep = NULL;
498			errno = 0;
499			lport = strtoul(optarg, &ep, 0);
500			if (errno || !*optarg || *ep) {
501				fprintf(stderr, "traceroute6: invalid port.\n");
502				exit(1);
503			}
504			if (lport == 0 || lport != (lport & 0xffff)) {
505				fprintf(stderr,
506				    "traceroute6: port out of range.\n");
507				exit(1);
508			}
509			port = lport & 0xffff;
510			break;
511		case 'q':
512			ep = NULL;
513			errno = 0;
514			nprobes = strtoul(optarg, &ep, 0);
515			if (errno || !*optarg || *ep) {
516				fprintf(stderr,
517				    "traceroute6: invalid nprobes.\n");
518				exit(1);
519			}
520			if (nprobes < 1) {
521				fprintf(stderr,
522				    "traceroute6: nprobes must be >0.\n");
523				exit(1);
524			}
525			break;
526		case 'r':
527			options |= SO_DONTROUTE;
528			break;
529		case 's':
530			/*
531			 * set the ip source address of the outbound
532			 * probe (e.g., on a multi-homed host).
533			 */
534			source = optarg;
535			break;
536		case 'v':
537			verbose++;
538			break;
539		case 'U':
540			useproto = IPPROTO_UDP;
541			break;
542		case 'w':
543			ep = NULL;
544			errno = 0;
545			waittime = strtoul(optarg, &ep, 0);
546			if (errno || !*optarg || *ep) {
547				fprintf(stderr,
548				    "traceroute6: invalid wait time.\n");
549				exit(1);
550			}
551			if (waittime < 1) {
552				fprintf(stderr,
553				    "traceroute6: wait must be >= 1 sec.\n");
554				exit(1);
555			}
556			break;
557		default:
558			usage();
559		}
560	argc -= optind;
561	argv += optind;
562
563	/*
564	 * Open socket to send probe packets.
565	 */
566	switch (useproto) {
567	case IPPROTO_ICMPV6:
568		sndsock = rcvsock;
569		break;
570	case IPPROTO_UDP:
571		if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
572			perror("socket(SOCK_DGRAM)");
573			exit(5);
574		}
575		break;
576	case IPPROTO_NONE:
577        	if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
578			perror("socket(SOCK_RAW)");
579			exit(5);
580		}
581		break;
582	default:
583		fprintf(stderr, "traceroute6: unknown probe protocol %d",
584		    useproto);
585		exit(5);
586	}
587	if (max_hops < first_hop) {
588		fprintf(stderr,
589		    "traceroute6: max hoplimit must be larger than first hoplimit.\n");
590		exit(1);
591	}
592
593	/* revoke privs */
594	uid = getuid();
595	if (setresuid(uid, uid, uid) == -1) {
596		perror("setresuid");
597		exit(1);
598	}
599
600
601	if (argc < 1 || argc > 2)
602		usage();
603
604#if 1
605	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
606#else
607	setlinebuf(stdout);
608#endif
609
610	memset(&hints, 0, sizeof(hints));
611	hints.ai_family = PF_INET6;
612	hints.ai_socktype = SOCK_RAW;
613	hints.ai_protocol = IPPROTO_ICMPV6;
614	hints.ai_flags = AI_CANONNAME;
615	error = getaddrinfo(*argv, NULL, &hints, &res);
616	if (error) {
617		fprintf(stderr,
618		    "traceroute6: %s\n", gai_strerror(error));
619		exit(1);
620	}
621	if (res->ai_addrlen != sizeof(Dst)) {
622		fprintf(stderr,
623		    "traceroute6: size of sockaddr mismatch\n");
624		exit(1);
625	}
626	memcpy(&Dst, res->ai_addr, res->ai_addrlen);
627	hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
628	if (!hostname) {
629		fprintf(stderr, "traceroute6: not enough core\n");
630		exit(1);
631	}
632	if (res->ai_next) {
633		if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
634		    sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
635			strlcpy(hbuf, "?", sizeof(hbuf));
636		fprintf(stderr, "traceroute6: Warning: %s has multiple "
637		    "addresses; using %s\n", hostname, hbuf);
638	}
639
640	if (*++argv) {
641		ep = NULL;
642		errno = 0;
643		datalen = strtoul(*argv, &ep, 0);
644		if (errno || !*argv || *ep) {
645			fprintf(stderr,
646			    "traceroute6: invalid packet length.\n");
647			exit(1);
648		}
649	}
650	switch (useproto) {
651	case IPPROTO_ICMPV6:
652		minlen = ICMP6ECHOLEN + sizeof(struct tv32);
653		break;
654	case IPPROTO_UDP:
655		minlen = sizeof(struct opacket);
656		break;
657	case IPPROTO_NONE:
658		minlen = 0;
659		datalen = 0;
660		break;
661	default:
662		fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
663		    useproto);
664		exit(1);
665	}
666	if (datalen < minlen)
667		datalen = minlen;
668	else if (datalen >= MAXPACKET) {
669		fprintf(stderr,
670		    "traceroute6: packet size must be %zu <= s < %d.\n",
671		    minlen, MAXPACKET);
672		exit(1);
673	}
674	outpacket = malloc(datalen);
675	if (!outpacket) {
676		perror("malloc");
677		exit(1);
678	}
679	(void) bzero((char *)outpacket, datalen);
680
681	/* initialize msghdr for receiving packets */
682	rcviov[0].iov_base = (caddr_t)packet;
683	rcviov[0].iov_len = sizeof(packet);
684	rcvmhdr.msg_name = (caddr_t)&Rcv;
685	rcvmhdr.msg_namelen = sizeof(Rcv);
686	rcvmhdr.msg_iov = rcviov;
687	rcvmhdr.msg_iovlen = 1;
688	rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
689	    CMSG_SPACE(sizeof(int));
690	if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
691		fprintf(stderr, "traceroute6: malloc failed\n");
692		exit(1);
693	}
694	rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
695	rcvmhdr.msg_controllen = rcvcmsglen;
696
697	if (options & SO_DEBUG)
698		(void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
699		    (char *)&on, sizeof(on));
700	if (options & SO_DONTROUTE)
701		(void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
702		    (char *)&on, sizeof(on));
703#ifdef IPSEC
704#ifdef IPSEC_POLICY_IPSEC
705	/*
706	 * do not raise error even if setsockopt fails, kernel may have ipsec
707	 * turned off.
708	 */
709	if (setpolicy(rcvsock, "in bypass") < 0)
710		errx(1, "%s", ipsec_strerror());
711	if (setpolicy(rcvsock, "out bypass") < 0)
712		errx(1, "%s", ipsec_strerror());
713#else
714    {
715	int level = IPSEC_LEVEL_NONE;
716
717	(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
718	    sizeof(level));
719	(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
720	    sizeof(level));
721#ifdef IP_AUTH_TRANS_LEVEL
722	(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
723	    sizeof(level));
724#else
725	(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
726	    sizeof(level));
727#endif
728#ifdef IP_AUTH_NETWORK_LEVEL
729	(void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
730	    sizeof(level));
731#endif
732    }
733#endif /*IPSEC_POLICY_IPSEC*/
734#endif /*IPSEC*/
735
736#ifdef SO_SNDBUF
737	i = datalen;
738	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
739	    sizeof(i)) < 0 && useproto != IPPROTO_NONE) {
740		perror("setsockopt(SO_SNDBUF)");
741		exit(6);
742	}
743#endif /* SO_SNDBUF */
744	if (options & SO_DEBUG)
745		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
746		    (char *)&on, sizeof(on));
747	if (options & SO_DONTROUTE)
748		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
749		    (char *)&on, sizeof(on));
750#ifdef USE_RFC2292BIS
751	if (rth) {/* XXX: there is no library to finalize the header... */
752		rth->ip6r_len = rth->ip6r_segleft * 2;
753		if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
754		    (void *)rth, (rth->ip6r_len + 1) << 3)) {
755			fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
756			    strerror(errno));
757			exit(1);
758		}
759	}
760#else  /* old advanced API */
761	if (cmsg != NULL) {
762		inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
763		if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
764		    rtbuf, cmsg->cmsg_len) < 0) {
765			fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n",
766			    strerror(errno));
767			exit(1);
768		}
769	}
770#endif /* USE_RFC2292BIS */
771#ifdef IPSEC
772#ifdef IPSEC_POLICY_IPSEC
773	/*
774	 * do not raise error even if setsockopt fails, kernel may have ipsec
775	 * turned off.
776	 */
777	if (setpolicy(sndsock, "in bypass") < 0)
778		errx(1, "%s", ipsec_strerror());
779	if (setpolicy(sndsock, "out bypass") < 0)
780		errx(1, "%s", ipsec_strerror());
781#else
782    {
783	int level = IPSEC_LEVEL_BYPASS;
784
785	(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
786	    sizeof(level));
787	(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
788	    sizeof(level));
789#ifdef IP_AUTH_TRANS_LEVEL
790	(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
791	    sizeof(level));
792#else
793	(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
794	    sizeof(level));
795#endif
796#ifdef IP_AUTH_NETWORK_LEVEL
797	(void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
798	    sizeof(level));
799#endif
800    }
801#endif /*IPSEC_POLICY_IPSEC*/
802#endif /*IPSEC*/
803
804	/*
805	 * Source selection
806	 */
807	bzero(&Src, sizeof(Src));
808	if (source) {
809		struct addrinfo hints, *res;
810		int error;
811
812		memset(&hints, 0, sizeof(hints));
813		hints.ai_family = AF_INET6;
814		hints.ai_socktype = SOCK_DGRAM;	/*dummy*/
815		hints.ai_flags = AI_NUMERICHOST;
816		error = getaddrinfo(source, "0", &hints, &res);
817		if (error) {
818			printf("traceroute6: %s: %s\n", source,
819			    gai_strerror(error));
820			exit(1);
821		}
822		if (res->ai_addrlen > sizeof(Src)) {
823			printf("traceroute6: %s: %s\n", source,
824			    gai_strerror(error));
825			exit(1);
826		}
827		memcpy(&Src, res->ai_addr, res->ai_addrlen);
828		freeaddrinfo(res);
829	} else {
830		struct sockaddr_in6 Nxt;
831		int dummy;
832		socklen_t len;
833
834		Nxt = Dst;
835		Nxt.sin6_port = htons(DUMMY_PORT);
836		if (cmsg != NULL)
837			bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
838			    sizeof(Nxt.sin6_addr));
839		if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
840			perror("socket");
841			exit(1);
842		}
843		if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
844			perror("connect");
845			exit(1);
846		}
847		len = sizeof(Src);
848		if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
849			perror("getsockname");
850			exit(1);
851		}
852		if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len,
853		    src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) {
854			fprintf(stderr, "getnameinfo failed for source\n");
855			exit(1);
856		}
857		source = src0;
858		close(dummy);
859	}
860
861	Src.sin6_port = htons(0);
862	if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
863		perror("bind");
864		exit(1);
865	}
866
867	{
868		socklen_t len;
869
870		len = sizeof(Src);
871		if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
872			perror("getsockname");
873			exit(1);
874		}
875		srcport = ntohs(Src.sin6_port);
876	}
877
878	if (as_path) {
879		asn = as_setup(as_server);
880		if (asn == NULL) {
881			fprintf(stderr,
882			    "traceroute6: as_setup failed, AS# lookups"
883			    " disabled\n");
884			(void)fflush(stderr);
885			as_path = 0;
886		}
887	}
888
889	/*
890	 * Message to users
891	 */
892	if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
893	    sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
894		strlcpy(hbuf, "(invalid)", sizeof(hbuf));
895	fprintf(stderr, "traceroute6");
896	fprintf(stderr, " to %s (%s)", hostname, hbuf);
897	if (source)
898		fprintf(stderr, " from %s", source);
899	fprintf(stderr, ", %lu hops max, %lu byte packets\n",
900	    max_hops, datalen);
901	(void) fflush(stderr);
902
903	if (first_hop > 1)
904		printf("Skipping %lu intermediate hops\n", first_hop - 1);
905
906	/*
907	 * Main loop
908	 */
909	for (hops = first_hop; hops <= max_hops; ++hops) {
910		struct in6_addr lastaddr;
911		int got_there = 0;
912		unsigned unreachable = 0;
913
914		printf("%2lu ", hops);
915		bzero(&lastaddr, sizeof(lastaddr));
916		for (probe = 0; probe < nprobes; ++probe) {
917			int cc;
918			struct timeval t1, t2;
919
920			(void) gettimeofday(&t1, NULL);
921			send_probe(++seq, hops);
922			while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
923				(void) gettimeofday(&t2, NULL);
924				if ((i = packet_ok(&rcvmhdr, cc, seq))) {
925					if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
926					    &lastaddr)) {
927						if (probe > 0)
928							fputs("\n   ", stdout);
929						print(&rcvmhdr, cc);
930						lastaddr = Rcv.sin6_addr;
931					}
932					printf("  %.3f ms", deltaT(&t1, &t2));
933					switch (i - 1) {
934					case ICMP6_DST_UNREACH_NOROUTE:
935						++unreachable;
936						printf(" !N");
937						break;
938					case ICMP6_DST_UNREACH_ADMIN:
939						++unreachable;
940						printf(" !P");
941						break;
942					case ICMP6_DST_UNREACH_NOTNEIGHBOR:
943						++unreachable;
944						printf(" !S");
945						break;
946					case ICMP6_DST_UNREACH_ADDR:
947						++unreachable;
948						printf(" !A");
949						break;
950					case ICMP6_DST_UNREACH_NOPORT:
951						if (rcvhlim >= 0 &&
952						    rcvhlim <= 1)
953							printf(" !");
954						++got_there;
955						break;
956					}
957					break;
958				} else if (deltaT(&t1, &t2) > waittime * 1000) {
959					cc = 0;
960					break;
961				}
962			}
963			if (cc == 0)
964				printf(" *");
965			(void) fflush(stdout);
966		}
967		putchar('\n');
968		if (got_there ||
969		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
970			exit(0);
971		}
972	}
973	if (as_path)
974		as_shutdown(asn);
975
976	exit(0);
977}
978
979int
980wait_for_reply(sock, mhdr)
981	int sock;
982	struct msghdr *mhdr;
983{
984#ifdef HAVE_POLL
985	struct pollfd pfd[1];
986	int cc = 0;
987
988	pfd[0].fd = sock;
989	pfd[0].events = POLLIN;
990	pfd[0].revents = 0;
991
992	if (poll(pfd, 1, waittime * 1000) > 0)
993		cc = recvmsg(rcvsock, mhdr, 0);
994
995	return(cc);
996#else
997	fd_set *fdsp;
998	struct timeval wait;
999	int cc = 0, fdsn;
1000
1001	fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1002	if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1003		err(1, "malloc");
1004	memset(fdsp, 0, fdsn);
1005	FD_SET(sock, fdsp);
1006	wait.tv_sec = waittime; wait.tv_usec = 0;
1007
1008	if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1009		cc = recvmsg(rcvsock, mhdr, 0);
1010
1011	free(fdsp);
1012	return(cc);
1013#endif
1014}
1015
1016#ifdef IPSEC
1017#ifdef IPSEC_POLICY_IPSEC
1018int
1019setpolicy(so, policy)
1020	int so;
1021	char *policy;
1022{
1023	char *buf;
1024
1025	buf = ipsec_set_policy(policy, strlen(policy));
1026	if (buf == NULL) {
1027		warnx("%s", ipsec_strerror());
1028		return -1;
1029	}
1030	(void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1031	    buf, ipsec_get_policylen(buf));
1032
1033	free(buf);
1034
1035	return 0;
1036}
1037#endif
1038#endif
1039
1040void
1041send_probe(seq, hops)
1042	int seq;
1043	u_long hops;
1044{
1045	struct icmp6_hdr *icp;
1046	struct opacket *op;
1047	struct timeval tv;
1048	struct tv32 tv32;
1049	int i;
1050
1051	i = hops;
1052	if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1053	    (char *)&i, sizeof(i)) < 0) {
1054		perror("setsockopt IPV6_UNICAST_HOPS");
1055	}
1056
1057	Dst.sin6_port = htons(port + seq);
1058	(void) gettimeofday(&tv, NULL);
1059	tv32.tv32_sec = htonl(tv.tv_sec);
1060	tv32.tv32_usec = htonl(tv.tv_usec);
1061
1062	switch (useproto) {
1063	case IPPROTO_ICMPV6:
1064		icp = (struct icmp6_hdr *)outpacket;
1065
1066		icp->icmp6_type = ICMP6_ECHO_REQUEST;
1067		icp->icmp6_code = 0;
1068		icp->icmp6_cksum = 0;
1069		icp->icmp6_id = ident;
1070		icp->icmp6_seq = htons(seq);
1071		bcopy(&tv32, ((u_int8_t *)outpacket + ICMP6ECHOLEN),
1072		    sizeof(tv32));
1073		break;
1074	case IPPROTO_UDP:
1075		op = outpacket;
1076
1077		op->seq = seq;
1078		op->hops = hops;
1079		bcopy(&tv32, &op->tv, sizeof tv32);
1080		break;
1081	case IPPROTO_NONE:
1082		/* No space for anything. No harm as seq/tv32 are decorative. */
1083		break;
1084	default:
1085		fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1086		exit(1);
1087	}
1088
1089	i = sendto(sndsock, (char *)outpacket, datalen, 0,
1090	    (struct sockaddr *)&Dst, Dst.sin6_len);
1091	if (i < 0 || (u_long)i != datalen)  {
1092		if (i < 0)
1093			perror("sendto");
1094		printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1095		    hostname, datalen, i);
1096		(void) fflush(stdout);
1097	}
1098}
1099
1100int
1101get_hoplim(mhdr)
1102	struct msghdr *mhdr;
1103{
1104	struct cmsghdr *cm;
1105
1106	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1107	    cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1108		if (cm->cmsg_level == IPPROTO_IPV6 &&
1109		    cm->cmsg_type == IPV6_HOPLIMIT &&
1110		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
1111			return(*(int *)CMSG_DATA(cm));
1112	}
1113
1114	return(-1);
1115}
1116
1117double
1118deltaT(t1p, t2p)
1119	struct timeval *t1p, *t2p;
1120{
1121	double dt;
1122
1123	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1124	    (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1125	return (dt);
1126}
1127
1128/*
1129 * Convert an ICMP "type" field to a printable string.
1130 */
1131const char *
1132pr_type(int t0)
1133{
1134	u_char t = t0 & 0xff;
1135	const char *cp;
1136
1137	switch (t) {
1138	case ICMP6_DST_UNREACH:
1139		cp = "Destination Unreachable";
1140		break;
1141	case ICMP6_PACKET_TOO_BIG:
1142		cp = "Packet Too Big";
1143		break;
1144	case ICMP6_TIME_EXCEEDED:
1145		cp = "Time Exceeded";
1146		break;
1147	case ICMP6_PARAM_PROB:
1148		cp = "Parameter Problem";
1149		break;
1150	case ICMP6_ECHO_REQUEST:
1151		cp = "Echo Request";
1152		break;
1153	case ICMP6_ECHO_REPLY:
1154		cp = "Echo Reply";
1155		break;
1156	case ICMP6_MEMBERSHIP_QUERY:
1157		cp = "Group Membership Query";
1158		break;
1159	case ICMP6_MEMBERSHIP_REPORT:
1160		cp = "Group Membership Report";
1161		break;
1162	case ICMP6_MEMBERSHIP_REDUCTION:
1163		cp = "Group Membership Reduction";
1164		break;
1165	case ND_ROUTER_SOLICIT:
1166		cp = "Router Solicitation";
1167		break;
1168	case ND_ROUTER_ADVERT:
1169		cp = "Router Advertisement";
1170		break;
1171	case ND_NEIGHBOR_SOLICIT:
1172		cp = "Neighbor Solicitation";
1173		break;
1174	case ND_NEIGHBOR_ADVERT:
1175		cp = "Neighbor Advertisement";
1176		break;
1177	case ND_REDIRECT:
1178		cp = "Redirect";
1179		break;
1180	default:
1181		cp = "Unknown";
1182		break;
1183	}
1184	return cp;
1185}
1186
1187int
1188packet_ok(mhdr, cc, seq)
1189	struct msghdr *mhdr;
1190	int cc;
1191	int seq;
1192{
1193	struct icmp6_hdr *icp;
1194	struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1195	u_char type, code;
1196	char *buf = (char *)mhdr->msg_iov[0].iov_base;
1197	struct cmsghdr *cm;
1198	int *hlimp;
1199	char hbuf[NI_MAXHOST];
1200
1201#ifdef OLDRAWSOCKET
1202	int hlen;
1203	struct ip6_hdr *ip;
1204#endif
1205
1206#ifdef OLDRAWSOCKET
1207	ip = (struct ip6_hdr *) buf;
1208	hlen = sizeof(struct ip6_hdr);
1209	if (cc < hlen + sizeof(struct icmp6_hdr)) {
1210		if (verbose) {
1211			if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1212			    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1213				strlcpy(hbuf, "invalid", sizeof(hbuf));
1214			printf("packet too short (%d bytes) from %s\n", cc,
1215			    hbuf);
1216		}
1217		return (0);
1218	}
1219	cc -= hlen;
1220	icp = (struct icmp6_hdr *)(buf + hlen);
1221#else
1222	if (cc < (int)sizeof(struct icmp6_hdr)) {
1223		if (verbose) {
1224			if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1225			    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1226				strlcpy(hbuf, "invalid", sizeof(hbuf));
1227			printf("data too short (%d bytes) from %s\n", cc, hbuf);
1228		}
1229		return(0);
1230	}
1231	icp = (struct icmp6_hdr *)buf;
1232#endif
1233	/* get optional information via advanced API */
1234	rcvpktinfo = NULL;
1235	hlimp = NULL;
1236	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1237	    cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1238		if (cm->cmsg_level == IPPROTO_IPV6 &&
1239		    cm->cmsg_type == IPV6_PKTINFO &&
1240		    cm->cmsg_len ==
1241		    CMSG_LEN(sizeof(struct in6_pktinfo)))
1242			rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1243
1244		if (cm->cmsg_level == IPPROTO_IPV6 &&
1245		    cm->cmsg_type == IPV6_HOPLIMIT &&
1246		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
1247			hlimp = (int *)CMSG_DATA(cm);
1248	}
1249	if (rcvpktinfo == NULL || hlimp == NULL) {
1250		warnx("failed to get received hop limit or packet info");
1251#if 0
1252		return(0);
1253#else
1254		rcvhlim = 0;	/*XXX*/
1255#endif
1256	}
1257	else
1258		rcvhlim = *hlimp;
1259
1260	type = icp->icmp6_type;
1261	code = icp->icmp6_code;
1262	if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
1263	    || type == ICMP6_DST_UNREACH) {
1264		struct ip6_hdr *hip;
1265		void *up;
1266
1267		hip = (struct ip6_hdr *)(icp + 1);
1268		if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1269			if (verbose)
1270				warnx("failed to get upper layer header");
1271			return(0);
1272		}
1273		switch (useproto) {
1274		case IPPROTO_ICMPV6:
1275			if (((struct icmp6_hdr *)up)->icmp6_id == ident &&
1276			    ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq))
1277				return (type == ICMP6_TIME_EXCEEDED ?
1278				    -1 : code + 1);
1279			break;
1280		case IPPROTO_UDP:
1281			if (((struct udphdr *)up)->uh_sport == htons(srcport) &&
1282			    ((struct udphdr *)up)->uh_dport == htons(port + seq))
1283				return (type == ICMP6_TIME_EXCEEDED ?
1284				    -1 : code + 1);
1285			break;
1286		case IPPROTO_NONE:
1287			return (type == ICMP6_TIME_EXCEEDED ?  -1 : code + 1);
1288		default:
1289			fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1290			break;
1291		}
1292	} else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) {
1293		if (icp->icmp6_id == ident &&
1294		    icp->icmp6_seq == htons(seq))
1295			return (ICMP6_DST_UNREACH_NOPORT + 1);
1296	}
1297	if (verbose) {
1298		char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
1299		u_int8_t *p;
1300		int i;
1301
1302		if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1303		    sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1304			strlcpy(sbuf, "invalid", sizeof(sbuf));
1305		printf("\n%d bytes from %s to %s", cc, sbuf,
1306		    rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1307		    dbuf, sizeof(dbuf)) : "?");
1308		printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
1309		    icp->icmp6_code);
1310		p = (u_int8_t *)(icp + 1);
1311#define WIDTH	16
1312		for (i = 0; i < cc; i++) {
1313			if (i % WIDTH == 0)
1314				printf("%04x:", i);
1315			if (i % 4 == 0)
1316				printf(" ");
1317			printf("%02x", p[i]);
1318			if (i % WIDTH == WIDTH - 1)
1319				printf("\n");
1320		}
1321		if (cc % WIDTH != 0)
1322			printf("\n");
1323	}
1324	return(0);
1325}
1326
1327/*
1328 * Increment pointer until find the UDP or ICMP header.
1329 */
1330void *
1331get_uphdr(ip6, lim)
1332	struct ip6_hdr *ip6;
1333	u_char *lim;
1334{
1335	u_char *cp = (u_char *)ip6, nh;
1336	int hlen;
1337	static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1338
1339	if (cp + sizeof(*ip6) > lim)
1340		return(NULL);
1341
1342	nh = ip6->ip6_nxt;
1343	cp += sizeof(struct ip6_hdr);
1344
1345	while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1346		switch (nh) {
1347		case IPPROTO_ESP:
1348		case IPPROTO_TCP:
1349			return(NULL);
1350		case IPPROTO_ICMPV6:
1351			return(useproto == nh ? cp : NULL);
1352		case IPPROTO_UDP:
1353			return(useproto == nh ? cp : NULL);
1354		case IPPROTO_NONE:
1355			return(useproto == nh ? none_hdr : NULL);
1356		case IPPROTO_FRAGMENT:
1357			hlen = sizeof(struct ip6_frag);
1358			nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1359			break;
1360		case IPPROTO_AH:
1361			hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1362			nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1363			break;
1364		default:
1365			hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1366			nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1367			break;
1368		}
1369
1370		cp += hlen;
1371	}
1372
1373	return(NULL);
1374}
1375
1376void
1377print(mhdr, cc)
1378	struct msghdr *mhdr;
1379	int cc;
1380{
1381	struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1382	char hbuf[NI_MAXHOST];
1383
1384	if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1385	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1386		strlcpy(hbuf, "invalid", sizeof(hbuf));
1387	if (as_path)
1388		printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1389	if (nflag)
1390		printf(" %s", hbuf);
1391	else if (lflag)
1392		printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1393	else
1394		printf(" %s", inetname((struct sockaddr *)from));
1395
1396	if (verbose) {
1397#ifdef OLDRAWSOCKET
1398		printf(" %d bytes to %s", cc,
1399		    rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1400		    hbuf, sizeof(hbuf)) : "?");
1401#else
1402		printf(" %d bytes of data to %s", cc,
1403		    rcvpktinfo ?  inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1404		    hbuf, sizeof(hbuf)) : "?");
1405#endif
1406	}
1407}
1408
1409/*
1410 * Construct an Internet address representation.
1411 * If the nflag has been supplied, give
1412 * numeric value, otherwise try for symbolic name.
1413 */
1414const char *
1415inetname(sa)
1416	struct sockaddr *sa;
1417{
1418	static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1419	static int first = 1;
1420	char *cp;
1421
1422	if (first && !nflag) {
1423		first = 0;
1424		if (gethostname(domain, sizeof(domain)) == 0 &&
1425		    (cp = strchr(domain, '.')))
1426			(void) strlcpy(domain, cp + 1, sizeof(domain));
1427		else
1428			domain[0] = 0;
1429	}
1430	cp = NULL;
1431	if (!nflag) {
1432		if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1433		    NI_NAMEREQD) == 0) {
1434			if ((cp = strchr(line, '.')) &&
1435			    !strcmp(cp + 1, domain))
1436				*cp = 0;
1437			cp = line;
1438		}
1439	}
1440	if (cp)
1441		return cp;
1442
1443	if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1444	    NI_NUMERICHOST) != 0)
1445		strlcpy(line, "invalid", sizeof(line));
1446	return line;
1447}
1448
1449void
1450usage()
1451{
1452
1453	fprintf(stderr,
1454"usage: traceroute6 [-adIlnNrUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1455"       [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"
1456"       [datalen]\n");
1457	exit(1);
1458}
1459