]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/traceroute6/traceroute6.c
Let packet_op() explicitly return the type and code instead of doing
[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, u_char *, u_char *);
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         u_char type, code;
371
372         /*
373          * Receive ICMP
374          */
375         if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
376                 perror("socket(ICMPv6)");
377                 exit(5);
378         }
379
380         size = sizeof(i);
381         (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &i, &size, NULL, 0);
382         max_hops = i;
383
384         /* specify to tell receiving interface */
385 #ifdef IPV6_RECVPKTINFO
386         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
387             sizeof(on)) < 0)
388                 err(1, "setsockopt(IPV6_RECVPKTINFO)");
389 #else  /* old adv. API */
390         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_PKTINFO, &on,
391             sizeof(on)) < 0)
392                 err(1, "setsockopt(IPV6_PKTINFO)");
393 #endif
394
395         /* specify to tell value of hoplimit field of received IP6 hdr */
396 #ifdef IPV6_RECVHOPLIMIT
397         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
398             sizeof(on)) < 0)
399                 err(1, "setsockopt(IPV6_RECVHOPLIMIT)");
400 #else  /* old adv. API */
401         if (setsockopt(rcvsock, IPPROTO_IPV6, IPV6_HOPLIMIT, &on,
402             sizeof(on)) < 0)
403                 err(1, "setsockopt(IPV6_HOPLIMIT)");
404 #endif
405
406         seq = 0;
407         ident = htons(getpid() & 0xffff); /* same as ping6 */
408
409         while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1)
410                 switch (ch) {
411                 case 'a':
412                         as_path = 1;
413                         break;
414                 case 'A':
415                         as_path = 1;
416                         as_server = optarg;
417                         break;
418                 case 'd':
419                         options |= SO_DEBUG;
420                         break;
421                 case 'f':
422                         ep = NULL;
423                         errno = 0;
424                         first_hop = strtoul(optarg, &ep, 0);
425                         if (errno || !*optarg || *ep || first_hop > 255) {
426                                 fprintf(stderr,
427                                     "traceroute6: invalid min hoplimit.\n");
428                                 exit(1);
429                         }
430                         break;
431                 case 'g':
432                         hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno);
433                         if (hp == NULL) {
434                                 fprintf(stderr,
435                                     "traceroute6: unknown host %s\n", optarg);
436                                 exit(1);
437                         }
438 #ifdef USE_RFC2292BIS
439                         if (rth == NULL) {
440                                 /*
441                                  * XXX: We can't detect the number of
442                                  * intermediate nodes yet.
443                                  */
444                                 if ((rth = inet6_rth_init((void *)rtbuf,
445                                     sizeof(rtbuf), IPV6_RTHDR_TYPE_0,
446                                     0)) == NULL) {
447                                         fprintf(stderr,
448                                             "inet6_rth_init failed.\n");
449                                         exit(1);
450                                 }
451                         }
452                         if (inet6_rth_add((void *)rth,
453                             (struct in6_addr *)hp->h_addr)) {
454                                 fprintf(stderr,
455                                     "inet6_rth_add failed for %s\n",
456                                     optarg);
457                                 exit(1);
458                         }
459 #else  /* old advanced API */
460                         if (cmsg == NULL)
461                                 cmsg = inet6_rthdr_init(rtbuf, IPV6_RTHDR_TYPE_0);
462                         inet6_rthdr_add(cmsg, (struct in6_addr *)hp->h_addr,
463                             IPV6_RTHDR_LOOSE);
464 #endif
465                         freehostent(hp);
466                         break;
467                 case 'I':
468                         useproto = IPPROTO_ICMPV6;
469                         break;
470                 case 'l':
471                         lflag++;
472                         break;
473                 case 'm':
474                         ep = NULL;
475                         errno = 0;
476                         max_hops = strtoul(optarg, &ep, 0);
477                         if (errno || !*optarg || *ep || max_hops > 255) {
478                                 fprintf(stderr,
479                                     "traceroute6: invalid max hoplimit.\n");
480                                 exit(1);
481                         }
482                         break;
483                 case 'n':
484                         nflag++;
485                         break;
486                 case 'N':
487                         useproto = IPPROTO_NONE;
488                         break;
489                 case 'p':
490                         ep = NULL;
491                         errno = 0;
492                         lport = strtoul(optarg, &ep, 0);
493                         if (errno || !*optarg || *ep) {
494                                 fprintf(stderr, "traceroute6: invalid port.\n");
495                                 exit(1);
496                         }
497                         if (lport == 0 || lport != (lport & 0xffff)) {
498                                 fprintf(stderr,
499                                     "traceroute6: port out of range.\n");
500                                 exit(1);
501                         }
502                         port = lport & 0xffff;
503                         break;
504                 case 'q':
505                         ep = NULL;
506                         errno = 0;
507                         nprobes = strtoul(optarg, &ep, 0);
508                         if (errno || !*optarg || *ep) {
509                                 fprintf(stderr,
510                                     "traceroute6: invalid nprobes.\n");
511                                 exit(1);
512                         }
513                         if (nprobes < 1) {
514                                 fprintf(stderr,
515                                     "traceroute6: nprobes must be >0.\n");
516                                 exit(1);
517                         }
518                         break;
519                 case 'r':
520                         options |= SO_DONTROUTE;
521                         break;
522                 case 's':
523                         /*
524                          * set the ip source address of the outbound
525                          * probe (e.g., on a multi-homed host).
526                          */
527                         source = optarg;
528                         break;
529                 case 'S':
530                         useproto = IPPROTO_SCTP;
531                         break;
532                 case 'T':
533                         useproto = IPPROTO_TCP;
534                         break;
535                 case 'U':
536                         useproto = IPPROTO_UDP;
537                         break;
538                 case 'v':
539                         verbose++;
540                         break;
541                 case 'w':
542                         ep = NULL;
543                         errno = 0;
544                         waittime = strtoul(optarg, &ep, 0);
545                         if (errno || !*optarg || *ep) {
546                                 fprintf(stderr,
547                                     "traceroute6: invalid wait time.\n");
548                                 exit(1);
549                         }
550                         if (waittime < 1) {
551                                 fprintf(stderr,
552                                     "traceroute6: wait must be >= 1 sec.\n");
553                                 exit(1);
554                         }
555                         break;
556                 default:
557                         usage();
558                 }
559         argc -= optind;
560         argv += optind;
561
562         /*
563          * Open socket to send probe packets.
564          */
565         switch (useproto) {
566         case IPPROTO_ICMPV6:
567                 sndsock = rcvsock;
568                 break;
569         case IPPROTO_UDP:
570                 if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
571                         perror("socket(SOCK_DGRAM)");
572                         exit(5);
573                 }
574                 break;
575         case IPPROTO_NONE:
576         case IPPROTO_SCTP:
577         case IPPROTO_TCP:
578                 if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
579                         perror("socket(SOCK_RAW)");
580                         exit(5);
581                 }
582                 break;
583         default:
584                 fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
585                     useproto);
586                 exit(5);
587         }
588         if (max_hops < first_hop) {
589                 fprintf(stderr,
590                     "traceroute6: max hoplimit must be larger than first hoplimit.\n");
591                 exit(1);
592         }
593
594         /* revoke privs */
595         uid = getuid();
596         if (setresuid(uid, uid, uid) == -1) {
597                 perror("setresuid");
598                 exit(1);
599         }
600
601
602         if (argc < 1 || argc > 2)
603                 usage();
604
605 #if 1
606         setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
607 #else
608         setlinebuf(stdout);
609 #endif
610
611         memset(&hints, 0, sizeof(hints));
612         hints.ai_family = PF_INET6;
613         hints.ai_socktype = SOCK_RAW;
614         hints.ai_protocol = IPPROTO_ICMPV6;
615         hints.ai_flags = AI_CANONNAME;
616         error = getaddrinfo(*argv, NULL, &hints, &res);
617         if (error) {
618                 fprintf(stderr,
619                     "traceroute6: %s\n", gai_strerror(error));
620                 exit(1);
621         }
622         if (res->ai_addrlen != sizeof(Dst)) {
623                 fprintf(stderr,
624                     "traceroute6: size of sockaddr mismatch\n");
625                 exit(1);
626         }
627         memcpy(&Dst, res->ai_addr, res->ai_addrlen);
628         hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv;
629         if (!hostname) {
630                 fprintf(stderr, "traceroute6: not enough core\n");
631                 exit(1);
632         }
633         if (res->ai_next) {
634                 if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf,
635                     sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
636                         strlcpy(hbuf, "?", sizeof(hbuf));
637                 fprintf(stderr, "traceroute6: Warning: %s has multiple "
638                     "addresses; using %s\n", hostname, hbuf);
639         }
640
641         if (*++argv) {
642                 ep = NULL;
643                 errno = 0;
644                 datalen = strtoul(*argv, &ep, 0);
645                 if (errno || *ep) {
646                         fprintf(stderr,
647                             "traceroute6: invalid packet length.\n");
648                         exit(1);
649                 }
650         }
651         switch (useproto) {
652         case IPPROTO_ICMPV6:
653                 minlen = ICMP6ECHOLEN;
654                 break;
655         case IPPROTO_UDP:
656                 minlen = sizeof(struct udphdr);
657                 break;
658         case IPPROTO_NONE:
659                 minlen = 0;
660                 datalen = 0;
661                 break;
662         case IPPROTO_SCTP:
663                 minlen = sizeof(struct sctphdr);
664                 break;
665         case IPPROTO_TCP:
666                 minlen = sizeof(struct tcphdr);
667                 break;
668         default:
669                 fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
670                     useproto);
671                 exit(1);
672         }
673         if (datalen < minlen)
674                 datalen = minlen;
675         else if (datalen >= MAXPACKET) {
676                 fprintf(stderr,
677                     "traceroute6: packet size must be %zu <= s < %d.\n",
678                     minlen, MAXPACKET);
679                 exit(1);
680         }
681         if (useproto == IPPROTO_UDP)
682                 datalen -= sizeof(struct udphdr);
683         if ((useproto == IPPROTO_SCTP) && (datalen & 3)) {
684                 fprintf(stderr, 
685                     "traceroute6: packet size must be a multiple of 4.\n");
686                 exit(1);
687         }
688         outpacket = malloc(datalen);
689         if (!outpacket) {
690                 perror("malloc");
691                 exit(1);
692         }
693         (void) bzero((char *)outpacket, datalen);
694
695         /* initialize msghdr for receiving packets */
696         rcviov[0].iov_base = (caddr_t)packet;
697         rcviov[0].iov_len = sizeof(packet);
698         rcvmhdr.msg_name = (caddr_t)&Rcv;
699         rcvmhdr.msg_namelen = sizeof(Rcv);
700         rcvmhdr.msg_iov = rcviov;
701         rcvmhdr.msg_iovlen = 1;
702         rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
703             CMSG_SPACE(sizeof(int));
704         if ((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
705                 fprintf(stderr, "traceroute6: malloc failed\n");
706                 exit(1);
707         }
708         rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
709         rcvmhdr.msg_controllen = rcvcmsglen;
710
711         if (options & SO_DEBUG)
712                 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
713                     (char *)&on, sizeof(on));
714         if (options & SO_DONTROUTE)
715                 (void) setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
716                     (char *)&on, sizeof(on));
717 #ifdef IPSEC
718 #ifdef IPSEC_POLICY_IPSEC
719         /*
720          * do not raise error even if setsockopt fails, kernel may have ipsec
721          * turned off.
722          */
723         if (setpolicy(rcvsock, "in bypass") < 0)
724                 errx(1, "%s", ipsec_strerror());
725         if (setpolicy(rcvsock, "out bypass") < 0)
726                 errx(1, "%s", ipsec_strerror());
727 #else
728     {
729         int level = IPSEC_LEVEL_NONE;
730
731         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
732             sizeof(level));
733         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
734             sizeof(level));
735 #ifdef IP_AUTH_TRANS_LEVEL
736         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
737             sizeof(level));
738 #else
739         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
740             sizeof(level));
741 #endif
742 #ifdef IP_AUTH_NETWORK_LEVEL
743         (void)setsockopt(rcvsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
744             sizeof(level));
745 #endif
746     }
747 #endif /*IPSEC_POLICY_IPSEC*/
748 #endif /*IPSEC*/
749
750 #ifdef SO_SNDBUF
751         i = datalen;
752         if (i == 0)
753                 i = 1;
754         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
755             sizeof(i)) < 0) {
756                 perror("setsockopt(SO_SNDBUF)");
757                 exit(6);
758         }
759 #endif /* SO_SNDBUF */
760         if (options & SO_DEBUG)
761                 (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
762                     (char *)&on, sizeof(on));
763         if (options & SO_DONTROUTE)
764                 (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
765                     (char *)&on, sizeof(on));
766 #ifdef USE_RFC2292BIS
767         if (rth) {/* XXX: there is no library to finalize the header... */
768                 rth->ip6r_len = rth->ip6r_segleft * 2;
769                 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_RTHDR,
770                     (void *)rth, (rth->ip6r_len + 1) << 3)) {
771                         fprintf(stderr, "setsockopt(IPV6_RTHDR): %s\n",
772                             strerror(errno));
773                         exit(1);
774                 }
775         }
776 #else  /* old advanced API */
777         if (cmsg != NULL) {
778                 inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
779                 if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_PKTOPTIONS,
780                     rtbuf, cmsg->cmsg_len) < 0) {
781                         fprintf(stderr, "setsockopt(IPV6_PKTOPTIONS): %s\n",
782                             strerror(errno));
783                         exit(1);
784                 }
785         }
786 #endif /* USE_RFC2292BIS */
787 #ifdef IPSEC
788 #ifdef IPSEC_POLICY_IPSEC
789         /*
790          * do not raise error even if setsockopt fails, kernel may have ipsec
791          * turned off.
792          */
793         if (setpolicy(sndsock, "in bypass") < 0)
794                 errx(1, "%s", ipsec_strerror());
795         if (setpolicy(sndsock, "out bypass") < 0)
796                 errx(1, "%s", ipsec_strerror());
797 #else
798     {
799         int level = IPSEC_LEVEL_BYPASS;
800
801         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &level,
802             sizeof(level));
803         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_ESP_NETWORK_LEVEL, &level,
804             sizeof(level));
805 #ifdef IP_AUTH_TRANS_LEVEL
806         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &level,
807             sizeof(level));
808 #else
809         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_LEVEL, &level,
810             sizeof(level));
811 #endif
812 #ifdef IP_AUTH_NETWORK_LEVEL
813         (void)setsockopt(sndsock, IPPROTO_IPV6, IPV6_AUTH_NETWORK_LEVEL, &level,
814             sizeof(level));
815 #endif
816     }
817 #endif /*IPSEC_POLICY_IPSEC*/
818 #endif /*IPSEC*/
819
820         /*
821          * Source selection
822          */
823         bzero(&Src, sizeof(Src));
824         if (source) {
825                 struct addrinfo hints, *res;
826                 int error;
827
828                 memset(&hints, 0, sizeof(hints));
829                 hints.ai_family = AF_INET6;
830                 hints.ai_socktype = SOCK_DGRAM; /*dummy*/
831                 hints.ai_flags = AI_NUMERICHOST;
832                 error = getaddrinfo(source, "0", &hints, &res);
833                 if (error) {
834                         printf("traceroute6: %s: %s\n", source,
835                             gai_strerror(error));
836                         exit(1);
837                 }
838                 if (res->ai_addrlen > sizeof(Src)) {
839                         printf("traceroute6: %s: %s\n", source,
840                             gai_strerror(error));
841                         exit(1);
842                 }
843                 memcpy(&Src, res->ai_addr, res->ai_addrlen);
844                 freeaddrinfo(res);
845         } else {
846                 struct sockaddr_in6 Nxt;
847                 int dummy;
848                 socklen_t len;
849
850                 Nxt = Dst;
851                 Nxt.sin6_port = htons(DUMMY_PORT);
852                 if (cmsg != NULL)
853                         bcopy(inet6_rthdr_getaddr(cmsg, 1), &Nxt.sin6_addr,
854                             sizeof(Nxt.sin6_addr));
855                 if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
856                         perror("socket");
857                         exit(1);
858                 }
859                 if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) {
860                         perror("connect");
861                         exit(1);
862                 }
863                 len = sizeof(Src);
864                 if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) {
865                         perror("getsockname");
866                         exit(1);
867                 }
868                 if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len,
869                     src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) {
870                         fprintf(stderr, "getnameinfo failed for source\n");
871                         exit(1);
872                 }
873                 source = src0;
874                 close(dummy);
875         }
876
877         Src.sin6_port = htons(0);
878         if (bind(sndsock, (struct sockaddr *)&Src, Src.sin6_len) < 0) {
879                 perror("bind");
880                 exit(1);
881         }
882
883         {
884                 socklen_t len;
885
886                 len = sizeof(Src);
887                 if (getsockname(sndsock, (struct sockaddr *)&Src, &len) < 0) {
888                         perror("getsockname");
889                         exit(1);
890                 }
891                 srcport = ntohs(Src.sin6_port);
892         }
893
894         if (as_path) {
895                 asn = as_setup(as_server);
896                 if (asn == NULL) {
897                         fprintf(stderr,
898                             "traceroute6: as_setup failed, AS# lookups"
899                             " disabled\n");
900                         (void)fflush(stderr);
901                         as_path = 0;
902                 }
903         }
904
905         /*
906          * Message to users
907          */
908         if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf,
909             sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
910                 strlcpy(hbuf, "(invalid)", sizeof(hbuf));
911         fprintf(stderr, "traceroute6");
912         fprintf(stderr, " to %s (%s)", hostname, hbuf);
913         if (source)
914                 fprintf(stderr, " from %s", source);
915         fprintf(stderr, ", %lu hops max, %lu byte packets\n",
916             max_hops,
917             datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
918         (void) fflush(stderr);
919
920         if (first_hop > 1)
921                 printf("Skipping %lu intermediate hops\n", first_hop - 1);
922
923         /*
924          * Main loop
925          */
926         for (hops = first_hop; hops <= max_hops; ++hops) {
927                 struct in6_addr lastaddr;
928                 int got_there = 0;
929                 unsigned unreachable = 0;
930
931                 printf("%2lu ", hops);
932                 bzero(&lastaddr, sizeof(lastaddr));
933                 for (probe = 0; probe < nprobes; ++probe) {
934                         int cc;
935                         struct timeval t1, t2;
936
937                         (void) gettimeofday(&t1, NULL);
938                         send_probe(++seq, hops);
939                         while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
940                                 (void) gettimeofday(&t2, NULL);
941                                 if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) {
942                                         if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
943                                             &lastaddr)) {
944                                                 if (probe > 0)
945                                                         fputs("\n   ", stdout);
946                                                 print(&rcvmhdr, cc);
947                                                 lastaddr = Rcv.sin6_addr;
948                                         }
949                                         printf("  %.3f ms", deltaT(&t1, &t2));
950                                         if (type == ICMP6_DST_UNREACH) {
951                                                 switch (code) {
952                                                 case ICMP6_DST_UNREACH_NOROUTE:
953                                                         ++unreachable;
954                                                         printf(" !N");
955                                                         break;
956                                                 case ICMP6_DST_UNREACH_ADMIN:
957                                                         ++unreachable;
958                                                         printf(" !P");
959                                                         break;
960                                                 case ICMP6_DST_UNREACH_NOTNEIGHBOR:
961                                                         ++unreachable;
962                                                         printf(" !S");
963                                                         break;
964                                                 case ICMP6_DST_UNREACH_ADDR:
965                                                         ++unreachable;
966                                                         printf(" !A");
967                                                         break;
968                                                 case ICMP6_DST_UNREACH_NOPORT:
969                                                         if (rcvhlim >= 0 &&
970                                                             rcvhlim <= 1)
971                                                                 printf(" !");
972                                                         ++got_there;
973                                                         break;
974                                                 }
975                                         } else if (type == ICMP6_ECHO_REPLY) {
976                                                 if (rcvhlim >= 0 &&
977                                                     rcvhlim <= 1)
978                                                         printf(" !");
979                                                 ++got_there;
980                                         }
981                                         break;
982                                 } else if (deltaT(&t1, &t2) > waittime * 1000) {
983                                         cc = 0;
984                                         break;
985                                 }
986                         }
987                         if (cc == 0)
988                                 printf(" *");
989                         (void) fflush(stdout);
990                 }
991                 putchar('\n');
992                 if (got_there ||
993                     (unreachable > 0 && unreachable >= ((nprobes + 1) / 2))) {
994                         exit(0);
995                 }
996         }
997         if (as_path)
998                 as_shutdown(asn);
999
1000         exit(0);
1001 }
1002
1003 int
1004 wait_for_reply(int sock, struct msghdr *mhdr)
1005 {
1006 #ifdef HAVE_POLL
1007         struct pollfd pfd[1];
1008         int cc = 0;
1009
1010         pfd[0].fd = sock;
1011         pfd[0].events = POLLIN;
1012         pfd[0].revents = 0;
1013
1014         if (poll(pfd, 1, waittime * 1000) > 0)
1015                 cc = recvmsg(rcvsock, mhdr, 0);
1016
1017         return (cc);
1018 #else
1019         fd_set *fdsp;
1020         struct timeval wait;
1021         int cc = 0, fdsn;
1022
1023         fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
1024         if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)
1025                 err(1, "malloc");
1026         memset(fdsp, 0, fdsn);
1027         FD_SET(sock, fdsp);
1028         wait.tv_sec = waittime; wait.tv_usec = 0;
1029
1030         if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)
1031                 cc = recvmsg(rcvsock, mhdr, 0);
1032
1033         free(fdsp);
1034         return (cc);
1035 #endif
1036 }
1037
1038 #ifdef IPSEC
1039 #ifdef IPSEC_POLICY_IPSEC
1040 int
1041 setpolicy(so, policy)
1042         int so;
1043         char *policy;
1044 {
1045         char *buf;
1046
1047         buf = ipsec_set_policy(policy, strlen(policy));
1048         if (buf == NULL) {
1049                 warnx("%s", ipsec_strerror());
1050                 return -1;
1051         }
1052         (void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,
1053             buf, ipsec_get_policylen(buf));
1054
1055         free(buf);
1056
1057         return 0;
1058 }
1059 #endif
1060 #endif
1061
1062 void
1063 send_probe(int seq, u_long hops)
1064 {
1065         struct icmp6_hdr *icp;
1066         struct sctphdr *sctp;
1067         struct sctp_chunkhdr *chk;
1068         struct sctp_init_chunk *init;
1069         struct sctp_paramhdr *param;
1070         struct tcphdr *tcp;
1071         int i;
1072
1073         i = hops;
1074         if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
1075             (char *)&i, sizeof(i)) < 0) {
1076                 perror("setsockopt IPV6_UNICAST_HOPS");
1077         }
1078
1079         Dst.sin6_port = htons(port + seq);
1080
1081         switch (useproto) {
1082         case IPPROTO_ICMPV6:
1083                 icp = (struct icmp6_hdr *)outpacket;
1084
1085                 icp->icmp6_type = ICMP6_ECHO_REQUEST;
1086                 icp->icmp6_code = 0;
1087                 icp->icmp6_cksum = 0;
1088                 icp->icmp6_id = ident;
1089                 icp->icmp6_seq = htons(seq);
1090                 break;
1091         case IPPROTO_UDP:
1092                 break;
1093         case IPPROTO_NONE:
1094                 /* No space for anything. No harm as seq/tv32 are decorative. */
1095                 break;
1096         case IPPROTO_SCTP:
1097                 sctp = (struct sctphdr *)outpacket;
1098
1099                 sctp->src_port = htons(ident);
1100                 sctp->dest_port = htons(port + seq);
1101                 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1102                     sizeof(struct sctp_init_chunk))) {
1103                         sctp->v_tag = 0;
1104                 } else {
1105                         sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
1106                 }
1107                 sctp->checksum = htonl(0);
1108                 if (datalen >= (u_long)(sizeof(struct sctphdr) +
1109                     sizeof(struct sctp_init_chunk))) {
1110                         /*
1111                          * Send a packet containing an INIT chunk. This works
1112                          * better in case of firewalls on the path, but
1113                          * results in a probe packet containing at least
1114                          * 32 bytes of payload. For shorter payloads, use
1115                          * SHUTDOWN-ACK chunks.
1116                          */
1117                         init = (struct sctp_init_chunk *)(sctp + 1);
1118                         init->ch.chunk_type = SCTP_INITIATION;
1119                         init->ch.chunk_flags = 0;
1120                         init->ch.chunk_length = htons((u_int16_t)(datalen -
1121                             sizeof(struct sctphdr)));
1122                         init->init.initiate_tag = (sctp->src_port << 16) |
1123                             sctp->dest_port;
1124                         init->init.a_rwnd = htonl(1500);
1125                         init->init.num_outbound_streams = htons(1);
1126                         init->init.num_inbound_streams = htons(1);
1127                         init->init.initial_tsn = htonl(0);
1128                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1129                             sizeof(struct sctp_init_chunk) +
1130                             sizeof(struct sctp_paramhdr))) {
1131                                 param = (struct sctp_paramhdr *)(init + 1);
1132                                 param->param_type = htons(SCTP_PAD);
1133                                 param->param_length =
1134                                     htons((u_int16_t)(datalen -
1135                                     sizeof(struct sctphdr) -
1136                                     sizeof(struct sctp_init_chunk)));
1137                         }
1138                 } else {
1139                         /*
1140                          * Send a packet containing a SHUTDOWN-ACK chunk,
1141                          * possibly followed by a PAD chunk.
1142                          */
1143                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1144                             sizeof(struct sctp_chunkhdr))) {
1145                                 chk = (struct sctp_chunkhdr *)(sctp + 1);
1146                                 chk->chunk_type = SCTP_SHUTDOWN_ACK;
1147                                 chk->chunk_flags = 0;
1148                                 chk->chunk_length = htons(4);
1149                         }
1150                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1151                             2 * sizeof(struct sctp_chunkhdr))) {
1152                                 chk = chk + 1;
1153                                 chk->chunk_type = SCTP_PAD_CHUNK;
1154                                 chk->chunk_flags = 0;
1155                                 chk->chunk_length = htons((u_int16_t)(datalen -
1156                                     sizeof(struct sctphdr) -
1157                                     sizeof(struct sctp_chunkhdr)));
1158                         }
1159                 }
1160                 sctp->checksum = sctp_crc32c(outpacket, datalen);
1161                 break;
1162         case IPPROTO_TCP:
1163                 tcp = (struct tcphdr *)outpacket;
1164
1165                 tcp->th_sport = htons(ident);
1166                 tcp->th_dport = htons(port + seq);
1167                 tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1168                 tcp->th_ack = 0;
1169                 tcp->th_off = 5;
1170                 tcp->th_flags = TH_SYN;
1171                 tcp->th_sum = 0;
1172                 tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
1173                 break;
1174         default:
1175                 fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
1176                 exit(1);
1177         }
1178
1179         i = sendto(sndsock, (char *)outpacket, datalen, 0,
1180             (struct sockaddr *)&Dst, Dst.sin6_len);
1181         if (i < 0 || (u_long)i != datalen)  {
1182                 if (i < 0)
1183                         perror("sendto");
1184                 printf("traceroute6: wrote %s %lu chars, ret=%d\n",
1185                     hostname, datalen, i);
1186                 (void) fflush(stdout);
1187         }
1188 }
1189
1190 int
1191 get_hoplim(struct msghdr *mhdr)
1192 {
1193         struct cmsghdr *cm;
1194
1195         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1196             cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1197                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1198                     cm->cmsg_type == IPV6_HOPLIMIT &&
1199                     cm->cmsg_len == CMSG_LEN(sizeof(int)))
1200                         return (*(int *)CMSG_DATA(cm));
1201         }
1202
1203         return (-1);
1204 }
1205
1206 double
1207 deltaT(struct timeval *t1p, struct timeval *t2p)
1208 {
1209         double dt;
1210
1211         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1212             (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1213         return (dt);
1214 }
1215
1216 /*
1217  * Convert an ICMP "type" field to a printable string.
1218  */
1219 const char *
1220 pr_type(int t0)
1221 {
1222         u_char t = t0 & 0xff;
1223         const char *cp;
1224
1225         switch (t) {
1226         case ICMP6_DST_UNREACH:
1227                 cp = "Destination Unreachable";
1228                 break;
1229         case ICMP6_PACKET_TOO_BIG:
1230                 cp = "Packet Too Big";
1231                 break;
1232         case ICMP6_TIME_EXCEEDED:
1233                 cp = "Time Exceeded";
1234                 break;
1235         case ICMP6_PARAM_PROB:
1236                 cp = "Parameter Problem";
1237                 break;
1238         case ICMP6_ECHO_REQUEST:
1239                 cp = "Echo Request";
1240                 break;
1241         case ICMP6_ECHO_REPLY:
1242                 cp = "Echo Reply";
1243                 break;
1244         case ICMP6_MEMBERSHIP_QUERY:
1245                 cp = "Group Membership Query";
1246                 break;
1247         case ICMP6_MEMBERSHIP_REPORT:
1248                 cp = "Group Membership Report";
1249                 break;
1250         case ICMP6_MEMBERSHIP_REDUCTION:
1251                 cp = "Group Membership Reduction";
1252                 break;
1253         case ND_ROUTER_SOLICIT:
1254                 cp = "Router Solicitation";
1255                 break;
1256         case ND_ROUTER_ADVERT:
1257                 cp = "Router Advertisement";
1258                 break;
1259         case ND_NEIGHBOR_SOLICIT:
1260                 cp = "Neighbor Solicitation";
1261                 break;
1262         case ND_NEIGHBOR_ADVERT:
1263                 cp = "Neighbor Advertisement";
1264                 break;
1265         case ND_REDIRECT:
1266                 cp = "Redirect";
1267                 break;
1268         default:
1269                 cp = "Unknown";
1270                 break;
1271         }
1272         return cp;
1273 }
1274
1275 int
1276 packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code)
1277 {
1278         struct icmp6_hdr *icp;
1279         struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1280         char *buf = (char *)mhdr->msg_iov[0].iov_base;
1281         struct cmsghdr *cm;
1282         int *hlimp;
1283         char hbuf[NI_MAXHOST];
1284
1285 #ifdef OLDRAWSOCKET
1286         int hlen;
1287         struct ip6_hdr *ip;
1288 #endif
1289
1290 #ifdef OLDRAWSOCKET
1291         ip = (struct ip6_hdr *) buf;
1292         hlen = sizeof(struct ip6_hdr);
1293         if (cc < hlen + sizeof(struct icmp6_hdr)) {
1294                 if (verbose) {
1295                         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1296                             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1297                                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1298                         printf("packet too short (%d bytes) from %s\n", cc,
1299                             hbuf);
1300                 }
1301                 return (0);
1302         }
1303         cc -= hlen;
1304         icp = (struct icmp6_hdr *)(buf + hlen);
1305 #else
1306         if (cc < (int)sizeof(struct icmp6_hdr)) {
1307                 if (verbose) {
1308                         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1309                             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1310                                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1311                         printf("data too short (%d bytes) from %s\n", cc, hbuf);
1312                 }
1313                 return (0);
1314         }
1315         icp = (struct icmp6_hdr *)buf;
1316 #endif
1317         /* get optional information via advanced API */
1318         rcvpktinfo = NULL;
1319         hlimp = NULL;
1320         for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
1321             cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
1322                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1323                     cm->cmsg_type == IPV6_PKTINFO &&
1324                     cm->cmsg_len ==
1325                     CMSG_LEN(sizeof(struct in6_pktinfo)))
1326                         rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));
1327
1328                 if (cm->cmsg_level == IPPROTO_IPV6 &&
1329                     cm->cmsg_type == IPV6_HOPLIMIT &&
1330                     cm->cmsg_len == CMSG_LEN(sizeof(int)))
1331                         hlimp = (int *)CMSG_DATA(cm);
1332         }
1333         if (rcvpktinfo == NULL || hlimp == NULL) {
1334                 warnx("failed to get received hop limit or packet info");
1335 #if 0
1336                 return (0);
1337 #else
1338                 rcvhlim = 0;    /*XXX*/
1339 #endif
1340         }
1341         else
1342                 rcvhlim = *hlimp;
1343
1344         *type = icp->icmp6_type;
1345         *code = icp->icmp6_code;
1346         if ((*type == ICMP6_TIME_EXCEEDED &&
1347             *code == ICMP6_TIME_EXCEED_TRANSIT) ||
1348             (*type == ICMP6_DST_UNREACH)) {
1349                 struct ip6_hdr *hip;
1350                 struct icmp6_hdr *icmp;
1351                 struct sctp_init_chunk *init;
1352                 struct sctphdr *sctp;
1353                 struct tcphdr *tcp;
1354                 struct udphdr *udp;
1355                 void *up;
1356
1357                 hip = (struct ip6_hdr *)(icp + 1);
1358                 if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) {
1359                         if (verbose)
1360                                 warnx("failed to get upper layer header");
1361                         return (0);
1362                 }
1363                 switch (useproto) {
1364                 case IPPROTO_ICMPV6:
1365                         icmp = (struct icmp6_hdr *)up;
1366                         if (icmp->icmp6_id == ident &&
1367                             icmp->icmp6_seq == htons(seq))
1368                                 return (1);
1369                         break;
1370                 case IPPROTO_UDP:
1371                         udp = (struct udphdr *)up;
1372                         if (udp->uh_sport == htons(srcport) &&
1373                             udp->uh_dport == htons(port + seq))
1374                                 return (1);
1375                         break;
1376                 case IPPROTO_SCTP:
1377                         sctp = (struct sctphdr *)up;
1378                         if (sctp->src_port != htons(ident) ||
1379                             sctp->dest_port != htons(port + seq)) {
1380                                 break;
1381                         }
1382                         if (datalen >= (u_long)(sizeof(struct sctphdr) +
1383                             sizeof(struct sctp_init_chunk))) {
1384                                 if (sctp->v_tag != 0) {
1385                                         break;
1386                                 }
1387                                 init = (struct sctp_init_chunk *)(sctp + 1);
1388                                 /* Check the initiate tag, if available. */
1389                                 if ((char *)&init->init.a_rwnd > buf + cc) {
1390                                         return (1);
1391                                 }
1392                                 if (init->init.initiate_tag == (u_int32_t)
1393                                     ((sctp->src_port << 16) | sctp->dest_port)) {
1394                                         return (1);
1395                                 }
1396                         } else {
1397                                 if (sctp->v_tag ==
1398                                     (u_int32_t)((sctp->src_port << 16) |
1399                                     sctp->dest_port)) {
1400                                         return (1);
1401                                 }
1402                         }
1403                         break;
1404                 case IPPROTO_TCP:
1405                         tcp = (struct tcphdr *)up;
1406                         if (tcp->th_sport == htons(ident) &&
1407                             tcp->th_dport == htons(port + seq) &&
1408                             tcp->th_seq ==
1409                             (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
1410                                 return (1);
1411                         break;
1412                 case IPPROTO_NONE:
1413                         return (1);
1414                 default:
1415                         fprintf(stderr, "Unknown probe proto %d.\n", useproto);
1416                         break;
1417                 }
1418         } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) {
1419                 if (icp->icmp6_id == ident &&
1420                     icp->icmp6_seq == htons(seq))
1421                         return (1);
1422         }
1423         if (verbose) {
1424                 char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
1425                 u_int8_t *p;
1426                 int i;
1427
1428                 if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1429                     sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)
1430                         strlcpy(sbuf, "invalid", sizeof(sbuf));
1431                 printf("\n%d bytes from %s to %s", cc, sbuf,
1432                     rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1433                     dbuf, sizeof(dbuf)) : "?");
1434                 printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type),
1435                     *code);
1436                 p = (u_int8_t *)(icp + 1);
1437 #define WIDTH   16
1438                 for (i = 0; i < cc; i++) {
1439                         if (i % WIDTH == 0)
1440                                 printf("%04x:", i);
1441                         if (i % 4 == 0)
1442                                 printf(" ");
1443                         printf("%02x", p[i]);
1444                         if (i % WIDTH == WIDTH - 1)
1445                                 printf("\n");
1446                 }
1447                 if (cc % WIDTH != 0)
1448                         printf("\n");
1449         }
1450         return (0);
1451 }
1452
1453 /*
1454  * Increment pointer until find the UDP or ICMP header.
1455  */
1456 void *
1457 get_uphdr(struct ip6_hdr *ip6, u_char *lim)
1458 {
1459         u_char *cp = (u_char *)ip6, nh;
1460         int hlen;
1461         static u_char none_hdr[1]; /* Fake pointer for IPPROTO_NONE. */
1462
1463         if (cp + sizeof(*ip6) > lim)
1464                 return (NULL);
1465
1466         nh = ip6->ip6_nxt;
1467         cp += sizeof(struct ip6_hdr);
1468
1469         while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
1470                 switch (nh) {
1471                 case IPPROTO_ESP:
1472                         return (NULL);
1473                 case IPPROTO_ICMPV6:
1474                         return (useproto == nh ? cp : NULL);
1475                 case IPPROTO_SCTP:
1476                 case IPPROTO_TCP:
1477                 case IPPROTO_UDP:
1478                         return (useproto == nh ? cp : NULL);
1479                 case IPPROTO_NONE:
1480                         return (useproto == nh ? none_hdr : NULL);
1481                 case IPPROTO_FRAGMENT:
1482                         hlen = sizeof(struct ip6_frag);
1483                         nh = ((struct ip6_frag *)cp)->ip6f_nxt;
1484                         break;
1485                 case IPPROTO_AH:
1486                         hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
1487                         nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1488                         break;
1489                 default:
1490                         hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
1491                         nh = ((struct ip6_ext *)cp)->ip6e_nxt;
1492                         break;
1493                 }
1494
1495                 cp += hlen;
1496         }
1497
1498         return (NULL);
1499 }
1500
1501 void
1502 print(struct msghdr *mhdr, int cc)
1503 {
1504         struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
1505         char hbuf[NI_MAXHOST];
1506
1507         if (getnameinfo((struct sockaddr *)from, from->sin6_len,
1508             hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
1509                 strlcpy(hbuf, "invalid", sizeof(hbuf));
1510         if (as_path)
1511                 printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6));
1512         if (nflag)
1513                 printf(" %s", hbuf);
1514         else if (lflag)
1515                 printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);
1516         else
1517                 printf(" %s", inetname((struct sockaddr *)from));
1518
1519         if (verbose) {
1520 #ifdef OLDRAWSOCKET
1521                 printf(" %d bytes to %s", cc,
1522                     rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1523                     hbuf, sizeof(hbuf)) : "?");
1524 #else
1525                 printf(" %d bytes of data to %s", cc,
1526                     rcvpktinfo ?  inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
1527                     hbuf, sizeof(hbuf)) : "?");
1528 #endif
1529         }
1530 }
1531
1532 /*
1533  * Construct an Internet address representation.
1534  * If the nflag has been supplied, give
1535  * numeric value, otherwise try for symbolic name.
1536  */
1537 const char *
1538 inetname(struct sockaddr *sa)
1539 {
1540         static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
1541         static int first = 1;
1542         char *cp;
1543
1544         if (first && !nflag) {
1545                 first = 0;
1546                 if (gethostname(domain, sizeof(domain)) == 0 &&
1547                     (cp = strchr(domain, '.')))
1548                         (void) strlcpy(domain, cp + 1, sizeof(domain));
1549                 else
1550                         domain[0] = 0;
1551         }
1552         cp = NULL;
1553         if (!nflag) {
1554                 if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1555                     NI_NAMEREQD) == 0) {
1556                         if ((cp = strchr(line, '.')) &&
1557                             !strcmp(cp + 1, domain))
1558                                 *cp = 0;
1559                         cp = line;
1560                 }
1561         }
1562         if (cp)
1563                 return cp;
1564
1565         if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,
1566             NI_NUMERICHOST) != 0)
1567                 strlcpy(line, "invalid", sizeof(line));
1568         return line;
1569 }
1570
1571 /*
1572  * CRC32C routine for the Stream Control Transmission Protocol
1573  */
1574
1575 #define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
1576
1577 static u_int32_t crc_c[256] = {
1578         0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
1579         0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
1580         0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
1581         0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
1582         0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
1583         0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
1584         0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
1585         0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
1586         0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
1587         0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
1588         0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
1589         0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
1590         0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
1591         0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
1592         0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
1593         0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
1594         0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
1595         0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
1596         0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
1597         0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
1598         0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
1599         0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
1600         0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
1601         0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
1602         0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
1603         0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
1604         0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
1605         0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
1606         0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
1607         0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
1608         0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
1609         0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
1610         0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
1611         0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
1612         0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
1613         0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
1614         0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
1615         0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
1616         0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
1617         0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
1618         0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
1619         0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
1620         0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
1621         0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
1622         0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
1623         0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
1624         0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
1625         0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
1626         0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
1627         0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
1628         0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
1629         0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
1630         0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
1631         0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
1632         0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
1633         0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
1634         0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
1635         0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
1636         0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
1637         0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
1638         0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
1639         0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
1640         0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
1641         0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
1642 };
1643
1644 u_int32_t
1645 sctp_crc32c(void *packet, u_int32_t len)
1646 {
1647         u_int32_t i, crc32c;
1648         u_int8_t byte0, byte1, byte2, byte3;
1649         u_int8_t *buf = (u_int8_t *)packet;
1650
1651         crc32c = ~0;
1652         for (i = 0; i < len; i++)
1653                 CRC32C(crc32c, buf[i]);
1654         crc32c = ~crc32c;
1655         byte0  = crc32c & 0xff;
1656         byte1  = (crc32c>>8) & 0xff;
1657         byte2  = (crc32c>>16) & 0xff;
1658         byte3  = (crc32c>>24) & 0xff;
1659         crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
1660         return htonl(crc32c);
1661 }
1662
1663 u_int16_t
1664 in_cksum(u_int16_t *addr, int len)
1665 {
1666         int nleft = len;
1667         u_int16_t *w = addr;
1668         u_int16_t answer;
1669         int sum = 0;
1670
1671         /*
1672          *  Our algorithm is simple, using a 32 bit accumulator (sum),
1673          *  we add sequential 16 bit words to it, and at the end, fold
1674          *  back all the carry bits from the top 16 bits into the lower
1675          *  16 bits.
1676          */
1677         while (nleft > 1)  {
1678                 sum += *w++;
1679                 nleft -= 2;
1680         }
1681
1682         /* mop up an odd byte, if necessary */
1683         if (nleft == 1)
1684                 sum += *(u_char *)w;
1685
1686         /*
1687          * add back carry outs from top 16 bits to low 16 bits
1688          */
1689         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1690         sum += (sum >> 16);                     /* add carry */
1691         answer = ~sum;                          /* truncate to 16 bits */
1692         return (answer);
1693 }
1694
1695 u_int16_t
1696 tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
1697     void *payload, u_int32_t len)
1698 {
1699         struct {
1700                 struct in6_addr src;
1701                 struct in6_addr dst;
1702                 u_int32_t len;
1703                 u_int8_t zero[3];
1704                 u_int8_t next;
1705         } pseudo_hdr;
1706         u_int16_t sum[2];
1707
1708         pseudo_hdr.src = src->sin6_addr;
1709         pseudo_hdr.dst = dst->sin6_addr;
1710         pseudo_hdr.len = htonl(len);
1711         pseudo_hdr.zero[0] = 0;
1712         pseudo_hdr.zero[1] = 0;
1713         pseudo_hdr.zero[2] = 0;
1714         pseudo_hdr.next = IPPROTO_TCP;
1715
1716         sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
1717         sum[0] = in_cksum(payload, len);
1718
1719         return (~in_cksum(sum, sizeof(sum)));
1720 }
1721
1722 void
1723 usage(void)
1724 {
1725
1726         fprintf(stderr,
1727 "usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
1728 "       [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"
1729 "       [datalen]\n");
1730         exit(1);
1731 }