xref: /aosp_15_r20/external/iputils/traceroute6.c (revision bd1f8aeb6080fa6544ec30aeca3eb4da100f359f)
1*bd1f8aebSAndroid Build Coastguard Worker /*
2*bd1f8aebSAndroid Build Coastguard Worker  *      Modified for NRL 4.4BSD IPv6 release.
3*bd1f8aebSAndroid Build Coastguard Worker  *      07/31/96 bgp
4*bd1f8aebSAndroid Build Coastguard Worker  *
5*bd1f8aebSAndroid Build Coastguard Worker  *      Search for "#ifdef NRL" to find the changes.
6*bd1f8aebSAndroid Build Coastguard Worker  */
7*bd1f8aebSAndroid Build Coastguard Worker 
8*bd1f8aebSAndroid Build Coastguard Worker /*
9*bd1f8aebSAndroid Build Coastguard Worker  *	Modified for Linux IPv6 by Pedro Roque <[email protected]>
10*bd1f8aebSAndroid Build Coastguard Worker  *	31/07/1996
11*bd1f8aebSAndroid Build Coastguard Worker  *
12*bd1f8aebSAndroid Build Coastguard Worker  *	As ICMP error messages for IPv6 now include more than 8 bytes
13*bd1f8aebSAndroid Build Coastguard Worker  *	UDP datagrams are now sent via an UDP socket instead of magic
14*bd1f8aebSAndroid Build Coastguard Worker  *	RAW socket tricks.
15*bd1f8aebSAndroid Build Coastguard Worker  *
16*bd1f8aebSAndroid Build Coastguard Worker  *	Original copyright and comments left intact. They might not
17*bd1f8aebSAndroid Build Coastguard Worker  *	match the code anymore.
18*bd1f8aebSAndroid Build Coastguard Worker  */
19*bd1f8aebSAndroid Build Coastguard Worker 
20*bd1f8aebSAndroid Build Coastguard Worker /*-
21*bd1f8aebSAndroid Build Coastguard Worker  * Copyright (c) 1990, 1993
22*bd1f8aebSAndroid Build Coastguard Worker  *	The Regents of the University of California.  All rights reserved.
23*bd1f8aebSAndroid Build Coastguard Worker  *
24*bd1f8aebSAndroid Build Coastguard Worker  * This code is derived from software contributed to Berkeley by
25*bd1f8aebSAndroid Build Coastguard Worker  * Van Jacobson.
26*bd1f8aebSAndroid Build Coastguard Worker  *
27*bd1f8aebSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
28*bd1f8aebSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
29*bd1f8aebSAndroid Build Coastguard Worker  * are met:
30*bd1f8aebSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
31*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
32*bd1f8aebSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
33*bd1f8aebSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
34*bd1f8aebSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
35*bd1f8aebSAndroid Build Coastguard Worker  * 3. All advertising materials mentioning features or use of this software
36*bd1f8aebSAndroid Build Coastguard Worker  *    must display the following acknowledgement:
37*bd1f8aebSAndroid Build Coastguard Worker  *	This product includes software developed by the University of
38*bd1f8aebSAndroid Build Coastguard Worker  *	California, Berkeley and its contributors.
39*bd1f8aebSAndroid Build Coastguard Worker  * 4. Neither the name of the University nor the names of its contributors
40*bd1f8aebSAndroid Build Coastguard Worker  *    may be used to endorse or promote products derived from this software
41*bd1f8aebSAndroid Build Coastguard Worker  *    without specific prior written permission.
42*bd1f8aebSAndroid Build Coastguard Worker  *
43*bd1f8aebSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44*bd1f8aebSAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45*bd1f8aebSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46*bd1f8aebSAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47*bd1f8aebSAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48*bd1f8aebSAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49*bd1f8aebSAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50*bd1f8aebSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51*bd1f8aebSAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52*bd1f8aebSAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53*bd1f8aebSAndroid Build Coastguard Worker  * SUCH DAMAGE.
54*bd1f8aebSAndroid Build Coastguard Worker  */
55*bd1f8aebSAndroid Build Coastguard Worker 
56*bd1f8aebSAndroid Build Coastguard Worker #ifndef lint
57*bd1f8aebSAndroid Build Coastguard Worker char copyright[] =
58*bd1f8aebSAndroid Build Coastguard Worker "@(#) Copyright (c) 1990, 1993\n\
59*bd1f8aebSAndroid Build Coastguard Worker 	The Regents of the University of California.  All rights reserved.\n";
60*bd1f8aebSAndroid Build Coastguard Worker #endif /* not lint */
61*bd1f8aebSAndroid Build Coastguard Worker 
62*bd1f8aebSAndroid Build Coastguard Worker /*
63*bd1f8aebSAndroid Build Coastguard Worker  * traceroute host  - trace the route ip packets follow going to "host".
64*bd1f8aebSAndroid Build Coastguard Worker  *
65*bd1f8aebSAndroid Build Coastguard Worker  * Attempt to trace the route an ip packet would follow to some
66*bd1f8aebSAndroid Build Coastguard Worker  * internet host.  We find out intermediate hops by launching probe
67*bd1f8aebSAndroid Build Coastguard Worker  * packets with a small ttl (time to live) then listening for an
68*bd1f8aebSAndroid Build Coastguard Worker  * icmp "time exceeded" reply from a gateway.  We start our probes
69*bd1f8aebSAndroid Build Coastguard Worker  * with a ttl of one and increase by one until we get an icmp "port
70*bd1f8aebSAndroid Build Coastguard Worker  * unreachable" (which means we got to "host") or hit a max (which
71*bd1f8aebSAndroid Build Coastguard Worker  * defaults to 30 hops & can be changed with the -m flag).  Three
72*bd1f8aebSAndroid Build Coastguard Worker  * probes (change with -q flag) are sent at each ttl setting and a
73*bd1f8aebSAndroid Build Coastguard Worker  * line is printed showing the ttl, address of the gateway and
74*bd1f8aebSAndroid Build Coastguard Worker  * round trip time of each probe.  If the probe answers come from
75*bd1f8aebSAndroid Build Coastguard Worker  * different gateways, the address of each responding system will
76*bd1f8aebSAndroid Build Coastguard Worker  * be printed.  If there is no response within a 5 sec. timeout
77*bd1f8aebSAndroid Build Coastguard Worker  * interval (changed with the -w flag), a "*" is printed for that
78*bd1f8aebSAndroid Build Coastguard Worker  * probe.
79*bd1f8aebSAndroid Build Coastguard Worker  *
80*bd1f8aebSAndroid Build Coastguard Worker  * Probe packets are UDP format.  We don't want the destination
81*bd1f8aebSAndroid Build Coastguard Worker  * host to process them so the destination port is set to an
82*bd1f8aebSAndroid Build Coastguard Worker  * unlikely value (if some clod on the destination is using that
83*bd1f8aebSAndroid Build Coastguard Worker  * value, it can be changed with the -p flag).
84*bd1f8aebSAndroid Build Coastguard Worker  *
85*bd1f8aebSAndroid Build Coastguard Worker  * A sample use might be:
86*bd1f8aebSAndroid Build Coastguard Worker  *
87*bd1f8aebSAndroid Build Coastguard Worker  *     [yak 71]% traceroute nis.nsf.net.
88*bd1f8aebSAndroid Build Coastguard Worker  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
89*bd1f8aebSAndroid Build Coastguard Worker  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
90*bd1f8aebSAndroid Build Coastguard Worker  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
91*bd1f8aebSAndroid Build Coastguard Worker  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
92*bd1f8aebSAndroid Build Coastguard Worker  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
93*bd1f8aebSAndroid Build Coastguard Worker  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
94*bd1f8aebSAndroid Build Coastguard Worker  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
95*bd1f8aebSAndroid Build Coastguard Worker  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
96*bd1f8aebSAndroid Build Coastguard Worker  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
97*bd1f8aebSAndroid Build Coastguard Worker  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
98*bd1f8aebSAndroid Build Coastguard Worker  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
99*bd1f8aebSAndroid Build Coastguard Worker  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
100*bd1f8aebSAndroid Build Coastguard Worker  *
101*bd1f8aebSAndroid Build Coastguard Worker  * Note that lines 2 & 3 are the same.  This is due to a buggy
102*bd1f8aebSAndroid Build Coastguard Worker  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
103*bd1f8aebSAndroid Build Coastguard Worker  * packets with a zero ttl.
104*bd1f8aebSAndroid Build Coastguard Worker  *
105*bd1f8aebSAndroid Build Coastguard Worker  * A more interesting example is:
106*bd1f8aebSAndroid Build Coastguard Worker  *
107*bd1f8aebSAndroid Build Coastguard Worker  *     [yak 72]% traceroute allspice.lcs.mit.edu.
108*bd1f8aebSAndroid Build Coastguard Worker  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
109*bd1f8aebSAndroid Build Coastguard Worker  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
110*bd1f8aebSAndroid Build Coastguard Worker  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
111*bd1f8aebSAndroid Build Coastguard Worker  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
112*bd1f8aebSAndroid Build Coastguard Worker  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
113*bd1f8aebSAndroid Build Coastguard Worker  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
114*bd1f8aebSAndroid Build Coastguard Worker  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
115*bd1f8aebSAndroid Build Coastguard Worker  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
116*bd1f8aebSAndroid Build Coastguard Worker  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
117*bd1f8aebSAndroid Build Coastguard Worker  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
118*bd1f8aebSAndroid Build Coastguard Worker  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
119*bd1f8aebSAndroid Build Coastguard Worker  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
120*bd1f8aebSAndroid Build Coastguard Worker  *     12  * * *
121*bd1f8aebSAndroid Build Coastguard Worker  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
122*bd1f8aebSAndroid Build Coastguard Worker  *     14  * * *
123*bd1f8aebSAndroid Build Coastguard Worker  *     15  * * *
124*bd1f8aebSAndroid Build Coastguard Worker  *     16  * * *
125*bd1f8aebSAndroid Build Coastguard Worker  *     17  * * *
126*bd1f8aebSAndroid Build Coastguard Worker  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
127*bd1f8aebSAndroid Build Coastguard Worker  *
128*bd1f8aebSAndroid Build Coastguard Worker  * (I start to see why I'm having so much trouble with mail to
129*bd1f8aebSAndroid Build Coastguard Worker  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
130*bd1f8aebSAndroid Build Coastguard Worker  * either don't send ICMP "time exceeded" messages or send them
131*bd1f8aebSAndroid Build Coastguard Worker  * with a ttl too small to reach us.  14 - 17 are running the
132*bd1f8aebSAndroid Build Coastguard Worker  * MIT C Gateway code that doesn't send "time exceeded"s.  God
133*bd1f8aebSAndroid Build Coastguard Worker  * only knows what's going on with 12.
134*bd1f8aebSAndroid Build Coastguard Worker  *
135*bd1f8aebSAndroid Build Coastguard Worker  * The silent gateway 12 in the above may be the result of a bug in
136*bd1f8aebSAndroid Build Coastguard Worker  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
137*bd1f8aebSAndroid Build Coastguard Worker  * sends an unreachable message using whatever ttl remains in the
138*bd1f8aebSAndroid Build Coastguard Worker  * original datagram.  Since, for gateways, the remaining ttl is
139*bd1f8aebSAndroid Build Coastguard Worker  * zero, the icmp "time exceeded" is guaranteed to not make it back
140*bd1f8aebSAndroid Build Coastguard Worker  * to us.  The behavior of this bug is slightly more interesting
141*bd1f8aebSAndroid Build Coastguard Worker  * when it appears on the destination system:
142*bd1f8aebSAndroid Build Coastguard Worker  *
143*bd1f8aebSAndroid Build Coastguard Worker  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
144*bd1f8aebSAndroid Build Coastguard Worker  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
145*bd1f8aebSAndroid Build Coastguard Worker  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
146*bd1f8aebSAndroid Build Coastguard Worker  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
147*bd1f8aebSAndroid Build Coastguard Worker  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
148*bd1f8aebSAndroid Build Coastguard Worker  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
149*bd1f8aebSAndroid Build Coastguard Worker  *      7  * * *
150*bd1f8aebSAndroid Build Coastguard Worker  *      8  * * *
151*bd1f8aebSAndroid Build Coastguard Worker  *      9  * * *
152*bd1f8aebSAndroid Build Coastguard Worker  *     10  * * *
153*bd1f8aebSAndroid Build Coastguard Worker  *     11  * * *
154*bd1f8aebSAndroid Build Coastguard Worker  *     12  * * *
155*bd1f8aebSAndroid Build Coastguard Worker  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
156*bd1f8aebSAndroid Build Coastguard Worker  *
157*bd1f8aebSAndroid Build Coastguard Worker  * Notice that there are 12 "gateways" (13 is the final
158*bd1f8aebSAndroid Build Coastguard Worker  * destination) and exactly the last half of them are "missing".
159*bd1f8aebSAndroid Build Coastguard Worker  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
160*bd1f8aebSAndroid Build Coastguard Worker  * is using the ttl from our arriving datagram as the ttl in its
161*bd1f8aebSAndroid Build Coastguard Worker  * icmp reply.  So, the reply will time out on the return path
162*bd1f8aebSAndroid Build Coastguard Worker  * (with no notice sent to anyone since icmp's aren't sent for
163*bd1f8aebSAndroid Build Coastguard Worker  * icmp's) until we probe with a ttl that's at least twice the path
164*bd1f8aebSAndroid Build Coastguard Worker  * length.  I.e., rip is really only 7 hops away.  A reply that
165*bd1f8aebSAndroid Build Coastguard Worker  * returns with a ttl of 1 is a clue this problem exists.
166*bd1f8aebSAndroid Build Coastguard Worker  * Traceroute prints a "!" after the time if the ttl is <= 1.
167*bd1f8aebSAndroid Build Coastguard Worker  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
168*bd1f8aebSAndroid Build Coastguard Worker  * non-standard (HPUX) software, expect to see this problem
169*bd1f8aebSAndroid Build Coastguard Worker  * frequently and/or take care picking the target host of your
170*bd1f8aebSAndroid Build Coastguard Worker  * probes.
171*bd1f8aebSAndroid Build Coastguard Worker  *
172*bd1f8aebSAndroid Build Coastguard Worker  * Other possible annotations after the time are !H, !N, !P (got a host,
173*bd1f8aebSAndroid Build Coastguard Worker  * network or protocol unreachable, respectively), !S or !F (source
174*bd1f8aebSAndroid Build Coastguard Worker  * route failed or fragmentation needed -- neither of these should
175*bd1f8aebSAndroid Build Coastguard Worker  * ever occur and the associated gateway is busted if you see one).  If
176*bd1f8aebSAndroid Build Coastguard Worker  * almost all the probes result in some kind of unreachable, traceroute
177*bd1f8aebSAndroid Build Coastguard Worker  * will give up and exit.
178*bd1f8aebSAndroid Build Coastguard Worker  *
179*bd1f8aebSAndroid Build Coastguard Worker  * Notes
180*bd1f8aebSAndroid Build Coastguard Worker  * -----
181*bd1f8aebSAndroid Build Coastguard Worker  * This program must be run by root or be setuid.  (I suggest that
182*bd1f8aebSAndroid Build Coastguard Worker  * you *don't* make it setuid -- casual use could result in a lot
183*bd1f8aebSAndroid Build Coastguard Worker  * of unnecessary traffic on our poor, congested nets.)
184*bd1f8aebSAndroid Build Coastguard Worker  *
185*bd1f8aebSAndroid Build Coastguard Worker  * This program requires a kernel mod that does not appear in any
186*bd1f8aebSAndroid Build Coastguard Worker  * system available from Berkeley:  A raw ip socket using proto
187*bd1f8aebSAndroid Build Coastguard Worker  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
188*bd1f8aebSAndroid Build Coastguard Worker  * opposed to data to be wrapped in a ip datagram).  See the README
189*bd1f8aebSAndroid Build Coastguard Worker  * file that came with the source to this program for a description
190*bd1f8aebSAndroid Build Coastguard Worker  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
191*bd1f8aebSAndroid Build Coastguard Worker  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
192*bd1f8aebSAndroid Build Coastguard Worker  * MODIFIED TO RUN THIS PROGRAM.
193*bd1f8aebSAndroid Build Coastguard Worker  *
194*bd1f8aebSAndroid Build Coastguard Worker  * The udp port usage may appear bizarre (well, ok, it is bizarre).
195*bd1f8aebSAndroid Build Coastguard Worker  * The problem is that an icmp message only contains 8 bytes of
196*bd1f8aebSAndroid Build Coastguard Worker  * data from the original datagram.  8 bytes is the size of a udp
197*bd1f8aebSAndroid Build Coastguard Worker  * header so, if we want to associate replies with the original
198*bd1f8aebSAndroid Build Coastguard Worker  * datagram, the necessary information must be encoded into the
199*bd1f8aebSAndroid Build Coastguard Worker  * udp header (the ip id could be used but there's no way to
200*bd1f8aebSAndroid Build Coastguard Worker  * interlock with the kernel's assignment of ip id's and, anyway,
201*bd1f8aebSAndroid Build Coastguard Worker  * it would have taken a lot more kernel hacking to allow this
202*bd1f8aebSAndroid Build Coastguard Worker  * code to set the ip id).  So, to allow two or more users to
203*bd1f8aebSAndroid Build Coastguard Worker  * use traceroute simultaneously, we use this task's pid as the
204*bd1f8aebSAndroid Build Coastguard Worker  * source port (the high bit is set to move the port number out
205*bd1f8aebSAndroid Build Coastguard Worker  * of the "likely" range).  To keep track of which probe is being
206*bd1f8aebSAndroid Build Coastguard Worker  * replied to (so times and/or hop counts don't get confused by a
207*bd1f8aebSAndroid Build Coastguard Worker  * reply that was delayed in transit), we increment the destination
208*bd1f8aebSAndroid Build Coastguard Worker  * port number before each probe.
209*bd1f8aebSAndroid Build Coastguard Worker  *
210*bd1f8aebSAndroid Build Coastguard Worker  * Don't use this as a coding example.  I was trying to find a
211*bd1f8aebSAndroid Build Coastguard Worker  * routing problem and this code sort-of popped out after 48 hours
212*bd1f8aebSAndroid Build Coastguard Worker  * without sleep.  I was amazed it ever compiled, much less ran.
213*bd1f8aebSAndroid Build Coastguard Worker  *
214*bd1f8aebSAndroid Build Coastguard Worker  * I stole the idea for this program from Steve Deering.  Since
215*bd1f8aebSAndroid Build Coastguard Worker  * the first release, I've learned that had I attended the right
216*bd1f8aebSAndroid Build Coastguard Worker  * IETF working group meetings, I also could have stolen it from Guy
217*bd1f8aebSAndroid Build Coastguard Worker  * Almes or Matt Mathis.  I don't know (or care) who came up with
218*bd1f8aebSAndroid Build Coastguard Worker  * the idea first.  I envy the originators' perspicacity and I'm
219*bd1f8aebSAndroid Build Coastguard Worker  * glad they didn't keep the idea a secret.
220*bd1f8aebSAndroid Build Coastguard Worker  *
221*bd1f8aebSAndroid Build Coastguard Worker  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
222*bd1f8aebSAndroid Build Coastguard Worker  * enhancements to the original distribution.
223*bd1f8aebSAndroid Build Coastguard Worker  *
224*bd1f8aebSAndroid Build Coastguard Worker  * I've hacked up a round-trip-route version of this that works by
225*bd1f8aebSAndroid Build Coastguard Worker  * sending a loose-source-routed udp datagram through the destination
226*bd1f8aebSAndroid Build Coastguard Worker  * back to yourself.  Unfortunately, SO many gateways botch source
227*bd1f8aebSAndroid Build Coastguard Worker  * routing, the thing is almost worthless.  Maybe one day...
228*bd1f8aebSAndroid Build Coastguard Worker  *
229*bd1f8aebSAndroid Build Coastguard Worker  *  -- Van Jacobson ([email protected])
230*bd1f8aebSAndroid Build Coastguard Worker  *     Tue Dec 20 03:50:13 PST 1988
231*bd1f8aebSAndroid Build Coastguard Worker  */
232*bd1f8aebSAndroid Build Coastguard Worker 
233*bd1f8aebSAndroid Build Coastguard Worker #include <sys/param.h>
234*bd1f8aebSAndroid Build Coastguard Worker #include <sys/time.h>
235*bd1f8aebSAndroid Build Coastguard Worker #include <sys/socket.h>
236*bd1f8aebSAndroid Build Coastguard Worker #include <sys/file.h>
237*bd1f8aebSAndroid Build Coastguard Worker #include <sys/ioctl.h>
238*bd1f8aebSAndroid Build Coastguard Worker #include <net/if.h>
239*bd1f8aebSAndroid Build Coastguard Worker 
240*bd1f8aebSAndroid Build Coastguard Worker #if __linux__
241*bd1f8aebSAndroid Build Coastguard Worker #include <endian.h>
242*bd1f8aebSAndroid Build Coastguard Worker #endif
243*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in_systm.h>
244*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/in.h>
245*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/ip.h>
246*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/ip_icmp.h>
247*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/udp.h>
248*bd1f8aebSAndroid Build Coastguard Worker 
249*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/ip6.h>
250*bd1f8aebSAndroid Build Coastguard Worker #include <netinet/icmp6.h>
251*bd1f8aebSAndroid Build Coastguard Worker #include <linux/types.h>
252*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
253*bd1f8aebSAndroid Build Coastguard Worker #include <sys/capability.h>
254*bd1f8aebSAndroid Build Coastguard Worker #endif
255*bd1f8aebSAndroid Build Coastguard Worker 
256*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
257*bd1f8aebSAndroid Build Coastguard Worker #include <idna.h>
258*bd1f8aebSAndroid Build Coastguard Worker #include <locale.h>
259*bd1f8aebSAndroid Build Coastguard Worker #endif
260*bd1f8aebSAndroid Build Coastguard Worker 
261*bd1f8aebSAndroid Build Coastguard Worker #include <arpa/inet.h>
262*bd1f8aebSAndroid Build Coastguard Worker 
263*bd1f8aebSAndroid Build Coastguard Worker #include <netdb.h>
264*bd1f8aebSAndroid Build Coastguard Worker #include <stdio.h>
265*bd1f8aebSAndroid Build Coastguard Worker #include <errno.h>
266*bd1f8aebSAndroid Build Coastguard Worker #include <stdlib.h>
267*bd1f8aebSAndroid Build Coastguard Worker #include <string.h>
268*bd1f8aebSAndroid Build Coastguard Worker #include <unistd.h>
269*bd1f8aebSAndroid Build Coastguard Worker 
270*bd1f8aebSAndroid Build Coastguard Worker #include "SNAPSHOT.h"
271*bd1f8aebSAndroid Build Coastguard Worker 
272*bd1f8aebSAndroid Build Coastguard Worker #ifndef SOL_IPV6
273*bd1f8aebSAndroid Build Coastguard Worker #define SOL_IPV6 IPPROTO_IPV6
274*bd1f8aebSAndroid Build Coastguard Worker #endif
275*bd1f8aebSAndroid Build Coastguard Worker 
276*bd1f8aebSAndroid Build Coastguard Worker #define	MAXPACKET	65535
277*bd1f8aebSAndroid Build Coastguard Worker #define MAX_HOSTNAMELEN	NI_MAXHOST
278*bd1f8aebSAndroid Build Coastguard Worker 
279*bd1f8aebSAndroid Build Coastguard Worker #ifndef FD_SET
280*bd1f8aebSAndroid Build Coastguard Worker #define NFDBITS         (8*sizeof(fd_set))
281*bd1f8aebSAndroid Build Coastguard Worker #define FD_SETSIZE      NFDBITS
282*bd1f8aebSAndroid Build Coastguard Worker #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
283*bd1f8aebSAndroid Build Coastguard Worker #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
284*bd1f8aebSAndroid Build Coastguard Worker #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
285*bd1f8aebSAndroid Build Coastguard Worker #define FD_ZERO(p)      memset((char *)(p), 0, sizeof(*(p)))
286*bd1f8aebSAndroid Build Coastguard Worker #endif
287*bd1f8aebSAndroid Build Coastguard Worker 
288*bd1f8aebSAndroid Build Coastguard Worker #define Fprintf (void)fprintf
289*bd1f8aebSAndroid Build Coastguard Worker #define Printf (void)printf
290*bd1f8aebSAndroid Build Coastguard Worker 
291*bd1f8aebSAndroid Build Coastguard Worker u_char	packet[512];		/* last inbound (icmp) packet */
292*bd1f8aebSAndroid Build Coastguard Worker 
293*bd1f8aebSAndroid Build Coastguard Worker int	wait_for_reply(int, struct sockaddr_in6 *, struct in6_addr *, int);
294*bd1f8aebSAndroid Build Coastguard Worker int	packet_ok(u_char *buf, int cc, struct sockaddr_in6 *from,
295*bd1f8aebSAndroid Build Coastguard Worker 		  struct in6_addr *to, int seq, struct timeval *);
296*bd1f8aebSAndroid Build Coastguard Worker void	send_probe(int seq, int ttl);
297*bd1f8aebSAndroid Build Coastguard Worker double	deltaT (struct timeval *, struct timeval *);
298*bd1f8aebSAndroid Build Coastguard Worker void	print(unsigned char *buf, int cc, struct sockaddr_in6 *from);
299*bd1f8aebSAndroid Build Coastguard Worker void	tvsub (struct timeval *, struct timeval *);
300*bd1f8aebSAndroid Build Coastguard Worker void	usage(void);
301*bd1f8aebSAndroid Build Coastguard Worker 
302*bd1f8aebSAndroid Build Coastguard Worker int icmp_sock;			/* receive (icmp) socket file descriptor */
303*bd1f8aebSAndroid Build Coastguard Worker int sndsock;			/* send (udp) socket file descriptor */
304*bd1f8aebSAndroid Build Coastguard Worker struct timezone tz;		/* leftover */
305*bd1f8aebSAndroid Build Coastguard Worker 
306*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in6 whereto;	/* Who to try to reach */
307*bd1f8aebSAndroid Build Coastguard Worker 
308*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in6 saddr;
309*bd1f8aebSAndroid Build Coastguard Worker struct sockaddr_in6 firsthop;
310*bd1f8aebSAndroid Build Coastguard Worker char *source = NULL;
311*bd1f8aebSAndroid Build Coastguard Worker char *device = NULL;
312*bd1f8aebSAndroid Build Coastguard Worker char *hostname;
313*bd1f8aebSAndroid Build Coastguard Worker 
314*bd1f8aebSAndroid Build Coastguard Worker int nprobes = 3;
315*bd1f8aebSAndroid Build Coastguard Worker int max_ttl = 30;
316*bd1f8aebSAndroid Build Coastguard Worker pid_t ident;
317*bd1f8aebSAndroid Build Coastguard Worker u_short port = 32768+666;	/* start udp dest port # for probe packets */
318*bd1f8aebSAndroid Build Coastguard Worker int options;			/* socket options */
319*bd1f8aebSAndroid Build Coastguard Worker int verbose;
320*bd1f8aebSAndroid Build Coastguard Worker int waittime = 5;		/* time to wait for response (in seconds) */
321*bd1f8aebSAndroid Build Coastguard Worker int nflag;			/* print addresses numerically */
322*bd1f8aebSAndroid Build Coastguard Worker 
323*bd1f8aebSAndroid Build Coastguard Worker 
324*bd1f8aebSAndroid Build Coastguard Worker struct pkt_format
325*bd1f8aebSAndroid Build Coastguard Worker {
326*bd1f8aebSAndroid Build Coastguard Worker 	__u32 ident;
327*bd1f8aebSAndroid Build Coastguard Worker 	__u32 seq;
328*bd1f8aebSAndroid Build Coastguard Worker 	struct timeval tv;
329*bd1f8aebSAndroid Build Coastguard Worker };
330*bd1f8aebSAndroid Build Coastguard Worker 
331*bd1f8aebSAndroid Build Coastguard Worker char *sendbuff;
332*bd1f8aebSAndroid Build Coastguard Worker int datalen = sizeof(struct pkt_format);
333*bd1f8aebSAndroid Build Coastguard Worker 
334*bd1f8aebSAndroid Build Coastguard Worker 
335*bd1f8aebSAndroid Build Coastguard Worker 
main(int argc,char * argv[])336*bd1f8aebSAndroid Build Coastguard Worker int main(int argc, char *argv[])
337*bd1f8aebSAndroid Build Coastguard Worker {
338*bd1f8aebSAndroid Build Coastguard Worker 	char pa[MAX_HOSTNAMELEN];
339*bd1f8aebSAndroid Build Coastguard Worker 	extern char *optarg;
340*bd1f8aebSAndroid Build Coastguard Worker 	extern int optind;
341*bd1f8aebSAndroid Build Coastguard Worker 	struct hostent *hp;
342*bd1f8aebSAndroid Build Coastguard Worker 	struct sockaddr_in6 from, *to;
343*bd1f8aebSAndroid Build Coastguard Worker 	int ch, i, on, probe, seq, tos, ttl;
344*bd1f8aebSAndroid Build Coastguard Worker 	int socket_errno;
345*bd1f8aebSAndroid Build Coastguard Worker 
346*bd1f8aebSAndroid Build Coastguard Worker 	icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
347*bd1f8aebSAndroid Build Coastguard Worker 	socket_errno = errno;
348*bd1f8aebSAndroid Build Coastguard Worker 
349*bd1f8aebSAndroid Build Coastguard Worker 	if (setuid(getuid())) {
350*bd1f8aebSAndroid Build Coastguard Worker 		perror("traceroute6: setuid");
351*bd1f8aebSAndroid Build Coastguard Worker 		exit(-1);
352*bd1f8aebSAndroid Build Coastguard Worker 	}
353*bd1f8aebSAndroid Build Coastguard Worker #ifdef CAPABILITIES
354*bd1f8aebSAndroid Build Coastguard Worker 	{
355*bd1f8aebSAndroid Build Coastguard Worker 		cap_t caps = cap_init();
356*bd1f8aebSAndroid Build Coastguard Worker 		if (cap_set_proc(caps)) {
357*bd1f8aebSAndroid Build Coastguard Worker 			perror("traceroute6: cap_set_proc");
358*bd1f8aebSAndroid Build Coastguard Worker 			exit(-1);
359*bd1f8aebSAndroid Build Coastguard Worker 		}
360*bd1f8aebSAndroid Build Coastguard Worker 		cap_free(caps);
361*bd1f8aebSAndroid Build Coastguard Worker 	}
362*bd1f8aebSAndroid Build Coastguard Worker #endif
363*bd1f8aebSAndroid Build Coastguard Worker 
364*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
365*bd1f8aebSAndroid Build Coastguard Worker 	setlocale(LC_ALL, "");
366*bd1f8aebSAndroid Build Coastguard Worker #endif
367*bd1f8aebSAndroid Build Coastguard Worker 
368*bd1f8aebSAndroid Build Coastguard Worker 	on = 1;
369*bd1f8aebSAndroid Build Coastguard Worker 	seq = tos = 0;
370*bd1f8aebSAndroid Build Coastguard Worker 	to = (struct sockaddr_in6 *)&whereto;
371*bd1f8aebSAndroid Build Coastguard Worker 	while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:vi:g:V")) != EOF) {
372*bd1f8aebSAndroid Build Coastguard Worker 		switch(ch) {
373*bd1f8aebSAndroid Build Coastguard Worker 		case 'd':
374*bd1f8aebSAndroid Build Coastguard Worker 			options |= SO_DEBUG;
375*bd1f8aebSAndroid Build Coastguard Worker 			break;
376*bd1f8aebSAndroid Build Coastguard Worker 		case 'm':
377*bd1f8aebSAndroid Build Coastguard Worker 			max_ttl = atoi(optarg);
378*bd1f8aebSAndroid Build Coastguard Worker 			if (max_ttl <= 1) {
379*bd1f8aebSAndroid Build Coastguard Worker 				Fprintf(stderr,
380*bd1f8aebSAndroid Build Coastguard Worker 				    "traceroute: max ttl must be >1.\n");
381*bd1f8aebSAndroid Build Coastguard Worker 				exit(1);
382*bd1f8aebSAndroid Build Coastguard Worker 			}
383*bd1f8aebSAndroid Build Coastguard Worker 			break;
384*bd1f8aebSAndroid Build Coastguard Worker 		case 'n':
385*bd1f8aebSAndroid Build Coastguard Worker 			nflag++;
386*bd1f8aebSAndroid Build Coastguard Worker 			break;
387*bd1f8aebSAndroid Build Coastguard Worker 		case 'p':
388*bd1f8aebSAndroid Build Coastguard Worker 			port = atoi(optarg);
389*bd1f8aebSAndroid Build Coastguard Worker 			if (port < 1) {
390*bd1f8aebSAndroid Build Coastguard Worker 				Fprintf(stderr,
391*bd1f8aebSAndroid Build Coastguard Worker 				    "traceroute: port must be >0.\n");
392*bd1f8aebSAndroid Build Coastguard Worker 				exit(1);
393*bd1f8aebSAndroid Build Coastguard Worker 			}
394*bd1f8aebSAndroid Build Coastguard Worker 			break;
395*bd1f8aebSAndroid Build Coastguard Worker 		case 'q':
396*bd1f8aebSAndroid Build Coastguard Worker 			nprobes = atoi(optarg);
397*bd1f8aebSAndroid Build Coastguard Worker 			if (nprobes < 1) {
398*bd1f8aebSAndroid Build Coastguard Worker 				Fprintf(stderr,
399*bd1f8aebSAndroid Build Coastguard Worker 				    "traceroute: nprobes must be >0.\n");
400*bd1f8aebSAndroid Build Coastguard Worker 				exit(1);
401*bd1f8aebSAndroid Build Coastguard Worker 			}
402*bd1f8aebSAndroid Build Coastguard Worker 			break;
403*bd1f8aebSAndroid Build Coastguard Worker 		case 'r':
404*bd1f8aebSAndroid Build Coastguard Worker 			options |= SO_DONTROUTE;
405*bd1f8aebSAndroid Build Coastguard Worker 			break;
406*bd1f8aebSAndroid Build Coastguard Worker 		case 's':
407*bd1f8aebSAndroid Build Coastguard Worker 			/*
408*bd1f8aebSAndroid Build Coastguard Worker 			 * set the ip source address of the outbound
409*bd1f8aebSAndroid Build Coastguard Worker 			 * probe (e.g., on a multi-homed host).
410*bd1f8aebSAndroid Build Coastguard Worker 			 */
411*bd1f8aebSAndroid Build Coastguard Worker 			source = optarg;
412*bd1f8aebSAndroid Build Coastguard Worker 			break;
413*bd1f8aebSAndroid Build Coastguard Worker 		case 'i':
414*bd1f8aebSAndroid Build Coastguard Worker 			device = optarg;
415*bd1f8aebSAndroid Build Coastguard Worker 			break;
416*bd1f8aebSAndroid Build Coastguard Worker 		case 'g':
417*bd1f8aebSAndroid Build Coastguard Worker 			Fprintf(stderr, "Sorry, rthdr is not yet supported\n");
418*bd1f8aebSAndroid Build Coastguard Worker 			break;
419*bd1f8aebSAndroid Build Coastguard Worker 		case 'v':
420*bd1f8aebSAndroid Build Coastguard Worker 			verbose++;
421*bd1f8aebSAndroid Build Coastguard Worker 			break;
422*bd1f8aebSAndroid Build Coastguard Worker 		case 'w':
423*bd1f8aebSAndroid Build Coastguard Worker 			waittime = atoi(optarg);
424*bd1f8aebSAndroid Build Coastguard Worker 			if (waittime <= 1) {
425*bd1f8aebSAndroid Build Coastguard Worker 				Fprintf(stderr,
426*bd1f8aebSAndroid Build Coastguard Worker 				    "traceroute: wait must be >1 sec.\n");
427*bd1f8aebSAndroid Build Coastguard Worker 				exit(1);
428*bd1f8aebSAndroid Build Coastguard Worker 			}
429*bd1f8aebSAndroid Build Coastguard Worker 			break;
430*bd1f8aebSAndroid Build Coastguard Worker 		case 'V':
431*bd1f8aebSAndroid Build Coastguard Worker 			printf("traceroute6 utility, iputils-%s\n", SNAPSHOT);
432*bd1f8aebSAndroid Build Coastguard Worker 			exit(0);
433*bd1f8aebSAndroid Build Coastguard Worker 		default:
434*bd1f8aebSAndroid Build Coastguard Worker 			usage();
435*bd1f8aebSAndroid Build Coastguard Worker 		}
436*bd1f8aebSAndroid Build Coastguard Worker 	}
437*bd1f8aebSAndroid Build Coastguard Worker 	argc -= optind;
438*bd1f8aebSAndroid Build Coastguard Worker 	argv += optind;
439*bd1f8aebSAndroid Build Coastguard Worker 
440*bd1f8aebSAndroid Build Coastguard Worker 	if (argc < 1)
441*bd1f8aebSAndroid Build Coastguard Worker 		usage();
442*bd1f8aebSAndroid Build Coastguard Worker 
443*bd1f8aebSAndroid Build Coastguard Worker 	setlinebuf (stdout);
444*bd1f8aebSAndroid Build Coastguard Worker 
445*bd1f8aebSAndroid Build Coastguard Worker 	(void) memset((char *)&whereto, 0, sizeof(whereto));
446*bd1f8aebSAndroid Build Coastguard Worker 
447*bd1f8aebSAndroid Build Coastguard Worker 	to->sin6_family = AF_INET6;
448*bd1f8aebSAndroid Build Coastguard Worker 	to->sin6_port = htons(port);
449*bd1f8aebSAndroid Build Coastguard Worker 
450*bd1f8aebSAndroid Build Coastguard Worker 	if (inet_pton(AF_INET6, *argv, &to->sin6_addr) > 0) {
451*bd1f8aebSAndroid Build Coastguard Worker 		hostname = *argv;
452*bd1f8aebSAndroid Build Coastguard Worker 	} else {
453*bd1f8aebSAndroid Build Coastguard Worker 		char *idn = NULL;
454*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
455*bd1f8aebSAndroid Build Coastguard Worker 		if (idna_to_ascii_lz(*argv, &idn, 0) != IDNA_SUCCESS)
456*bd1f8aebSAndroid Build Coastguard Worker 			idn = NULL;
457*bd1f8aebSAndroid Build Coastguard Worker #endif
458*bd1f8aebSAndroid Build Coastguard Worker 		hp = gethostbyname2(idn ? idn : *argv, AF_INET6);
459*bd1f8aebSAndroid Build Coastguard Worker 		if (hp) {
460*bd1f8aebSAndroid Build Coastguard Worker 			memmove((caddr_t)&to->sin6_addr, hp->h_addr, sizeof(to->sin6_addr));
461*bd1f8aebSAndroid Build Coastguard Worker 			hostname = (char *)hp->h_name;
462*bd1f8aebSAndroid Build Coastguard Worker 		} else {
463*bd1f8aebSAndroid Build Coastguard Worker 			(void)fprintf(stderr,
464*bd1f8aebSAndroid Build Coastguard Worker 			    "traceroute: unknown host %s\n", *argv);
465*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
466*bd1f8aebSAndroid Build Coastguard Worker 		}
467*bd1f8aebSAndroid Build Coastguard Worker 	}
468*bd1f8aebSAndroid Build Coastguard Worker 	firsthop = *to;
469*bd1f8aebSAndroid Build Coastguard Worker 	if (*++argv) {
470*bd1f8aebSAndroid Build Coastguard Worker 		datalen = atoi(*argv);
471*bd1f8aebSAndroid Build Coastguard Worker 		/* Message for rpm maintainers: have _shame_. If you want
472*bd1f8aebSAndroid Build Coastguard Worker 		 * to fix something send the patch to me for sanity checking.
473*bd1f8aebSAndroid Build Coastguard Worker 		 * "datalen" patch is a shit. */
474*bd1f8aebSAndroid Build Coastguard Worker 		if (datalen == 0)
475*bd1f8aebSAndroid Build Coastguard Worker 			datalen = sizeof(struct pkt_format);
476*bd1f8aebSAndroid Build Coastguard Worker 		else if (datalen < (int)sizeof(struct pkt_format) ||
477*bd1f8aebSAndroid Build Coastguard Worker 			 datalen >= MAXPACKET) {
478*bd1f8aebSAndroid Build Coastguard Worker 			Fprintf(stderr,
479*bd1f8aebSAndroid Build Coastguard Worker 			    "traceroute: packet size must be %d <= s < %d.\n",
480*bd1f8aebSAndroid Build Coastguard Worker 				(int)sizeof(struct pkt_format), MAXPACKET);
481*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
482*bd1f8aebSAndroid Build Coastguard Worker 		}
483*bd1f8aebSAndroid Build Coastguard Worker 	}
484*bd1f8aebSAndroid Build Coastguard Worker 
485*bd1f8aebSAndroid Build Coastguard Worker 	ident = getpid();
486*bd1f8aebSAndroid Build Coastguard Worker 
487*bd1f8aebSAndroid Build Coastguard Worker 	sendbuff = malloc(datalen);
488*bd1f8aebSAndroid Build Coastguard Worker 	if (sendbuff == NULL) {
489*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, "malloc failed\n");
490*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
491*bd1f8aebSAndroid Build Coastguard Worker 	}
492*bd1f8aebSAndroid Build Coastguard Worker 
493*bd1f8aebSAndroid Build Coastguard Worker 	if (icmp_sock < 0) {
494*bd1f8aebSAndroid Build Coastguard Worker 		errno = socket_errno;
495*bd1f8aebSAndroid Build Coastguard Worker 		perror("traceroute6: icmp socket");
496*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
497*bd1f8aebSAndroid Build Coastguard Worker 	}
498*bd1f8aebSAndroid Build Coastguard Worker 
499*bd1f8aebSAndroid Build Coastguard Worker #ifdef IPV6_RECVPKTINFO
500*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
501*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_IPV6, IPV6_2292PKTINFO, &on, sizeof(on));
502*bd1f8aebSAndroid Build Coastguard Worker #else
503*bd1f8aebSAndroid Build Coastguard Worker 	setsockopt(icmp_sock, SOL_IPV6, IPV6_PKTINFO, &on, sizeof(on));
504*bd1f8aebSAndroid Build Coastguard Worker #endif
505*bd1f8aebSAndroid Build Coastguard Worker 
506*bd1f8aebSAndroid Build Coastguard Worker 	if (options & SO_DEBUG)
507*bd1f8aebSAndroid Build Coastguard Worker 		setsockopt(icmp_sock, SOL_SOCKET, SO_DEBUG,
508*bd1f8aebSAndroid Build Coastguard Worker 			   (char *)&on, sizeof(on));
509*bd1f8aebSAndroid Build Coastguard Worker 	if (options & SO_DONTROUTE)
510*bd1f8aebSAndroid Build Coastguard Worker 		setsockopt(icmp_sock, SOL_SOCKET, SO_DONTROUTE,
511*bd1f8aebSAndroid Build Coastguard Worker 			   (char *)&on, sizeof(on));
512*bd1f8aebSAndroid Build Coastguard Worker 
513*bd1f8aebSAndroid Build Coastguard Worker #ifdef __linux__
514*bd1f8aebSAndroid Build Coastguard Worker 	on = 2;
515*bd1f8aebSAndroid Build Coastguard Worker 	if (setsockopt(icmp_sock, SOL_RAW, IPV6_CHECKSUM, &on, sizeof(on)) < 0) {
516*bd1f8aebSAndroid Build Coastguard Worker 		/* checksum should be enabled by default and setting this
517*bd1f8aebSAndroid Build Coastguard Worker 		 * option might fail anyway.
518*bd1f8aebSAndroid Build Coastguard Worker 		 */
519*bd1f8aebSAndroid Build Coastguard Worker 		fprintf(stderr, "setsockopt(RAW_CHECKSUM) failed - try to continue.");
520*bd1f8aebSAndroid Build Coastguard Worker 	}
521*bd1f8aebSAndroid Build Coastguard Worker #endif
522*bd1f8aebSAndroid Build Coastguard Worker 
523*bd1f8aebSAndroid Build Coastguard Worker 	if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
524*bd1f8aebSAndroid Build Coastguard Worker 		perror("traceroute: UDP socket");
525*bd1f8aebSAndroid Build Coastguard Worker 		exit(5);
526*bd1f8aebSAndroid Build Coastguard Worker 	}
527*bd1f8aebSAndroid Build Coastguard Worker #ifdef SO_SNDBUF
528*bd1f8aebSAndroid Build Coastguard Worker 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
529*bd1f8aebSAndroid Build Coastguard Worker 		       sizeof(datalen)) < 0) {
530*bd1f8aebSAndroid Build Coastguard Worker 		perror("traceroute: SO_SNDBUF");
531*bd1f8aebSAndroid Build Coastguard Worker 		exit(6);
532*bd1f8aebSAndroid Build Coastguard Worker 	}
533*bd1f8aebSAndroid Build Coastguard Worker #endif /* SO_SNDBUF */
534*bd1f8aebSAndroid Build Coastguard Worker 
535*bd1f8aebSAndroid Build Coastguard Worker 	if (options & SO_DEBUG)
536*bd1f8aebSAndroid Build Coastguard Worker 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
537*bd1f8aebSAndroid Build Coastguard Worker 				  (char *)&on, sizeof(on));
538*bd1f8aebSAndroid Build Coastguard Worker 	if (options & SO_DONTROUTE)
539*bd1f8aebSAndroid Build Coastguard Worker 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
540*bd1f8aebSAndroid Build Coastguard Worker 				  (char *)&on, sizeof(on));
541*bd1f8aebSAndroid Build Coastguard Worker 
542*bd1f8aebSAndroid Build Coastguard Worker 	if (source == NULL) {
543*bd1f8aebSAndroid Build Coastguard Worker 		socklen_t alen;
544*bd1f8aebSAndroid Build Coastguard Worker 		int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0);
545*bd1f8aebSAndroid Build Coastguard Worker 
546*bd1f8aebSAndroid Build Coastguard Worker 		if (probe_fd < 0) {
547*bd1f8aebSAndroid Build Coastguard Worker 			perror("socket");
548*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
549*bd1f8aebSAndroid Build Coastguard Worker 		}
550*bd1f8aebSAndroid Build Coastguard Worker 		if (device) {
551*bd1f8aebSAndroid Build Coastguard Worker 			if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1)
552*bd1f8aebSAndroid Build Coastguard Worker 				perror("WARNING: interface is ignored");
553*bd1f8aebSAndroid Build Coastguard Worker 		}
554*bd1f8aebSAndroid Build Coastguard Worker 		firsthop.sin6_port = htons(1025);
555*bd1f8aebSAndroid Build Coastguard Worker 		if (connect(probe_fd, (struct sockaddr*)&firsthop, sizeof(firsthop)) == -1) {
556*bd1f8aebSAndroid Build Coastguard Worker 			perror("connect");
557*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
558*bd1f8aebSAndroid Build Coastguard Worker 		}
559*bd1f8aebSAndroid Build Coastguard Worker 		alen = sizeof(saddr);
560*bd1f8aebSAndroid Build Coastguard Worker 		if (getsockname(probe_fd, (struct sockaddr*)&saddr, &alen) == -1) {
561*bd1f8aebSAndroid Build Coastguard Worker 			perror("getsockname");
562*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
563*bd1f8aebSAndroid Build Coastguard Worker 		}
564*bd1f8aebSAndroid Build Coastguard Worker 		saddr.sin6_port = 0;
565*bd1f8aebSAndroid Build Coastguard Worker 		close(probe_fd);
566*bd1f8aebSAndroid Build Coastguard Worker 	} else {
567*bd1f8aebSAndroid Build Coastguard Worker 		(void) memset((char *)&saddr, 0, sizeof(saddr));
568*bd1f8aebSAndroid Build Coastguard Worker 		saddr.sin6_family = AF_INET6;
569*bd1f8aebSAndroid Build Coastguard Worker 		if (inet_pton(AF_INET6, source, &saddr.sin6_addr) <= 0)
570*bd1f8aebSAndroid Build Coastguard Worker 		{
571*bd1f8aebSAndroid Build Coastguard Worker 			Printf("traceroute: unknown addr %s\n", source);
572*bd1f8aebSAndroid Build Coastguard Worker 			exit(1);
573*bd1f8aebSAndroid Build Coastguard Worker 		}
574*bd1f8aebSAndroid Build Coastguard Worker 	}
575*bd1f8aebSAndroid Build Coastguard Worker 
576*bd1f8aebSAndroid Build Coastguard Worker 	if (bind(sndsock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
577*bd1f8aebSAndroid Build Coastguard Worker 		perror ("traceroute: bind sending socket");
578*bd1f8aebSAndroid Build Coastguard Worker 		exit (1);
579*bd1f8aebSAndroid Build Coastguard Worker 	}
580*bd1f8aebSAndroid Build Coastguard Worker 	if (bind(icmp_sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
581*bd1f8aebSAndroid Build Coastguard Worker 		perror ("traceroute: bind icmp6 socket");
582*bd1f8aebSAndroid Build Coastguard Worker 		exit (1);
583*bd1f8aebSAndroid Build Coastguard Worker 	}
584*bd1f8aebSAndroid Build Coastguard Worker 
585*bd1f8aebSAndroid Build Coastguard Worker 	Fprintf(stderr, "traceroute to %s (%s)", hostname,
586*bd1f8aebSAndroid Build Coastguard Worker 		inet_ntop(AF_INET6, &to->sin6_addr, pa, sizeof(pa)));
587*bd1f8aebSAndroid Build Coastguard Worker 
588*bd1f8aebSAndroid Build Coastguard Worker 	Fprintf(stderr, " from %s",
589*bd1f8aebSAndroid Build Coastguard Worker 		inet_ntop(AF_INET6, &saddr.sin6_addr, pa, sizeof(pa)));
590*bd1f8aebSAndroid Build Coastguard Worker 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
591*bd1f8aebSAndroid Build Coastguard Worker 	(void) fflush(stderr);
592*bd1f8aebSAndroid Build Coastguard Worker 
593*bd1f8aebSAndroid Build Coastguard Worker 	for (ttl = 1; ttl <= max_ttl; ++ttl) {
594*bd1f8aebSAndroid Build Coastguard Worker 		struct in6_addr lastaddr = {{{0,}}};
595*bd1f8aebSAndroid Build Coastguard Worker 		int got_there = 0;
596*bd1f8aebSAndroid Build Coastguard Worker 		int unreachable = 0;
597*bd1f8aebSAndroid Build Coastguard Worker 
598*bd1f8aebSAndroid Build Coastguard Worker 		Printf("%2d ", ttl);
599*bd1f8aebSAndroid Build Coastguard Worker 		for (probe = 0; probe < nprobes; ++probe) {
600*bd1f8aebSAndroid Build Coastguard Worker 			int cc, reset_timer;
601*bd1f8aebSAndroid Build Coastguard Worker 			struct timeval t1, t2;
602*bd1f8aebSAndroid Build Coastguard Worker 			struct timezone tz;
603*bd1f8aebSAndroid Build Coastguard Worker 			struct in6_addr to;
604*bd1f8aebSAndroid Build Coastguard Worker 
605*bd1f8aebSAndroid Build Coastguard Worker 			gettimeofday(&t1, &tz);
606*bd1f8aebSAndroid Build Coastguard Worker 			send_probe(++seq, ttl);
607*bd1f8aebSAndroid Build Coastguard Worker 			reset_timer = 1;
608*bd1f8aebSAndroid Build Coastguard Worker 
609*bd1f8aebSAndroid Build Coastguard Worker 			while ((cc = wait_for_reply(icmp_sock, &from, &to, reset_timer)) != 0) {
610*bd1f8aebSAndroid Build Coastguard Worker 				gettimeofday(&t2, &tz);
611*bd1f8aebSAndroid Build Coastguard Worker 				if ((i = packet_ok(packet, cc, &from, &to, seq, &t1))) {
612*bd1f8aebSAndroid Build Coastguard Worker 					reset_timer = 1;
613*bd1f8aebSAndroid Build Coastguard Worker 					if (memcmp(&from.sin6_addr, &lastaddr, sizeof(from.sin6_addr))) {
614*bd1f8aebSAndroid Build Coastguard Worker 						print(packet, cc, &from);
615*bd1f8aebSAndroid Build Coastguard Worker 						memcpy(&lastaddr,
616*bd1f8aebSAndroid Build Coastguard Worker 						       &from.sin6_addr,
617*bd1f8aebSAndroid Build Coastguard Worker 						       sizeof(lastaddr));
618*bd1f8aebSAndroid Build Coastguard Worker 					}
619*bd1f8aebSAndroid Build Coastguard Worker 					Printf("  %g ms", deltaT(&t1, &t2));
620*bd1f8aebSAndroid Build Coastguard Worker 					switch(i - 1) {
621*bd1f8aebSAndroid Build Coastguard Worker 					case ICMP6_DST_UNREACH_NOPORT:
622*bd1f8aebSAndroid Build Coastguard Worker 						++got_there;
623*bd1f8aebSAndroid Build Coastguard Worker 						break;
624*bd1f8aebSAndroid Build Coastguard Worker 
625*bd1f8aebSAndroid Build Coastguard Worker 					case ICMP6_DST_UNREACH_NOROUTE:
626*bd1f8aebSAndroid Build Coastguard Worker 						++unreachable;
627*bd1f8aebSAndroid Build Coastguard Worker 						Printf(" !N");
628*bd1f8aebSAndroid Build Coastguard Worker 						break;
629*bd1f8aebSAndroid Build Coastguard Worker 					case ICMP6_DST_UNREACH_ADDR:
630*bd1f8aebSAndroid Build Coastguard Worker 						++unreachable;
631*bd1f8aebSAndroid Build Coastguard Worker 						Printf(" !H");
632*bd1f8aebSAndroid Build Coastguard Worker 						break;
633*bd1f8aebSAndroid Build Coastguard Worker 
634*bd1f8aebSAndroid Build Coastguard Worker 					case ICMP6_DST_UNREACH_ADMIN:
635*bd1f8aebSAndroid Build Coastguard Worker 						++unreachable;
636*bd1f8aebSAndroid Build Coastguard Worker 						Printf(" !S");
637*bd1f8aebSAndroid Build Coastguard Worker 						break;
638*bd1f8aebSAndroid Build Coastguard Worker 					}
639*bd1f8aebSAndroid Build Coastguard Worker 					break;
640*bd1f8aebSAndroid Build Coastguard Worker 				} else
641*bd1f8aebSAndroid Build Coastguard Worker 					reset_timer = 0;
642*bd1f8aebSAndroid Build Coastguard Worker 			}
643*bd1f8aebSAndroid Build Coastguard Worker 			if (cc <= 0)
644*bd1f8aebSAndroid Build Coastguard Worker 				Printf(" *");
645*bd1f8aebSAndroid Build Coastguard Worker 			(void) fflush(stdout);
646*bd1f8aebSAndroid Build Coastguard Worker 		}
647*bd1f8aebSAndroid Build Coastguard Worker 		putchar('\n');
648*bd1f8aebSAndroid Build Coastguard Worker 		if (got_there ||
649*bd1f8aebSAndroid Build Coastguard Worker 		    (unreachable > 0 && unreachable >= nprobes-1))
650*bd1f8aebSAndroid Build Coastguard Worker 			exit(0);
651*bd1f8aebSAndroid Build Coastguard Worker 	}
652*bd1f8aebSAndroid Build Coastguard Worker 
653*bd1f8aebSAndroid Build Coastguard Worker 	return 0;
654*bd1f8aebSAndroid Build Coastguard Worker }
655*bd1f8aebSAndroid Build Coastguard Worker 
656*bd1f8aebSAndroid Build Coastguard Worker int
wait_for_reply(sock,from,to,reset_timer)657*bd1f8aebSAndroid Build Coastguard Worker wait_for_reply(sock, from, to, reset_timer)
658*bd1f8aebSAndroid Build Coastguard Worker 	int sock;
659*bd1f8aebSAndroid Build Coastguard Worker 	struct sockaddr_in6 *from;
660*bd1f8aebSAndroid Build Coastguard Worker 	struct in6_addr *to;
661*bd1f8aebSAndroid Build Coastguard Worker 	int reset_timer;
662*bd1f8aebSAndroid Build Coastguard Worker {
663*bd1f8aebSAndroid Build Coastguard Worker 	fd_set fds;
664*bd1f8aebSAndroid Build Coastguard Worker 	static struct timeval wait;
665*bd1f8aebSAndroid Build Coastguard Worker 	int cc = 0;
666*bd1f8aebSAndroid Build Coastguard Worker 	char cbuf[512];
667*bd1f8aebSAndroid Build Coastguard Worker 
668*bd1f8aebSAndroid Build Coastguard Worker 	FD_ZERO(&fds);
669*bd1f8aebSAndroid Build Coastguard Worker 	FD_SET(sock, &fds);
670*bd1f8aebSAndroid Build Coastguard Worker 	if (reset_timer) {
671*bd1f8aebSAndroid Build Coastguard Worker 		/*
672*bd1f8aebSAndroid Build Coastguard Worker 		 * traceroute could hang if someone else has a ping
673*bd1f8aebSAndroid Build Coastguard Worker 		 * running and our ICMP reply gets dropped but we don't
674*bd1f8aebSAndroid Build Coastguard Worker 		 * realize it because we keep waking up to handle those
675*bd1f8aebSAndroid Build Coastguard Worker 		 * other ICMP packets that keep coming in.  To fix this,
676*bd1f8aebSAndroid Build Coastguard Worker 		 * "reset_timer" will only be true if the last packet that
677*bd1f8aebSAndroid Build Coastguard Worker 		 * came in was for us or if this is the first time we're
678*bd1f8aebSAndroid Build Coastguard Worker 		 * waiting for a reply since sending out a probe.  Note
679*bd1f8aebSAndroid Build Coastguard Worker 		 * that this takes advantage of the select() feature on
680*bd1f8aebSAndroid Build Coastguard Worker 		 * Linux where the remaining timeout is written to the
681*bd1f8aebSAndroid Build Coastguard Worker 		 * struct timeval area.
682*bd1f8aebSAndroid Build Coastguard Worker 		 */
683*bd1f8aebSAndroid Build Coastguard Worker 		wait.tv_sec = waittime;
684*bd1f8aebSAndroid Build Coastguard Worker 		wait.tv_usec = 0;
685*bd1f8aebSAndroid Build Coastguard Worker 	}
686*bd1f8aebSAndroid Build Coastguard Worker 
687*bd1f8aebSAndroid Build Coastguard Worker 	if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0) {
688*bd1f8aebSAndroid Build Coastguard Worker 		struct iovec iov;
689*bd1f8aebSAndroid Build Coastguard Worker 		struct msghdr msg;
690*bd1f8aebSAndroid Build Coastguard Worker 		iov.iov_base = packet;
691*bd1f8aebSAndroid Build Coastguard Worker 		iov.iov_len = sizeof(packet);
692*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_name = (void *)from;
693*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_namelen = sizeof(*from);
694*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_iov = &iov;
695*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_iovlen = 1;
696*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_flags = 0;
697*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_control = cbuf;
698*bd1f8aebSAndroid Build Coastguard Worker 		msg.msg_controllen = sizeof(cbuf);
699*bd1f8aebSAndroid Build Coastguard Worker 
700*bd1f8aebSAndroid Build Coastguard Worker 		cc = recvmsg(icmp_sock, &msg, 0);
701*bd1f8aebSAndroid Build Coastguard Worker 		if (cc >= 0) {
702*bd1f8aebSAndroid Build Coastguard Worker 			struct cmsghdr *cmsg;
703*bd1f8aebSAndroid Build Coastguard Worker 			struct in6_pktinfo *ipi;
704*bd1f8aebSAndroid Build Coastguard Worker 
705*bd1f8aebSAndroid Build Coastguard Worker 			for (cmsg = CMSG_FIRSTHDR(&msg);
706*bd1f8aebSAndroid Build Coastguard Worker 			     cmsg;
707*bd1f8aebSAndroid Build Coastguard Worker 			     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
708*bd1f8aebSAndroid Build Coastguard Worker 				if (cmsg->cmsg_level != SOL_IPV6)
709*bd1f8aebSAndroid Build Coastguard Worker 					continue;
710*bd1f8aebSAndroid Build Coastguard Worker 				switch (cmsg->cmsg_type) {
711*bd1f8aebSAndroid Build Coastguard Worker 				case IPV6_PKTINFO:
712*bd1f8aebSAndroid Build Coastguard Worker #ifdef IPV6_2292PKTINFO
713*bd1f8aebSAndroid Build Coastguard Worker 				case IPV6_2292PKTINFO:
714*bd1f8aebSAndroid Build Coastguard Worker #endif
715*bd1f8aebSAndroid Build Coastguard Worker 					ipi = (struct in6_pktinfo *)CMSG_DATA(cmsg);
716*bd1f8aebSAndroid Build Coastguard Worker 					memcpy(to, ipi, sizeof(*to));
717*bd1f8aebSAndroid Build Coastguard Worker 				}
718*bd1f8aebSAndroid Build Coastguard Worker 			}
719*bd1f8aebSAndroid Build Coastguard Worker 		}
720*bd1f8aebSAndroid Build Coastguard Worker 	}
721*bd1f8aebSAndroid Build Coastguard Worker 
722*bd1f8aebSAndroid Build Coastguard Worker 	return(cc);
723*bd1f8aebSAndroid Build Coastguard Worker }
724*bd1f8aebSAndroid Build Coastguard Worker 
725*bd1f8aebSAndroid Build Coastguard Worker 
send_probe(int seq,int ttl)726*bd1f8aebSAndroid Build Coastguard Worker void send_probe(int seq, int ttl)
727*bd1f8aebSAndroid Build Coastguard Worker {
728*bd1f8aebSAndroid Build Coastguard Worker 	struct pkt_format *pkt = (struct pkt_format *) sendbuff;
729*bd1f8aebSAndroid Build Coastguard Worker 	int i;
730*bd1f8aebSAndroid Build Coastguard Worker 
731*bd1f8aebSAndroid Build Coastguard Worker 	pkt->ident = htonl(ident);
732*bd1f8aebSAndroid Build Coastguard Worker 	pkt->seq = htonl(seq);
733*bd1f8aebSAndroid Build Coastguard Worker 	gettimeofday(&pkt->tv, &tz);
734*bd1f8aebSAndroid Build Coastguard Worker 
735*bd1f8aebSAndroid Build Coastguard Worker 	i = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
736*bd1f8aebSAndroid Build Coastguard Worker 	if (i < 0)
737*bd1f8aebSAndroid Build Coastguard Worker 	{
738*bd1f8aebSAndroid Build Coastguard Worker 		perror("setsockopt");
739*bd1f8aebSAndroid Build Coastguard Worker 		exit(1);
740*bd1f8aebSAndroid Build Coastguard Worker 	}
741*bd1f8aebSAndroid Build Coastguard Worker 
742*bd1f8aebSAndroid Build Coastguard Worker 	do {
743*bd1f8aebSAndroid Build Coastguard Worker 		i = sendto(sndsock, sendbuff, datalen, 0,
744*bd1f8aebSAndroid Build Coastguard Worker 			   (struct sockaddr *)&whereto, sizeof(whereto));
745*bd1f8aebSAndroid Build Coastguard Worker 	} while (i<0 && errno == ECONNREFUSED);
746*bd1f8aebSAndroid Build Coastguard Worker 
747*bd1f8aebSAndroid Build Coastguard Worker 	if (i < 0 || i != datalen)  {
748*bd1f8aebSAndroid Build Coastguard Worker 		if (i<0)
749*bd1f8aebSAndroid Build Coastguard Worker 			perror("sendto");
750*bd1f8aebSAndroid Build Coastguard Worker 		Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
751*bd1f8aebSAndroid Build Coastguard Worker 			datalen, i);
752*bd1f8aebSAndroid Build Coastguard Worker 		(void) fflush(stdout);
753*bd1f8aebSAndroid Build Coastguard Worker 	}
754*bd1f8aebSAndroid Build Coastguard Worker }
755*bd1f8aebSAndroid Build Coastguard Worker 
756*bd1f8aebSAndroid Build Coastguard Worker 
deltaT(struct timeval * t1p,struct timeval * t2p)757*bd1f8aebSAndroid Build Coastguard Worker double deltaT(struct timeval *t1p, struct timeval *t2p)
758*bd1f8aebSAndroid Build Coastguard Worker {
759*bd1f8aebSAndroid Build Coastguard Worker 	register double dt;
760*bd1f8aebSAndroid Build Coastguard Worker 
761*bd1f8aebSAndroid Build Coastguard Worker 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
762*bd1f8aebSAndroid Build Coastguard Worker 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
763*bd1f8aebSAndroid Build Coastguard Worker 	return (dt);
764*bd1f8aebSAndroid Build Coastguard Worker }
765*bd1f8aebSAndroid Build Coastguard Worker 
766*bd1f8aebSAndroid Build Coastguard Worker 
767*bd1f8aebSAndroid Build Coastguard Worker /*
768*bd1f8aebSAndroid Build Coastguard Worker  * Convert an ICMP "type" field to a printable string.
769*bd1f8aebSAndroid Build Coastguard Worker  */
pr_type(unsigned char t)770*bd1f8aebSAndroid Build Coastguard Worker char * pr_type(unsigned char t)
771*bd1f8aebSAndroid Build Coastguard Worker {
772*bd1f8aebSAndroid Build Coastguard Worker 	switch(t) {
773*bd1f8aebSAndroid Build Coastguard Worker 	/* Unknown */
774*bd1f8aebSAndroid Build Coastguard Worker 	case 0:
775*bd1f8aebSAndroid Build Coastguard Worker 		return "Error";
776*bd1f8aebSAndroid Build Coastguard Worker 	case 1:
777*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_DST_UNREACH: */
778*bd1f8aebSAndroid Build Coastguard Worker 		return "Destination Unreachable";
779*bd1f8aebSAndroid Build Coastguard Worker 	case 2:
780*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_PACKET_TOO_BIG: */
781*bd1f8aebSAndroid Build Coastguard Worker 		return "Packet Too Big";
782*bd1f8aebSAndroid Build Coastguard Worker 	case 3:
783*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_TIME_EXCEEDED */
784*bd1f8aebSAndroid Build Coastguard Worker 		return "Time Exceeded in Transit";
785*bd1f8aebSAndroid Build Coastguard Worker 	case 4:
786*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_PARAM_PROB */
787*bd1f8aebSAndroid Build Coastguard Worker 		return "Parameter Problem";
788*bd1f8aebSAndroid Build Coastguard Worker 	case 128:
789*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_ECHO_REQUEST */
790*bd1f8aebSAndroid Build Coastguard Worker 		return "Echo Request";
791*bd1f8aebSAndroid Build Coastguard Worker 	case 129:
792*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_ECHO_REPLY */
793*bd1f8aebSAndroid Build Coastguard Worker 		return "Echo Reply";
794*bd1f8aebSAndroid Build Coastguard Worker 	case 130:
795*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_MEMBERSHIP_QUERY */
796*bd1f8aebSAndroid Build Coastguard Worker 		return "Membership Query";
797*bd1f8aebSAndroid Build Coastguard Worker 	case 131:
798*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_MEMBERSHIP_REPORT */
799*bd1f8aebSAndroid Build Coastguard Worker 		return "Membership Report";
800*bd1f8aebSAndroid Build Coastguard Worker 	case 132:
801*bd1f8aebSAndroid Build Coastguard Worker 		/* ICMP6_MEMBERSHIP_REDUCTION */
802*bd1f8aebSAndroid Build Coastguard Worker 		return "Membership Reduction";
803*bd1f8aebSAndroid Build Coastguard Worker 	case 133:
804*bd1f8aebSAndroid Build Coastguard Worker 		/* ND_ROUTER_SOLICIT */
805*bd1f8aebSAndroid Build Coastguard Worker 		return "Router Solicitation";
806*bd1f8aebSAndroid Build Coastguard Worker 	case 134:
807*bd1f8aebSAndroid Build Coastguard Worker 		/* ND_ROUTER_ADVERT */
808*bd1f8aebSAndroid Build Coastguard Worker 		return "Router Advertisement";
809*bd1f8aebSAndroid Build Coastguard Worker 	case 135:
810*bd1f8aebSAndroid Build Coastguard Worker 		/* ND_NEIGHBOR_SOLICIT */
811*bd1f8aebSAndroid Build Coastguard Worker 		return "Neighbor Solicitation";
812*bd1f8aebSAndroid Build Coastguard Worker 	case 136:
813*bd1f8aebSAndroid Build Coastguard Worker 		/* ND_NEIGHBOR_ADVERT */
814*bd1f8aebSAndroid Build Coastguard Worker 		return "Neighbor Advertisement";
815*bd1f8aebSAndroid Build Coastguard Worker 	case 137:
816*bd1f8aebSAndroid Build Coastguard Worker 		/* ND_REDIRECT */
817*bd1f8aebSAndroid Build Coastguard Worker 		return "Redirect";
818*bd1f8aebSAndroid Build Coastguard Worker 	}
819*bd1f8aebSAndroid Build Coastguard Worker 
820*bd1f8aebSAndroid Build Coastguard Worker 	return("OUT-OF-RANGE");
821*bd1f8aebSAndroid Build Coastguard Worker }
822*bd1f8aebSAndroid Build Coastguard Worker 
823*bd1f8aebSAndroid Build Coastguard Worker 
packet_ok(u_char * buf,int cc,struct sockaddr_in6 * from,struct in6_addr * to,int seq,struct timeval * tv)824*bd1f8aebSAndroid Build Coastguard Worker int packet_ok(u_char *buf, int cc, struct sockaddr_in6 *from,
825*bd1f8aebSAndroid Build Coastguard Worker 	      struct in6_addr *to, int seq,
826*bd1f8aebSAndroid Build Coastguard Worker 	      struct timeval *tv)
827*bd1f8aebSAndroid Build Coastguard Worker {
828*bd1f8aebSAndroid Build Coastguard Worker 	struct icmp6_hdr *icp;
829*bd1f8aebSAndroid Build Coastguard Worker 	u_char type, code;
830*bd1f8aebSAndroid Build Coastguard Worker 
831*bd1f8aebSAndroid Build Coastguard Worker 	icp = (struct icmp6_hdr *) buf;
832*bd1f8aebSAndroid Build Coastguard Worker 
833*bd1f8aebSAndroid Build Coastguard Worker 	type = icp->icmp6_type;
834*bd1f8aebSAndroid Build Coastguard Worker 	code = icp->icmp6_code;
835*bd1f8aebSAndroid Build Coastguard Worker 
836*bd1f8aebSAndroid Build Coastguard Worker 	if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT) ||
837*bd1f8aebSAndroid Build Coastguard Worker 	    type == ICMP6_DST_UNREACH)
838*bd1f8aebSAndroid Build Coastguard Worker 	{
839*bd1f8aebSAndroid Build Coastguard Worker 		struct ip6_hdr *hip;
840*bd1f8aebSAndroid Build Coastguard Worker 		struct udphdr *up;
841*bd1f8aebSAndroid Build Coastguard Worker 		int nexthdr;
842*bd1f8aebSAndroid Build Coastguard Worker 
843*bd1f8aebSAndroid Build Coastguard Worker 		hip = (struct ip6_hdr *) (icp + 1);
844*bd1f8aebSAndroid Build Coastguard Worker 		up = (struct udphdr *)(hip+1);
845*bd1f8aebSAndroid Build Coastguard Worker 		nexthdr = hip->ip6_nxt;
846*bd1f8aebSAndroid Build Coastguard Worker 
847*bd1f8aebSAndroid Build Coastguard Worker 		if (nexthdr == 44) {
848*bd1f8aebSAndroid Build Coastguard Worker 			nexthdr = *(unsigned char*)up;
849*bd1f8aebSAndroid Build Coastguard Worker 			up++;
850*bd1f8aebSAndroid Build Coastguard Worker 		}
851*bd1f8aebSAndroid Build Coastguard Worker 		if (nexthdr == IPPROTO_UDP)
852*bd1f8aebSAndroid Build Coastguard Worker 		{
853*bd1f8aebSAndroid Build Coastguard Worker 			struct pkt_format *pkt;
854*bd1f8aebSAndroid Build Coastguard Worker 
855*bd1f8aebSAndroid Build Coastguard Worker 			pkt = (struct pkt_format *) (up + 1);
856*bd1f8aebSAndroid Build Coastguard Worker 
857*bd1f8aebSAndroid Build Coastguard Worker 			if (ntohl(pkt->ident) == ident &&
858*bd1f8aebSAndroid Build Coastguard Worker 			    ntohl(pkt->seq) == seq)
859*bd1f8aebSAndroid Build Coastguard Worker 			{
860*bd1f8aebSAndroid Build Coastguard Worker 				*tv = pkt->tv;
861*bd1f8aebSAndroid Build Coastguard Worker 				return (type == ICMP6_TIME_EXCEEDED ? -1 : code+1);
862*bd1f8aebSAndroid Build Coastguard Worker 			}
863*bd1f8aebSAndroid Build Coastguard Worker 		}
864*bd1f8aebSAndroid Build Coastguard Worker 
865*bd1f8aebSAndroid Build Coastguard Worker 	}
866*bd1f8aebSAndroid Build Coastguard Worker 
867*bd1f8aebSAndroid Build Coastguard Worker 	if (verbose) {
868*bd1f8aebSAndroid Build Coastguard Worker 		unsigned char *p;
869*bd1f8aebSAndroid Build Coastguard Worker 		char pa1[MAX_HOSTNAMELEN];
870*bd1f8aebSAndroid Build Coastguard Worker 		char pa2[MAX_HOSTNAMELEN];
871*bd1f8aebSAndroid Build Coastguard Worker 		int i;
872*bd1f8aebSAndroid Build Coastguard Worker 
873*bd1f8aebSAndroid Build Coastguard Worker 		p = (unsigned char *) (icp + 1);
874*bd1f8aebSAndroid Build Coastguard Worker 
875*bd1f8aebSAndroid Build Coastguard Worker 		Printf("\n%d bytes from %s to %s", cc,
876*bd1f8aebSAndroid Build Coastguard Worker 		       inet_ntop(AF_INET6, &from->sin6_addr, pa1, sizeof(pa1)),
877*bd1f8aebSAndroid Build Coastguard Worker 		       inet_ntop(AF_INET6, to, pa2, sizeof(pa2)));
878*bd1f8aebSAndroid Build Coastguard Worker 
879*bd1f8aebSAndroid Build Coastguard Worker 		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
880*bd1f8aebSAndroid Build Coastguard Worker 		       icp->icmp6_code);
881*bd1f8aebSAndroid Build Coastguard Worker 
882*bd1f8aebSAndroid Build Coastguard Worker 		cc -= sizeof(struct icmp6_hdr);
883*bd1f8aebSAndroid Build Coastguard Worker 		for (i = 0; i < cc ; i++) {
884*bd1f8aebSAndroid Build Coastguard Worker 			if (i % 16 == 0)
885*bd1f8aebSAndroid Build Coastguard Worker 				Printf("%04x:", i);
886*bd1f8aebSAndroid Build Coastguard Worker 			if (i % 4 == 0)
887*bd1f8aebSAndroid Build Coastguard Worker 				Printf(" ");
888*bd1f8aebSAndroid Build Coastguard Worker 			Printf("%02x", 0xff & (unsigned)p[i]);
889*bd1f8aebSAndroid Build Coastguard Worker 			if (i % 16 == 15 && i + 1 < cc)
890*bd1f8aebSAndroid Build Coastguard Worker 				Printf("\n");
891*bd1f8aebSAndroid Build Coastguard Worker 		}
892*bd1f8aebSAndroid Build Coastguard Worker 		Printf("\n");
893*bd1f8aebSAndroid Build Coastguard Worker 	}
894*bd1f8aebSAndroid Build Coastguard Worker 
895*bd1f8aebSAndroid Build Coastguard Worker 	return(0);
896*bd1f8aebSAndroid Build Coastguard Worker }
897*bd1f8aebSAndroid Build Coastguard Worker 
898*bd1f8aebSAndroid Build Coastguard Worker 
print(unsigned char * buf,int cc,struct sockaddr_in6 * from)899*bd1f8aebSAndroid Build Coastguard Worker void print(unsigned char *buf, int cc, struct sockaddr_in6 *from)
900*bd1f8aebSAndroid Build Coastguard Worker {
901*bd1f8aebSAndroid Build Coastguard Worker 	char pa[MAX_HOSTNAMELEN];
902*bd1f8aebSAndroid Build Coastguard Worker 
903*bd1f8aebSAndroid Build Coastguard Worker 	if (nflag)
904*bd1f8aebSAndroid Build Coastguard Worker 		Printf(" %s", inet_ntop(AF_INET6, &from->sin6_addr,
905*bd1f8aebSAndroid Build Coastguard Worker 					pa, sizeof(pa)));
906*bd1f8aebSAndroid Build Coastguard Worker 	else
907*bd1f8aebSAndroid Build Coastguard Worker 	{
908*bd1f8aebSAndroid Build Coastguard Worker 		const char *hostname;
909*bd1f8aebSAndroid Build Coastguard Worker 		struct hostent *hp;
910*bd1f8aebSAndroid Build Coastguard Worker 		char *s = NULL;
911*bd1f8aebSAndroid Build Coastguard Worker 
912*bd1f8aebSAndroid Build Coastguard Worker 		hostname = inet_ntop(AF_INET6, &from->sin6_addr, pa, sizeof(pa));
913*bd1f8aebSAndroid Build Coastguard Worker 
914*bd1f8aebSAndroid Build Coastguard Worker 		if ((hp = gethostbyaddr((char *)&from->sin6_addr,
915*bd1f8aebSAndroid Build Coastguard Worker 					sizeof(from->sin6_addr), AF_INET6))) {
916*bd1f8aebSAndroid Build Coastguard Worker #ifdef USE_IDN
917*bd1f8aebSAndroid Build Coastguard Worker 			if (idna_to_unicode_lzlz(hp->h_name, &s, 0) != IDNA_SUCCESS)
918*bd1f8aebSAndroid Build Coastguard Worker 				s = NULL;
919*bd1f8aebSAndroid Build Coastguard Worker #endif
920*bd1f8aebSAndroid Build Coastguard Worker 		}
921*bd1f8aebSAndroid Build Coastguard Worker 
922*bd1f8aebSAndroid Build Coastguard Worker 		Printf(" %s (%s)", hp ? (s ? s : hp->h_name) : hostname, pa);
923*bd1f8aebSAndroid Build Coastguard Worker 
924*bd1f8aebSAndroid Build Coastguard Worker 		free(s);
925*bd1f8aebSAndroid Build Coastguard Worker 	}
926*bd1f8aebSAndroid Build Coastguard Worker }
927*bd1f8aebSAndroid Build Coastguard Worker 
928*bd1f8aebSAndroid Build Coastguard Worker 
929*bd1f8aebSAndroid Build Coastguard Worker /*
930*bd1f8aebSAndroid Build Coastguard Worker  * Subtract 2 timeval structs:  out = out - in.
931*bd1f8aebSAndroid Build Coastguard Worker  * Out is assumed to be >= in.
932*bd1f8aebSAndroid Build Coastguard Worker  */
933*bd1f8aebSAndroid Build Coastguard Worker void
tvsub(out,in)934*bd1f8aebSAndroid Build Coastguard Worker tvsub(out, in)
935*bd1f8aebSAndroid Build Coastguard Worker 	register struct timeval *out, *in;
936*bd1f8aebSAndroid Build Coastguard Worker {
937*bd1f8aebSAndroid Build Coastguard Worker 	if ((out->tv_usec -= in->tv_usec) < 0)   {
938*bd1f8aebSAndroid Build Coastguard Worker 		out->tv_sec--;
939*bd1f8aebSAndroid Build Coastguard Worker 		out->tv_usec += 1000000;
940*bd1f8aebSAndroid Build Coastguard Worker 	}
941*bd1f8aebSAndroid Build Coastguard Worker 	out->tv_sec -= in->tv_sec;
942*bd1f8aebSAndroid Build Coastguard Worker }
943*bd1f8aebSAndroid Build Coastguard Worker 
usage(void)944*bd1f8aebSAndroid Build Coastguard Worker void usage(void)
945*bd1f8aebSAndroid Build Coastguard Worker {
946*bd1f8aebSAndroid Build Coastguard Worker 	fprintf(stderr,
947*bd1f8aebSAndroid Build Coastguard Worker "Usage: traceroute6 [-dnrvV] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
948*bd1f8aebSAndroid Build Coastguard Worker [-s src_addr] [-t tos] [-w wait] host [data size]\n");
949*bd1f8aebSAndroid Build Coastguard Worker 	exit(1);
950*bd1f8aebSAndroid Build Coastguard Worker }
951