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