]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/traceroute6/traceroute6.c
Add two missing eventhandler.h headers
[FreeBSD/FreeBSD.git] / usr.sbin / traceroute6 / traceroute6.c
1 /*      $KAME: traceroute6.c,v 1.68 2004/01/25 11:16:12 suz Exp $       */
2
3 /*-
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*-
35  * Copyright (c) 1990, 1993
36  *      The Regents of the University of California.  All rights reserved.
37  *
38  * This code is derived from software contributed to Berkeley by
39  * Van Jacobson.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  */
65
66 #ifndef lint
67 static const char copyright[] =
68 "@(#) Copyright (c) 1990, 1993\n\
69         The Regents of the University of California.  All rights reserved.\n";
70 #endif /* not lint */
71
72 #ifndef lint
73 #if 0
74 static char sccsid[] = "@(#)traceroute.c        8.1 (Berkeley) 6/6/93";
75 #endif
76 static const char rcsid[] =
77   "$FreeBSD$";
78 #endif /* not lint */
79
80 /*
81  * traceroute host  - trace the route ip packets follow going to "host".
82  *
83  * Attempt to trace the route an ip packet would follow to some
84  * internet host.  We find out intermediate hops by launching probe
85  * packets with a small ttl (time to live) then listening for an
86  * icmp "time exceeded" reply from a gateway.  We start our probes
87  * with a ttl of one and increase by one until we get an icmp "port
88  * unreachable" (which means we got to "host") or hit a max (which
89  * defaults to 30 hops & can be changed with the -m flag).  Three
90  * probes (change with -q flag) are sent at each ttl setting and a
91  * line is printed showing the ttl, address of the gateway and
92  * round trip time of each probe.  If the probe answers come from
93  * different gateways, the address of each responding system will
94  * be printed.  If there is no response within a 5 sec. timeout
95  * interval (changed with the -w flag), a "*" is printed for that
96  * probe.
97  *
98  * Probe packets are UDP format.  We don't want the destination
99  * host to process them so the destination port is set to an
100  * unlikely value (if some clod on the destination is using that
101  * value, it can be changed with the -p flag).
102  *
103  * A sample use might be:
104  *
105  *     [yak 71]% traceroute nis.nsf.net.
106  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
107  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
108  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
109  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
110  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
111  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
112  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
113  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
114  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
115  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
116  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
117  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
118  *
119  * Note that lines 2 & 3 are the same.  This is due to a buggy
120  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
121  * packets with a zero ttl.
122  *
123  * A more interesting example is:
124  *
125  *     [yak 72]% traceroute allspice.lcs.mit.edu.
126  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
127  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
128  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
129  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
130  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
131  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
132  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
133  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
134  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
135  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
136  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
137  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
138  *     12  * * *
139  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
140  *     14  * * *
141  *     15  * * *
142  *     16  * * *
143  *     17  * * *
144  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
145  *
146  * (I start to see why I'm having so much trouble with mail to
147  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
148  * either don't send ICMP "time exceeded" messages or send them
149  * with a ttl too small to reach us.  14 - 17 are running the
150  * MIT C Gateway code that doesn't send "time exceeded"s.  God
151  * only knows what's going on with 12.
152  *
153  * The silent gateway 12 in the above may be the result of a bug in
154  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
155  * sends an unreachable message using whatever ttl remains in the
156  * original datagram.  Since, for gateways, the remaining ttl is
157  * zero, the icmp "time exceeded" is guaranteed to not make it back
158  * to us.  The behavior of this bug is slightly more interesting
159  * when it appears on the destination system:
160  *
161  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
162  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
163  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
164  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
165  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
166  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
167  *      7  * * *
168  *      8  * * *
169  *      9  * * *
170  *     10  * * *
171  *     11  * * *
172  *     12  * * *
173  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
174  *
175  * Notice that there are 12 "gateways" (13 is the final
176  * destination) and exactly the last half of them are "missing".
177  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
178  * is using the ttl from our arriving datagram as the ttl in its
179  * icmp reply.  So, the reply will time out on the return path
180  * (with no notice sent to anyone since icmp's aren't sent for
181  * icmp's) until we probe with a ttl that's at least twice the path
182  * length.  I.e., rip is really only 7 hops away.  A reply that
183  * returns with a ttl of 1 is a clue this problem exists.
184  * Traceroute prints a "!" after the time if the ttl is <= 1.
185  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
186  * non-standard (HPUX) software, expect to see this problem
187  * frequently and/or take care picking the target host of your
188  * probes.
189  *
190  * Other possible annotations after the time are !H, !N, !P (got a host,
191  * network or protocol unreachable, respectively), !S or !F (source
192  * route failed or fragmentation needed -- neither of these should
193  * ever occur and the associated gateway is busted if you see one).  If
194  * almost all the probes result in some kind of unreachable, traceroute
195  * will give up and exit.
196  *
197  * Notes
198  * -----
199  * This program must be run by root or be setuid.  (I suggest that
200  * you *don't* make it setuid -- casual use could result in a lot
201  * of unnecessary traffic on our poor, congested nets.)
202  *
203  * This program requires a kernel mod that does not appear in any
204  * system available from Berkeley:  A raw ip socket using proto
205  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
206  * opposed to data to be wrapped in an ip datagram).  See the README
207  * file that came with the source to this program for a description
208  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
209  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
210  * MODIFIED TO RUN THIS PROGRAM.
211  *
212  * The udp port usage may appear bizarre (well, ok, it is bizarre).
213  * The problem is that an icmp message only contains 8 bytes of
214  * data from the original datagram.  8 bytes is the size of a udp
215  * header so, if we want to associate replies with the original
216  * datagram, the necessary information must be encoded into the
217  * udp header (the ip id could be used but there's no way to
218  * interlock with the kernel's assignment of ip id's and, anyway,
219  * it would have taken a lot more kernel hacking to allow this
220  * code to set the ip id).  So, to allow two or more users to
221  * use traceroute simultaneously, we use this task's pid as the
222  * source port (the high bit is set to move the port number out
223  * of the "likely" range).  To keep track of which probe is being
224  * replied to (so times and/or hop counts don't get confused by a
225  * reply that was delayed in transit), we increment the destination
226  * port number before each probe.
227  *
228  * Don't use this as a coding example.  I was trying to find a
229  * routing problem and this code sort-of popped out after 48 hours
230  * without sleep.  I was amazed it ever compiled, much less ran.
231  *
232  * I stole the idea for this program from Steve Deering.  Since
233  * the first release, I've learned that had I attended the right
234  * IETF working group meetings, I also could have stolen it from Guy
235  * Almes or Matt Mathis.  I don't know (or care) who came up with
236  * the idea first.  I envy the originators' perspicacity and I'm
237  * glad they didn't keep the idea a secret.
238  *
239  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
240  * enhancements to the original distribution.
241  *
242  * I've hacked up a round-trip-route version of this that works by
243  * sending a loose-source-routed udp datagram through the destination
244  * back to yourself.  Unfortunately, SO many gateways botch source
245  * routing, the thing is almost worthless.  Maybe one day...
246  *
247  *  -- Van Jacobson (van@helios.ee.lbl.gov)
248  *     Tue Dec 20 03:50:13 PST 1988
249  */
250
251 #include <sys/param.h>
252 #include <sys/time.h>
253 #include <sys/socket.h>
254 #include <sys/uio.h>
255 #include <sys/file.h>
256 #include <sys/ioctl.h>
257 #include <sys/sysctl.h>
258
259 #include <netinet/in.h>
260
261 #include <arpa/inet.h>
262
263 #include <netdb.h>
264 #include <stdio.h>
265 #include <err.h>
266 #ifdef HAVE_POLL
267 #include <poll.h>
268 #endif
269 #include <errno.h>
270 #include <stdlib.h>
271 #include <string.h>
272 #include <unistd.h>
273
274 #include <netinet/ip6.h>
275 #include <netinet/icmp6.h>
276 #include <netinet/sctp.h>
277 #include <netinet/sctp_header.h>
278 #include <netinet/tcp.h>
279 #include <netinet/udp.h>
280
281 #ifdef IPSEC
282 #include <net/route.h>
283 #include <netipsec/ipsec.h>
284 #endif
285
286 #include "as.h"
287
288 #define DUMMY_PORT 10010
289
290 #define MAXPACKET       65535   /* max ip packet size */
291
292 #ifndef HAVE_GETIPNODEBYNAME
293 #define getipnodebyname(x, y, z, u)     gethostbyname2((x), (y))
294 #define freehostent(x)
295 #endif
296
297 u_char  packet[512];            /* last inbound (icmp) packet */
298 char    *outpacket;             /* last output packet */
299
300 int     main(int, char *[]);
301 int     wait_for_reply(int, struct msghdr *);
302 #ifdef IPSEC
303 #ifdef IPSEC_POLICY_IPSEC
304 int     setpolicy(int so, char *policy);
305 #endif
306 #endif
307 void    send_probe(int, u_long);
308 void    *get_uphdr(struct ip6_hdr *, u_char *);
309 int     get_hoplim(struct msghdr *);
310 double  deltaT(struct timeval *, struct timeval *);
311 const char *pr_type(int);
312 int     packet_ok(struct msghdr *, int, int);
313 void    print(struct msghdr *, int);
314 const char *inetname(struct sockaddr *);
315 u_int32_t sctp_crc32c(void *, u_int32_t);
316 u_int16_t in_cksum(u_int16_t *addr, int);
317 u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
318     void *, u_int32_t);
319 void    usage(void);
320
321 int rcvsock;                    /* receive (icmp) socket file descriptor */
322 int sndsock;                    /* send (raw/udp) socket file descriptor */
323
324 struct msghdr rcvmhdr;
325 struct iovec rcviov[2];
326 int rcvhlim;
327 struct in6_pktinfo *rcvpktinfo;
328
329 struct sockaddr_in6 Src, Dst, Rcv;
330 u_long datalen = 20;                    /* How much data */
331 #define ICMP6ECHOLEN    8
332 /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
333 char rtbuf[2064];
334 #ifdef USE_RFC2292BIS
335 struct ip6_rthdr *rth;
336 #endif
337 struct cmsghdr *cmsg;
338
339 char *source = NULL;
340 char *hostname;
341
342 u_long nprobes = 3;
343 u_long first_hop = 1;
344 u_long max_hops = 30;
345 u_int16_t srcport;
346 u_int16_t port = 32768+666;     /* start udp dest port # for probe packets */
347 u_int16_t ident;
348 int options;                    /* socket options */
349 int verbose;
350 int waittime = 5;               /* time to wait for response (in seconds) */
351 int nflag;                      /* print addresses numerically */
352 int useproto = IPPROTO_UDP;     /* protocol to use to send packet */
353 int lflag;                      /* print both numerical address & hostname */
354 int as_path;                    /* print as numbers for each hop */
355 char *as_server = NULL;
356 void *asn;
357
358 int
359 main(int argc, char *argv[])
360 {
361         int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
362         char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
363         int ch, i, on = 1, seq, rcvcmsglen, error;
364         struct addrinfo hints, *res;
365         static u_char *rcvcmsgbuf;
366         u_long probe, hops, lport;
367         struct hostent *hp;
368         size_t size, minlen;
369         uid_t uid;
370
371         /*
372          * Receive ICMP
373          */
374         if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
375                 perror("socket(ICMPv6)");
376                 exit(5);
377         }
378
379         size = sizeof(i);
380         (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0);
381         max_hops = i;
382
383         /* specify to tell receiving interface */
384 #ifdef IPV6_RECVPKTINFO
385         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
386             sizeof(on)) < 0)
387                 err(1, "setsockopt(IPV6_RECVPKTINFO)");
388 #else  /* old adv. API */
389         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
390             sizeof(on)) < 0)
391                 err(1, "setsockopt(IPV6_PKTINFO)");
392 #endif
393
394         /* specify to tell value of hoplimit field of received IP6 hdr */
395 #ifdef IPV6_RECVHOPLIMIT
396         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
397             sizeof(on)) < 0)
398                 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
399 #else  /* old adv. API */
400         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
401             sizeof(on)) < 0)
402                 err(1, "setsockopt(IPV6_HOPLIMIT)");
403 #endif
404
405         seq = 0;
406         ident = htons(getpid() & 0xffff); /* same as ping6 */
407
408         while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1)
409                 switch (ch) {
410                 case 'a':
411                         as_path = 1;
412                         break;
413                 case 'A':
414                         as_path = 1;
415                         as_server = optarg;
416                         break;
417                 case 'd':
418                         options |= SO_DEBUG;
419                         break;
420                 case 'f':
421                         ep = NULL;
422                         errno = 0;
423                         first_hop = strtoul(optarg, &ep, 0);
424                         if (errno || !*optarg || *ep || first_hop > 255) {
425                                 fprintf(stderr,
426                                     "traceroute6: invalid min hoplimit.\n");
427                                 exit(1);
428                         }
429                         break;
430                 case 'g':
431                         hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
432                         if (hp == NULL) {
433                                 fprintf(stderr,
434                                     "traceroute6: unknown host %s\n", optarg);
435                                 exit(1);
436                         }
437 #ifdef USE_RFC2292BIS
438                         if (rth == NULL) {
439                                 /*
440                                  * XXX: We can't detect the number of
441                                  * intermediate nodes yet.
442                                  */
443                                 if ((rth = inet6_rth_init((void *)rtbuf,
444                                     sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
445                                     0)) == NULL) {
446                                         fprintf(stderr,
447                                             "inet6_rth_init failed.\n");
448                                         exit(1);
449                                 }
450                         }
451                         if (inet6_rth_add((void *)rth,
452                             (struct in6_addr *)hp->h_addr)) {
453                                 fprintf(stderr,
454                                     "inet6_rth_add failed for %s\n",
455                                     optarg);
456                                 exit(1);
457                         }
458 #else  /* old advanced API */
459                         if (cmsg == NULL)
460                                 cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0);
461                         inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr,
462                             IPV6_RTHDR_LOOSE);
463 #endif
464                         freehostent(hp);
465                         break;
466                 case 'I':
467                         useproto = IPPROTO_ICMPV6;
468                         break;
469                 case 'l':
470                         lflag++;
471                         break;
472                 case 'm':
473                         ep = NULL;
474                         errno = 0;
475                         max_hops = strtoul(optarg, &ep, 0);
476                         if (errno || !*optarg || *ep || max_hops > 255) {
477                                 fprintf(stderr,
478                                     "traceroute6: invalid max hoplimit.\n");
479                                 exit(1);
480                         }
481                         break;
482                 case 'n':
483                         nflag++;
484                         break;
485                 case 'N':
486                         useproto = IPPROTO_NONE;
487                         break;
488                 case 'p':
489                         ep = NULL;
490                         errno = 0;
491                         lport = strtoul(optarg, &ep, 0);
492                         if (errno || !*optarg || *ep) {
493                                 fprintf(stderr, "traceroute6: invalid port.\n");
494                                 exit(1);
495                         }
496                         if (lport == 0 || lport != (lport & 0xffff)) {
497                                 fprintf(stderr,
498                                     "traceroute6: port out of range.\n");
499                                 exit(1);
500                         }
501                         port = lport & 0xffff;
502                         break;
503                 case 'q':
504                         ep = NULL;
505                         errno = 0;
506                         nprobes = strtoul(optarg, &ep, 0);
507                         if (errno || !*optarg || *ep) {
508                                 fprintf(stderr,
509                                     "traceroute6: invalid nprobes.\n");
510                                 exit(1);
511                         }
512                         if (nprobes < 1) {
513                                 fprintf(stderr,
514                                     "traceroute6: nprobes must be >0.\n");
515                                 exit(1);
516                         }
517                         break;
518                 case 'r':
519                         options |= SO_DONTROUTE;
520                         break;
521                 case 's':
522                         /*
523                          * set the ip source address of the outbound
524                          * probe (e.g., on a multi-homed host).
525                          */
526                         source = optarg;
527                         break;
528                 case 'S':
529                         useproto = IPPROTO_SCTP;
530                         break;
531                 case 'T':
532                         useproto = IPPROTO_TCP;
533                         break;
534                 case 'U':
535                         useproto = IPPROTO_UDP;
536                         break;
537                 case 'v':
538                         verbose++;
539                         break;
540                 case 'w':
541                         ep = NULL;
542                         errno = 0;
543                         waittime = strtoul(optarg, &ep, 0);
544                         if (errno || !*optarg || *ep) {
545                                 fprintf(stderr,
546                                     "traceroute6: invalid wait time.\n");
547                                 exit(1);
548                         }
549                         if (waittime < 1) {
550                                 fprintf(stderr,
551                                     "traceroute6: wait must be >= 1 sec.\n");
552                                 exit(1);
553                         }
554                         break;
555                 default:
556                         usage();
557                 }
558         argc -= optind;
559         argv += optind;
560
561         /*
562          * Open socket to send probe packets.
563          */
564         switch (useproto) {
565         case IPPROTO_ICMPV6:
566                 sndsock = rcvsock;
567                 break;
568         case IPPROTO_UDP:
569                 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
570                         perror("socket(SOCK_DGRAM)");
571                         exit(5);
572                 }
573                 break;
574         case IPPROTO_NONE:
575         case IPPROTO_SCTP:
576         case IPPROTO_TCP:
577                 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
578                         perror("socket(SOCK_RAW)");
579                         exit(5);
580                 }
581                 break;
582         default:
583                 fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
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 || *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;
653                 break;
654         case IPPROTO_UDP:
655                 minlen = sizeof(struct udphdr);
656                 break;
657         case IPPROTO_NONE:
658                 minlen = 0;
659                 datalen = 0;
660                 break;
661         case IPPROTO_SCTP:
662                 minlen = sizeof(struct sctphdr);
663                 break;
664         case IPPROTO_TCP:
665                 minlen = sizeof(struct tcphdr);
666                 break;
667         default:
668                 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
669                     useproto);
670                 exit(1);
671         }
672         if (datalen < minlen)
673                 datalen = minlen;
674         else if (datalen >= MAXPACKET) {
675                 fprintf(stderr,
676                     "traceroute6: packet size must be %zu <= s < %d.\n",
677                     minlen, MAXPACKET);
678                 exit(1);
679         }
680         if (useproto == IPPROTO_UDP)
681                 datalen -= sizeof(struct udphdr);
682         if ((useproto == IPPROTO_SCTP) && (datalen & 3)) {
683                 fprintf(stderr, 
684                     "traceroute6: packet size must be a multiple of 4.\n");
685                 exit(1);
686         }
687         outpacket = malloc(datalen);
688         if (!outpacket) {
689                 perror("malloc");
690                 exit(1);
691         }
692         (void) bzero((char *)outpacket, datalen);
693
694         /* initialize msghdr for receiving packets */
695         rcviov[0].iov_base = (caddr_t)packet;
696         rcviov[0].iov_len = sizeof(packet);
697         rcvmhdr.msg_name = (caddr_t)&Rcv;
698         rcvmhdr.msg_namelen = sizeof(Rcv);
699         rcvmhdr.msg_iov = rcviov;
700         rcvmhdr.msg_iovlen = 1;
701         rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
702             CMSG_SPACE(sizeof(int));
703         if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
704                 fprintf(stderr, "traceroute6: malloc failed\n");
705                 exit(1);
706         }
707         rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
708         rcvmhdr.msg_controllen = rcvcmsglen;
709
710         if (options & SO_DEBUG)
711                 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
712                     (char *)&on, sizeof(on));
713         if (options & SO_DONTROUTE)
714                 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
715                     (char *)&on, sizeof(on));
716 #ifdef IPSEC
717 #ifdef IPSEC_POLICY_IPSEC
718         /*
719          * do not raise error even if setsockopt fails, kernel may have ipsec
720          * turned off.
721          */
722         if (setpolicy(rcvsock, "in bypass") < 0)
723                 errx(1, "%s", ipsec_strerror());
724         if (setpolicy(rcvsock, "out bypass") < 0)
725                 errx(1, "%s", ipsec_strerror());
726 #else
727     {
728         int level = IPSEC_LEVEL_NONE;
729
730         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
731             sizeof(level));
732         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
733             sizeof(level));
734 #ifdef IP_AUTH_TRANS_LEVEL
735         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
736             sizeof(level));
737 #else
738         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
739             sizeof(level));
740 #endif
741 #ifdef IP_AUTH_NETWORK_LEVEL
742         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
743             sizeof(level));
744 #endif
745     }
746 #endif /*IPSEC_POLICY_IPSEC*/
747 #endif /*IPSEC*/
748
749 #ifdef SO_SNDBUF
750         i = datalen;
751         if (i == 0)
752                 i = 1;
753         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
754             sizeof(i)) < 0) {
755                 perror("setsockopt(SO_SNDBUF)");
756                 exit(6);
757         }
758 #endif /* SO_SNDBUF */
759         if (options & SO_DEBUG)
760                 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
761                     (char *)&on, sizeof(on));
762         if (options & SO_DONTROUTE)
763                 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
764                     (char *)&on, sizeof(on));
765 #ifdef USE_RFC2292BIS
766         if (rth) {/* XXX: there is no library to finalize the header... */
767                 rth->ip6r_len = rth->ip6r_segleft * 2;
768                 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
769                     (void *)rth, (rth->ip6r_len + 1) << 3)) {
770                         fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
771                             strerror(errno));
772                         exit(1);
773                 }
774         }
775 #else  /* old advanced API */
776         if (cmsg != NULL) {
777                 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
778                 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
779                     rtbuf, cmsg->cmsg_len) < 0) {
780                         fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n",
781                             strerror(errno));
782                         exit(1);
783                 }
784         }
785 #endif /* USE_RFC2292BIS */
786 #ifdef IPSEC
787 #ifdef IPSEC_POLICY_IPSEC
788         /*
789          * do not raise error even if setsockopt fails, kernel may have ipsec
790          * turned off.
791          */
792         if (setpolicy(sndsock, "in bypass") < 0)
793                 errx(1, "%s", ipsec_strerror());
794         if (setpolicy(sndsock, "out bypass") < 0)
795                 errx(1, "%s", ipsec_strerror());
796 #else
797     {
798         int level = IPSEC_LEVEL_BYPASS;
799
800         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
801             sizeof(level));
802         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
803             sizeof(level));
804 #ifdef IP_AUTH_TRANS_LEVEL
805         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
806             sizeof(level));
807 #else
808         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
809             sizeof(level));
810 #endif
811 #ifdef IP_AUTH_NETWORK_LEVEL
812         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
813             sizeof(level));
814 #endif
815     }
816 #endif /*IPSEC_POLICY_IPSEC*/
817 #endif /*IPSEC*/
818
819         /*
820          * Source selection
821          */
822         bzero(&Src, sizeof(Src));
823         if (source) {
824                 struct addrinfo hints, *res;
825                 int error;
826
827                 memset(&hints, 0, sizeof(hints));
828                 hints.ai_family = AF_INET6;
829                 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
830                 hints.ai_flags = AI_NUMERICHOST;
831                 error = getaddrinfo(source, "0", &hints, &res);
832                 if (error) {
833                         printf("traceroute6: %s: %s\n", source,
834                             gai_strerror(error));
835                         exit(1);
836                 }
837                 if (res->ai_addrlen > sizeof(Src)) {
838                         printf("traceroute6: %s: %s\n", source,
839                             gai_strerror(error));
840                         exit(1);
841                 }
842                 memcpy(&Src, res->ai_addr, res->ai_addrlen);
843                 freeaddrinfo(res);
844         } else {
845                 struct sockaddr_in6 Nxt;
846                 int dummy;
847                 socklen_t len;
848
849                 Nxt = Dst;
850                 Nxt.sin6_port = htons(DUMMY_PORT);
851                 if (cmsg != NULL)
852                         bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
853                             sizeof(Nxt.sin6_addr));
854                 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
855                         perror("socket");
856                         exit(1);
857                 }
858                 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
859                         perror("connect");
860                         exit(1);
861                 }
862                 len = sizeof(Src);
863                 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
864                         perror("getsockname");
865                         exit(1);
866                 }
867                 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len,
868                     src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) {
869                         fprintf(stderr, "getnameinfo failed for source\n");
870                         exit(1);
871                 }
872                 source = src0;
873                 close(dummy);
874         }
875
876         Src.sin6_port = htons(0);
877         if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
878                 perror("bind");
879                 exit(1);
880         }
881
882         {
883                 socklen_t len;
884
885                 len = sizeof(Src);
886                 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
887                         perror("getsockname");
888                         exit(1);
889                 }
890                 srcport = ntohs(Src.sin6_port);
891         }
892
893         if (as_path) {
894                 asn = as_setup(as_server);
895                 if (asn == NULL) {
896                         fprintf(stderr,
897                             "traceroute6: as_setup failed, AS# lookups"
898                             " disabled\n");
899                         (void)fflush(stderr);
900                         as_path = 0;
901                 }
902         }
903
904         /*
905          * Message to users
906          */
907         if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
908             sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
909                 strlcpy(hbuf, "(invalid)", sizeof(hbuf));
910         fprintf(stderr, "traceroute6");
911         fprintf(stderr, " to %s (%s)", hostname, hbuf);
912         if (source)
913                 fprintf(stderr, " from %s", source);
914         fprintf(stderr, ", %lu hops max, %lu byte packets\n",
915             max_hops,
916             datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
917         (void) fflush(stderr);
918
919         if (first_hop > 1)
920                 printf("Skipping %lu intermediate hops\n", first_hop - 1);
921
922         /*
923          * Main loop
924          */
925         for (hops = first_hop; hops <= max_hops; ++hops) {
926                 struct in6_addr lastaddr;
927                 int got_there = 0;
928                 unsigned unreachable = 0;
929
930                 printf("%2lu ", hops);
931                 bzero(&lastaddr, sizeof(lastaddr));
932                 for (probe = 0; probe < nprobes; ++probe) {
933                         int cc;
934                         struct timeval t1, t2;
935
936                         (void) gettimeofday(&t1, NULL);
937                         send_probe(++seq, hops);
938                         while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
939                                 (void) gettimeofday(&t2, NULL);
940                                 if ((i = packet_ok(&rcvmhdr, cc, seq))) {
941                                         if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
942                                             &lastaddr)) {
943                                                 if (probe > 0)
944                                                         fputs("\n   ", stdout);
945                                                 print(&rcvmhdr, cc);
946                                                 lastaddr = Rcv.sin6_addr;
947                                         }
948                                         printf("  %.3f ms", deltaT(&t1, &t2));
949                                         switch (i - 1) {
950                                         case ICMP6_DST_UNREACH_NOROUTE:
951                                                 ++unreachable;
952                                                 printf(" !N");
953                                                 break;
954                                         case ICMP6_DST_UNREACH_ADMIN:
955                                                 ++unreachable;
956                                                 printf(" !P");
957                                                 break;
958                                         case ICMP6_DST_UNREACH_NOTNEIGHBOR:
959                                                 ++unreachable;
960                                                 printf(" !S");
961                                                 break;
962                                         case ICMP6_DST_UNREACH_ADDR:
963                                                 ++unreachable;
964                                                 printf(" !A");
965                                                 break;
966                                         case ICMP6_DST_UNREACH_NOPORT:
967                                                 if (rcvhlim >= 0 &&
968                                                     rcvhlim <= 1)
969                                                         printf(" !");
970                                                 ++got_there;
971                                                 break;
972                                         }
973                                         break;
974                                 } else if (deltaT(&t1, &t2) > waittime * 1000) {
975                                         cc = 0;
976                                         break;
977                                 }
978                         }
979                         if (cc == 0)
980                                 printf(" *");
981                         (void) fflush(stdout);
982                 }
983                 putchar('\n');
984                 if (got_there ||
985                     (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
986                         exit(0);
987                 }
988         }
989         if (as_path)
990                 as_shutdown(asn);
991
992         exit(0);
993 }
994
995 int
996 wait_for_reply(int sock, struct msghdr *mhdr)
997 {
998 #ifdef HAVE_POLL
999         struct pollfd pfd[1];
1000         int cc = 0;
1001
1002         pfd[0].fd = sock;
1003         pfd[0].events = POLLIN;
1004         pfd[0].revents = 0;
1005
1006         if (poll(pfd, 1, waittime * 1000) > 0)
1007                 cc = recvmsg(rcvsock, mhdr, 0);
1008
1009         return(cc);
1010 #else
1011         fd_set *fdsp;
1012         struct timeval wait;
1013         int cc = 0, fdsn;
1014
1015         fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1016         if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1017                 err(1, "malloc");
1018         memset(fdsp, 0, fdsn);
1019         FD_SET(sock, fdsp);
1020         wait.tv_sec = waittime; wait.tv_usec = 0;
1021
1022         if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1023                 cc = recvmsg(rcvsock, mhdr, 0);
1024
1025         free(fdsp);
1026         return(cc);
1027 #endif
1028 }
1029
1030 #ifdef IPSEC
1031 #ifdef IPSEC_POLICY_IPSEC
1032 int
1033 setpolicy(so, policy)
1034         int so;
1035         char *policy;
1036 {
1037         char *buf;
1038
1039         buf = ipsec_set_policy(policy, strlen(policy));
1040         if (buf == NULL) {
1041                 warnx("%s", ipsec_strerror());
1042                 return -1;
1043         }
1044         (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1045             buf, ipsec_get_policylen(buf));
1046
1047         free(buf);
1048
1049         return 0;
1050 }
1051 #endif
1052 #endif
1053
1054 void
1055 send_probe(int seq, u_long hops)
1056 {
1057         struct icmp6_hdr *icp;
1058         struct sctphdr *sctp;
1059         struct sctp_chunkhdr *chk;
1060         struct sctp_init_chunk *init;
1061         struct sctp_paramhdr *param;
1062         struct tcphdr *tcp;
1063         int i;
1064
1065         i = hops;
1066         if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1067             (char *)&i, sizeof(i)) < 0) {
1068                 perror("setsockopt IPV6_UNICAST_HOPS");
1069         }
1070
1071         Dst.sin6_port = htons(port + seq);
1072
1073         switch (useproto) {
1074         case IPPROTO_ICMPV6:
1075                 icp = (struct icmp6_hdr *)outpacket;
1076
1077                 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1078                 icp->icmp6_code = 0;
1079                 icp->icmp6_cksum = 0;
1080                 icp->icmp6_id = ident;
1081                 icp->icmp6_seq = htons(seq);
1082                 break;
1083         case IPPROTO_UDP:
1084                 break;
1085         case IPPROTO_NONE:
1086                 /* No space for anything. No harm as seq/tv32 are decorative. */
1087                 break;
1088         case IPPROTO_SCTP:
1089                 sctp = (struct sctphdr *)outpacket;
1090
1091                 sctp->src_port = htons(ident);
1092                 sctp->dest_port = htons(port + seq);
1093                 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1094                     sizeof(struct sctp_init_chunk))) {
1095                         sctp->v_tag = 0;
1096                 } else {
1097                         sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1098                 }
1099                 sctp->checksum = htonl(0);
1100                 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1101                     sizeof(struct sctp_init_chunk))) {
1102                         /*
1103                          * Send a packet containing an INIT chunk. This works
1104                          * better in case of firewalls on the path, but
1105                          * results in a probe packet containing at least
1106                          * 32 bytes of payload. For shorter payloads, use
1107                          * SHUTDOWN-ACK chunks.
1108                          */
1109                         init = (struct sctp_init_chunk *)(sctp + 1);
1110                         init->ch.chunk_type = SCTP_INITIATION;
1111                         init->ch.chunk_flags = 0;
1112                         init->ch.chunk_length = htons((u_int16_t)(datalen -
1113                             sizeof(struct sctphdr)));
1114                         init->init.initiate_tag = (sctp->src_port << 16) |
1115                             sctp->dest_port;
1116                         init->init.a_rwnd = htonl(1500);
1117                         init->init.num_outbound_streams = htons(1);
1118                         init->init.num_inbound_streams = htons(1);
1119                         init->init.initial_tsn = htonl(0);
1120                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1121                             sizeof(struct sctp_init_chunk) +
1122                             sizeof(struct sctp_paramhdr))) {
1123                                 param = (struct sctp_paramhdr *)(init + 1);
1124                                 param->param_type = htons(SCTP_PAD);
1125                                 param->param_length =
1126                                     htons((u_int16_t)(datalen -
1127                                     sizeof(struct sctphdr) -
1128                                     sizeof(struct sctp_init_chunk)));
1129                         }
1130                 } else {
1131                         /*
1132                          * Send a packet containing a SHUTDOWN-ACK chunk,
1133                          * possibly followed by a PAD chunk.
1134                          */
1135                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1136                             sizeof(struct sctp_chunkhdr))) {
1137                                 chk = (struct sctp_chunkhdr *)(sctp + 1);
1138                                 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1139                                 chk->chunk_flags = 0;
1140                                 chk->chunk_length = htons(4);
1141                         }
1142                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1143                             2 * sizeof(struct sctp_chunkhdr))) {
1144                                 chk = chk + 1;
1145                                 chk->chunk_type = SCTP_PAD_CHUNK;
1146                                 chk->chunk_flags = 0;
1147                                 chk->chunk_length = htons((u_int16_t)(datalen -
1148                                     sizeof(struct sctphdr) -
1149                                     sizeof(struct sctp_chunkhdr)));
1150                         }
1151                 }
1152                 sctp->checksum = sctp_crc32c(outpacket, datalen);
1153                 break;
1154         case IPPROTO_TCP:
1155                 tcp = (struct tcphdr *)outpacket;
1156
1157                 tcp->th_sport = htons(ident);
1158                 tcp->th_dport = htons(port + seq);
1159                 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1160                 tcp->th_ack = 0;
1161                 tcp->th_off = 5;
1162                 tcp->th_flags = TH_SYN;
1163                 tcp->th_sum = 0;
1164                 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1165                 break;
1166         default:
1167                 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1168                 exit(1);
1169         }
1170
1171         i = sendto(sndsock, (char *)outpacket, datalen, 0,
1172             (struct sockaddr *)&Dst, Dst.sin6_len);
1173         if (i < 0 || (u_long)i != datalen)  {
1174                 if (i < 0)
1175                         perror("sendto");
1176                 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1177                     hostname, datalen, i);
1178                 (void) fflush(stdout);
1179         }
1180 }
1181
1182 int
1183 get_hoplim(struct msghdr *mhdr)
1184 {
1185         struct cmsghdr *cm;
1186
1187         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1188             cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1189                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1190                     cm->cmsg_type == IPV6_HOPLIMIT &&
1191                     cm->cmsg_len == CMSG_LEN(sizeof(int)))
1192                         return(*(int *)CMSG_DATA(cm));
1193         }
1194
1195         return(-1);
1196 }
1197
1198 double
1199 deltaT(struct timeval *t1p, struct timeval *t2p)
1200 {
1201         double dt;
1202
1203         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1204             (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1205         return (dt);
1206 }
1207
1208 /*
1209  * Convert an ICMP "type" field to a printable string.
1210  */
1211 const char *
1212 pr_type(int t0)
1213 {
1214         u_char t = t0 & 0xff;
1215         const char *cp;
1216
1217         switch (t) {
1218         case ICMP6_DST_UNREACH:
1219                 cp = "Destination Unreachable";
1220                 break;
1221         case ICMP6_PACKET_TOO_BIG:
1222                 cp = "Packet Too Big";
1223                 break;
1224         case ICMP6_TIME_EXCEEDED:
1225                 cp = "Time Exceeded";
1226                 break;
1227         case ICMP6_PARAM_PROB:
1228                 cp = "Parameter Problem";
1229                 break;
1230         case ICMP6_ECHO_REQUEST:
1231                 cp = "Echo Request";
1232                 break;
1233         case ICMP6_ECHO_REPLY:
1234                 cp = "Echo Reply";
1235                 break;
1236         case ICMP6_MEMBERSHIP_QUERY:
1237                 cp = "Group Membership Query";
1238                 break;
1239         case ICMP6_MEMBERSHIP_REPORT:
1240                 cp = "Group Membership Report";
1241                 break;
1242         case ICMP6_MEMBERSHIP_REDUCTION:
1243                 cp = "Group Membership Reduction";
1244                 break;
1245         case ND_ROUTER_SOLICIT:
1246                 cp = "Router Solicitation";
1247                 break;
1248         case ND_ROUTER_ADVERT:
1249                 cp = "Router Advertisement";
1250                 break;
1251         case ND_NEIGHBOR_SOLICIT:
1252                 cp = "Neighbor Solicitation";
1253                 break;
1254         case ND_NEIGHBOR_ADVERT:
1255                 cp = "Neighbor Advertisement";
1256                 break;
1257         case ND_REDIRECT:
1258                 cp = "Redirect";
1259                 break;
1260         default:
1261                 cp = "Unknown";
1262                 break;
1263         }
1264         return cp;
1265 }
1266
1267 int
1268 packet_ok(struct msghdr *mhdr, int cc, int seq)
1269 {
1270         struct icmp6_hdr *icp;
1271         struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1272         u_char type, code;
1273         char *buf = (char *)mhdr->msg_iov[0].iov_base;
1274         struct cmsghdr *cm;
1275         int *hlimp;
1276         char hbuf[NI_MAXHOST];
1277
1278 #ifdef OLDRAWSOCKET
1279         int hlen;
1280         struct ip6_hdr *ip;
1281 #endif
1282
1283 #ifdef OLDRAWSOCKET
1284         ip = (struct ip6_hdr *) buf;
1285         hlen = sizeof(struct ip6_hdr);
1286         if (cc < hlen + sizeof(struct icmp6_hdr)) {
1287                 if (verbose) {
1288                         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1289                             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1290                                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1291                         printf("packet too short (%d bytes) from %s\n", cc,
1292                             hbuf);
1293                 }
1294                 return (0);
1295         }
1296         cc -= hlen;
1297         icp = (struct icmp6_hdr *)(buf + hlen);
1298 #else
1299         if (cc < (int)sizeof(struct icmp6_hdr)) {
1300                 if (verbose) {
1301                         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1302                             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1303                                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1304                         printf("data too short (%d bytes) from %s\n", cc, hbuf);
1305                 }
1306                 return(0);
1307         }
1308         icp = (struct icmp6_hdr *)buf;
1309 #endif
1310         /* get optional information via advanced API */
1311         rcvpktinfo = NULL;
1312         hlimp = NULL;
1313         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1314             cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1315                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1316                     cm->cmsg_type == IPV6_PKTINFO &&
1317                     cm->cmsg_len ==
1318                     CMSG_LEN(sizeof(struct in6_pktinfo)))
1319                         rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1320
1321                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1322                     cm->cmsg_type == IPV6_HOPLIMIT &&
1323                     cm->cmsg_len == CMSG_LEN(sizeof(int)))
1324                         hlimp = (int *)CMSG_DATA(cm);
1325         }
1326         if (rcvpktinfo == NULL || hlimp == NULL) {
1327                 warnx("failed to get received hop limit or packet info");
1328 #if 0
1329                 return(0);
1330 #else
1331                 rcvhlim = 0;    /*XXX*/
1332 #endif
1333         }
1334         else
1335                 rcvhlim = *hlimp;
1336
1337         type = icp->icmp6_type;
1338         code = icp->icmp6_code;
1339         if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
1340             || type == ICMP6_DST_UNREACH) {
1341                 struct ip6_hdr *hip;
1342                 struct icmp6_hdr *icmp;
1343                 struct sctp_init_chunk *init;
1344                 struct sctphdr *sctp;
1345                 struct tcphdr *tcp;
1346                 struct udphdr *udp;
1347                 void *up;
1348
1349                 hip = (struct ip6_hdr *)(icp + 1);
1350                 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1351                         if (verbose)
1352                                 warnx("failed to get upper layer header");
1353                         return(0);
1354                 }
1355                 switch (useproto) {
1356                 case IPPROTO_ICMPV6:
1357                         icmp = (struct icmp6_hdr *)up;
1358                         if (icmp->icmp6_id == ident &&
1359                             icmp->icmp6_seq == htons(seq))
1360                                 return (type == ICMP6_TIME_EXCEEDED ?
1361                                     -1 : code + 1);
1362                         break;
1363                 case IPPROTO_UDP:
1364                         udp = (struct udphdr *)up;
1365                         if (udp->uh_sport == htons(srcport) &&
1366                             udp->uh_dport == htons(port + seq))
1367                                 return (type == ICMP6_TIME_EXCEEDED ?
1368                                     -1 : code + 1);
1369                         break;
1370                 case IPPROTO_SCTP:
1371                         sctp = (struct sctphdr *)up;
1372                         if (sctp->src_port != htons(ident) ||
1373                             sctp->dest_port != htons(port + seq)) {
1374                                 break;
1375                         }
1376                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1377                             sizeof(struct sctp_init_chunk))) {
1378                                 if (sctp->v_tag != 0) {
1379                                         break;
1380                                 }
1381                                 init = (struct sctp_init_chunk *)(sctp + 1);
1382                                 /* Check the initiate tag, if available. */
1383                                 if ((char *)&init->init.a_rwnd > buf + cc) {
1384                                         return (type == ICMP6_TIME_EXCEEDED ?
1385                                             -1 : code + 1);
1386                                 }
1387                                 if (init->init.initiate_tag == (u_int32_t)
1388                                     ((sctp->src_port << 16) | sctp->dest_port)) {
1389                                         return (type == ICMP6_TIME_EXCEEDED ?
1390                                             -1 : code + 1);
1391                                 }
1392                         } else {
1393                                 if (sctp->v_tag ==
1394                                     (u_int32_t)((sctp->src_port << 16) |
1395                                     sctp->dest_port)) {
1396                                         return (type == ICMP6_TIME_EXCEEDED ?
1397                                             -1 : code + 1);
1398                                 }
1399                         }
1400                         break;
1401                 case IPPROTO_TCP:
1402                         tcp = (struct tcphdr *)up;
1403                         if (tcp->th_sport == htons(ident) &&
1404                             tcp->th_dport == htons(port + seq) &&
1405                             tcp->th_seq ==
1406                             (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1407                                 return (type == ICMP6_TIME_EXCEEDED ?
1408                                     -1 : code + 1);
1409                         break;
1410                 case IPPROTO_NONE:
1411                         return (type == ICMP6_TIME_EXCEEDED ?  -1 : code + 1);
1412                 default:
1413                         fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1414                         break;
1415                 }
1416         } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) {
1417                 if (icp->icmp6_id == ident &&
1418                     icp->icmp6_seq == htons(seq))
1419                         return (ICMP6_DST_UNREACH_NOPORT + 1);
1420         }
1421         if (verbose) {
1422                 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
1423                 u_int8_t *p;
1424                 int i;
1425
1426                 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1427                     sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1428                         strlcpy(sbuf, "invalid", sizeof(sbuf));
1429                 printf("\n%d bytes from %s to %s", cc, sbuf,
1430                     rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1431                     dbuf, sizeof(dbuf)) : "?");
1432                 printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
1433                     icp->icmp6_code);
1434                 p = (u_int8_t *)(icp + 1);
1435 #define WIDTH   16
1436                 for (i = 0; i < cc; i++) {
1437                         if (i % WIDTH == 0)
1438                                 printf("%04x:", i);
1439                         if (i % 4 == 0)
1440                                 printf(" ");
1441                         printf("%02x", p[i]);
1442                         if (i % WIDTH == WIDTH - 1)
1443                                 printf("\n");
1444                 }
1445                 if (cc % WIDTH != 0)
1446                         printf("\n");
1447         }
1448         return(0);
1449 }
1450
1451 /*
1452  * Increment pointer until find the UDP or ICMP header.
1453  */
1454 void *
1455 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1456 {
1457         u_char *cp = (u_char *)ip6, nh;
1458         int hlen;
1459         static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1460
1461         if (cp + sizeof(*ip6) > lim)
1462                 return(NULL);
1463
1464         nh = ip6->ip6_nxt;
1465         cp += sizeof(struct ip6_hdr);
1466
1467         while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1468                 switch (nh) {
1469                 case IPPROTO_ESP:
1470                         return(NULL);
1471                 case IPPROTO_ICMPV6:
1472                         return(useproto == nh ? cp : NULL);
1473                 case IPPROTO_SCTP:
1474                 case IPPROTO_TCP:
1475                 case IPPROTO_UDP:
1476                         return(useproto == nh ? cp : NULL);
1477                 case IPPROTO_NONE:
1478                         return(useproto == nh ? none_hdr : NULL);
1479                 case IPPROTO_FRAGMENT:
1480                         hlen = sizeof(struct ip6_frag);
1481                         nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1482                         break;
1483                 case IPPROTO_AH:
1484                         hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1485                         nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1486                         break;
1487                 default:
1488                         hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1489                         nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1490                         break;
1491                 }
1492
1493                 cp += hlen;
1494         }
1495
1496         return(NULL);
1497 }
1498
1499 void
1500 print(struct msghdr *mhdr, int cc)
1501 {
1502         struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1503         char hbuf[NI_MAXHOST];
1504
1505         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1506             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1507                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1508         if (as_path)
1509                 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1510         if (nflag)
1511                 printf(" %s", hbuf);
1512         else if (lflag)
1513                 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1514         else
1515                 printf(" %s", inetname((struct sockaddr *)from));
1516
1517         if (verbose) {
1518 #ifdef OLDRAWSOCKET
1519                 printf(" %d bytes to %s", cc,
1520                     rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1521                     hbuf, sizeof(hbuf)) : "?");
1522 #else
1523                 printf(" %d bytes of data to %s", cc,
1524                     rcvpktinfo ?  inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1525                     hbuf, sizeof(hbuf)) : "?");
1526 #endif
1527         }
1528 }
1529
1530 /*
1531  * Construct an Internet address representation.
1532  * If the nflag has been supplied, give
1533  * numeric value, otherwise try for symbolic name.
1534  */
1535 const char *
1536 inetname(struct sockaddr *sa)
1537 {
1538         static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1539         static int first = 1;
1540         char *cp;
1541
1542         if (first && !nflag) {
1543                 first = 0;
1544                 if (gethostname(domain, sizeof(domain)) == 0 &&
1545                     (cp = strchr(domain, '.')))
1546                         (void) strlcpy(domain, cp + 1, sizeof(domain));
1547                 else
1548                         domain[0] = 0;
1549         }
1550         cp = NULL;
1551         if (!nflag) {
1552                 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1553                     NI_NAMEREQD) == 0) {
1554                         if ((cp = strchr(line, '.')) &&
1555                             !strcmp(cp + 1, domain))
1556                                 *cp = 0;
1557                         cp = line;
1558                 }
1559         }
1560         if (cp)
1561                 return cp;
1562
1563         if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1564             NI_NUMERICHOST) != 0)
1565                 strlcpy(line, "invalid", sizeof(line));
1566         return line;
1567 }
1568
1569 /*
1570  * CRC32C routine for the Stream Control Transmission Protocol
1571  */
1572
1573 #define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
1574
1575 static u_int32_t crc_c[256] = {
1576         0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1577         0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1578         0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1579         0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1580         0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1581         0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1582         0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1583         0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1584         0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1585         0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1586         0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1587         0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1588         0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1589         0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1590         0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1591         0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1592         0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1593         0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1594         0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1595         0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1596         0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1597         0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1598         0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1599         0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1600         0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1601         0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1602         0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1603         0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1604         0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1605         0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1606         0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1607         0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1608         0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1609         0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1610         0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1611         0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1612         0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1613         0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1614         0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1615         0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1616         0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1617         0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1618         0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1619         0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1620         0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1621         0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1622         0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1623         0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1624         0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1625         0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1626         0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1627         0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1628         0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1629         0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1630         0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1631         0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1632         0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1633         0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1634         0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1635         0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1636         0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1637         0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1638         0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1639         0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1640 };
1641
1642 u_int32_t
1643 sctp_crc32c(void *packet, u_int32_t len)
1644 {
1645         u_int32_t i, crc32c;
1646         u_int8_t byte0, byte1, byte2, byte3;
1647         u_int8_t *buf = (u_int8_t *)packet;
1648
1649         crc32c = ~0;
1650         for (i = 0; i < len; i++)
1651                 CRC32C(crc32c, buf[i]);
1652         crc32c = ~crc32c;
1653         byte0  = crc32c & 0xff;
1654         byte1  = (crc32c>>8) & 0xff;
1655         byte2  = (crc32c>>16) & 0xff;
1656         byte3  = (crc32c>>24) & 0xff;
1657         crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1658         return htonl(crc32c);
1659 }
1660
1661 u_int16_t
1662 in_cksum(u_int16_t *addr, int len)
1663 {
1664         int nleft = len;
1665         u_int16_t *w = addr;
1666         u_int16_t answer;
1667         int sum = 0;
1668
1669         /*
1670          *  Our algorithm is simple, using a 32 bit accumulator (sum),
1671          *  we add sequential 16 bit words to it, and at the end, fold
1672          *  back all the carry bits from the top 16 bits into the lower
1673          *  16 bits.
1674          */
1675         while (nleft > 1)  {
1676                 sum += *w++;
1677                 nleft -= 2;
1678         }
1679
1680         /* mop up an odd byte, if necessary */
1681         if (nleft == 1)
1682                 sum += *(u_char *)w;
1683
1684         /*
1685          * add back carry outs from top 16 bits to low 16 bits
1686          */
1687         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1688         sum += (sum >> 16);                     /* add carry */
1689         answer = ~sum;                          /* truncate to 16 bits */
1690         return (answer);
1691 }
1692
1693 u_int16_t
1694 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1695     void *payload, u_int32_t len)
1696 {
1697         struct {
1698                 struct in6_addr src;
1699                 struct in6_addr dst;
1700                 u_int32_t len;
1701                 u_int8_t zero[3];
1702                 u_int8_t next;
1703         } pseudo_hdr;
1704         u_int16_t sum[2];
1705
1706         pseudo_hdr.src = src->sin6_addr;
1707         pseudo_hdr.dst = dst->sin6_addr;
1708         pseudo_hdr.len = htonl(len);
1709         pseudo_hdr.zero[0] = 0;
1710         pseudo_hdr.zero[1] = 0;
1711         pseudo_hdr.zero[2] = 0;
1712         pseudo_hdr.next = IPPROTO_TCP;
1713
1714         sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1715         sum[0] = in_cksum(payload, len);
1716
1717         return (~in_cksum(sum, sizeof(sum)));
1718 }
1719
1720 void
1721 usage(void)
1722 {
1723
1724         fprintf(stderr,
1725 "usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1726 "       [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"
1727 "       [datalen]\n");
1728         exit(1);
1729 }