2ba558fc2112def5dae90791d1b820bfc8d6528a
[platform/upstream/busybox.git] / networking / traceroute.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * Busybox port by Vladimir Oleynik (C) 2005 <dzo@simtreas.ru>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  */
24
25 /*
26  * traceroute host  - trace the route ip packets follow going to "host".
27  *
28  * Attempt to trace the route an ip packet would follow to some
29  * internet host.  We find out intermediate hops by launching probe
30  * packets with a small ttl (time to live) then listening for an
31  * icmp "time exceeded" reply from a gateway.  We start our probes
32  * with a ttl of one and increase by one until we get an icmp "port
33  * unreachable" (which means we got to "host") or hit a max (which
34  * defaults to 30 hops & can be changed with the -m flag).  Three
35  * probes (change with -q flag) are sent at each ttl setting and a
36  * line is printed showing the ttl, address of the gateway and
37  * round trip time of each probe.  If the probe answers come from
38  * different gateways, the address of each responding system will
39  * be printed.  If there is no response within a 5 sec. timeout
40  * interval (changed with the -w flag), a "*" is printed for that
41  * probe.
42  *
43  * Probe packets are UDP format.  We don't want the destination
44  * host to process them so the destination port is set to an
45  * unlikely value (if some clod on the destination is using that
46  * value, it can be changed with the -p flag).
47  *
48  * A sample use might be:
49  *
50  *     [yak 71]% traceroute nis.nsf.net.
51  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
52  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
53  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
54  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
55  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
56  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
57  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
58  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
59  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
60  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
61  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
62  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
63  *
64  * Note that lines 2 & 3 are the same.  This is due to a buggy
65  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
66  * packets with a zero ttl.
67  *
68  * A more interesting example is:
69  *
70  *     [yak 72]% traceroute allspice.lcs.mit.edu.
71  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
72  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
73  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
74  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
75  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
76  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
77  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
78  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
79  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
80  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
81  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
82  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
83  *     12  * * *
84  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
85  *     14  * * *
86  *     15  * * *
87  *     16  * * *
88  *     17  * * *
89  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
90  *
91  * (I start to see why I'm having so much trouble with mail to
92  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
93  * either don't send ICMP "time exceeded" messages or send them
94  * with a ttl too small to reach us.  14 - 17 are running the
95  * MIT C Gateway code that doesn't send "time exceeded"s.  God
96  * only knows what's going on with 12.
97  *
98  * The silent gateway 12 in the above may be the result of a bug in
99  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
100  * sends an unreachable message using whatever ttl remains in the
101  * original datagram.  Since, for gateways, the remaining ttl is
102  * zero, the icmp "time exceeded" is guaranteed to not make it back
103  * to us.  The behavior of this bug is slightly more interesting
104  * when it appears on the destination system:
105  *
106  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
107  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
108  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
109  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
110  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
111  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
112  *      7  * * *
113  *      8  * * *
114  *      9  * * *
115  *     10  * * *
116  *     11  * * *
117  *     12  * * *
118  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
119  *
120  * Notice that there are 12 "gateways" (13 is the final
121  * destination) and exactly the last half of them are "missing".
122  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
123  * is using the ttl from our arriving datagram as the ttl in its
124  * icmp reply.  So, the reply will time out on the return path
125  * (with no notice sent to anyone since icmp's aren't sent for
126  * icmp's) until we probe with a ttl that's at least twice the path
127  * length.  I.e., rip is really only 7 hops away.  A reply that
128  * returns with a ttl of 1 is a clue this problem exists.
129  * Traceroute prints a "!" after the time if the ttl is <= 1.
130  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
131  * non-standard (HPUX) software, expect to see this problem
132  * frequently and/or take care picking the target host of your
133  * probes.
134  *
135  * Other possible annotations after the time are !H, !N, !P (got a host,
136  * network or protocol unreachable, respectively), !S or !F (source
137  * route failed or fragmentation needed -- neither of these should
138  * ever occur and the associated gateway is busted if you see one).  If
139  * almost all the probes result in some kind of unreachable, traceroute
140  * will give up and exit.
141  *
142  * Notes
143  * -----
144  * This program must be run by root or be setuid.  (I suggest that
145  * you *don't* make it setuid -- casual use could result in a lot
146  * of unnecessary traffic on our poor, congested nets.)
147  *
148  * This program requires a kernel mod that does not appear in any
149  * system available from Berkeley:  A raw ip socket using proto
150  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
151  * opposed to data to be wrapped in a ip datagram).  See the README
152  * file that came with the source to this program for a description
153  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
154  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
155  * MODIFIED TO RUN THIS PROGRAM.
156  *
157  * The udp port usage may appear bizarre (well, ok, it is bizarre).
158  * The problem is that an icmp message only contains 8 bytes of
159  * data from the original datagram.  8 bytes is the size of a udp
160  * header so, if we want to associate replies with the original
161  * datagram, the necessary information must be encoded into the
162  * udp header (the ip id could be used but there's no way to
163  * interlock with the kernel's assignment of ip id's and, anyway,
164  * it would have taken a lot more kernel hacking to allow this
165  * code to set the ip id).  So, to allow two or more users to
166  * use traceroute simultaneously, we use this task's pid as the
167  * source port (the high bit is set to move the port number out
168  * of the "likely" range).  To keep track of which probe is being
169  * replied to (so times and/or hop counts don't get confused by a
170  * reply that was delayed in transit), we increment the destination
171  * port number before each probe.
172  *
173  * Don't use this as a coding example.  I was trying to find a
174  * routing problem and this code sort-of popped out after 48 hours
175  * without sleep.  I was amazed it ever compiled, much less ran.
176  *
177  * I stole the idea for this program from Steve Deering.  Since
178  * the first release, I've learned that had I attended the right
179  * IETF working group meetings, I also could have stolen it from Guy
180  * Almes or Matt Mathis.  I don't know (or care) who came up with
181  * the idea first.  I envy the originators' perspicacity and I'm
182  * glad they didn't keep the idea a secret.
183  *
184  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
185  * enhancements to the original distribution.
186  *
187  * I've hacked up a round-trip-route version of this that works by
188  * sending a loose-source-routed udp datagram through the destination
189  * back to yourself.  Unfortunately, SO many gateways botch source
190  * routing, the thing is almost worthless.  Maybe one day...
191  *
192  *  -- Van Jacobson (van@ee.lbl.gov)
193  *     Tue Dec 20 03:50:13 PST 1988
194  */
195
196 #define TRACEROUTE_SO_DEBUG 0
197
198 /* TODO: undefs were uncommented - ??! we have config system for that! */
199 /* probably ok to remove altogether */
200 //#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
201 //#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
202 //#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
203 //#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
204 //#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
205 //#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
206
207
208 #include <net/if.h>
209 #include <arpa/inet.h>
210 #include <netinet/in.h>
211 #include <netinet/udp.h>
212 #include <netinet/ip.h>
213 #include <netinet/ip_icmp.h>
214
215 #include "libbb.h"
216 #include "inet_common.h"
217
218
219 /*
220  * Definitions for internet protocol version 4.
221  * Per RFC 791, September 1981.
222  */
223 #define IPVERSION 4
224
225 #ifndef IPPROTO_ICMP
226 /* Grrrr.... */
227 #define IPPROTO_ICMP 1
228 #endif
229 #ifndef IPPROTO_IP
230 #define IPPROTO_IP 0
231 #endif
232
233 /*
234  * Overlay for ip header used by other protocols (tcp, udp).
235  */
236 struct ipovly {
237         unsigned char  ih_x1[9];               /* (unused) */
238         unsigned char  ih_pr;                  /* protocol */
239         short   ih_len;                 /* protocol length */
240         struct  in_addr ih_src;         /* source internet address */
241         struct  in_addr ih_dst;         /* destination internet address */
242 };
243
244 /*
245  * UDP kernel structures and variables.
246  */
247 struct udpiphdr {
248         struct  ipovly ui_i;            /* overlaid ip structure */
249         struct  udphdr ui_u;            /* udp header */
250 };
251 #define ui_next         ui_i.ih_next
252 #define ui_prev         ui_i.ih_prev
253 #define ui_x1           ui_i.ih_x1
254 #define ui_pr           ui_i.ih_pr
255 #define ui_len          ui_i.ih_len
256 #define ui_src          ui_i.ih_src
257 #define ui_dst          ui_i.ih_dst
258 #define ui_sport        ui_u.uh_sport
259 #define ui_dport        ui_u.uh_dport
260 #define ui_ulen         ui_u.uh_ulen
261 #define ui_sum          ui_u.uh_sum
262
263
264 /* Host name and address list */
265 struct hostinfo {
266         char *name;
267         int n;
268         uint32_t *addrs;
269 };
270
271 /* Data section of the probe packet */
272 typedef struct outdata {
273         unsigned char seq;             /* sequence number of this packet */
274         unsigned char ttl;             /* ttl packet left with */
275 // UNUSED. Retaining to have the same packet size.
276         struct timeval tv_UNUSED ATTRIBUTE_PACKED; /* time packet left */
277 } outdata_t;
278
279 struct IFADDRLIST {
280         uint32_t addr;
281         char device[sizeof(struct ifreq)];
282 };
283
284
285 /* Keep in sync with getopt32 call! */
286 #define OPT_DONT_FRAGMNT (1<<0)    /* F */
287 #define OPT_USE_ICMP     (1<<1)    /* I */
288 #define OPT_TTL_FLAG     (1<<2)    /* l */
289 #define OPT_ADDR_NUM     (1<<3)    /* n */
290 #define OPT_BYPASS_ROUTE (1<<4)    /* r */
291 #define OPT_DEBUG        (1<<5)    /* d */
292 #define OPT_VERBOSE      (1<<6)    /* v */
293 #define OPT_IP_CHKSUM    (1<<7)    /* x */
294 #define OPT_TOS          (1<<8)    /* t */
295 #define OPT_DEVICE       (1<<9)    /* i */
296 #define OPT_MAX_TTL      (1<<10)   /* m */
297 #define OPT_PORT         (1<<11)   /* p */
298 #define OPT_NPROBES      (1<<12)   /* q */
299 #define OPT_SOURCE       (1<<13)   /* s */
300 #define OPT_WAITTIME     (1<<14)   /* w */
301 #define OPT_PAUSE_MS     (1<<15)   /* z */
302 #define OPT_FIRST_TTL    (1<<16)   /* f */
303
304 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
305 /* use icmp echo instead of udp packets */
306 #define useicmp (option_mask32 & OPT_USE_ICMP)
307 #endif
308 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
309 #define verbose (option_mask32 & OPT_VERBOSE)
310 #endif
311 #define nflag   (option_mask32 & OPT_ADDR_NUM)
312
313
314 struct globals {
315         struct ip *outip;               /* last output (udp) packet */
316         struct udphdr *outudp;          /* last output (udp) packet */
317         struct outdata *outdata;        /* last output (udp) packet */
318
319 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
320         struct icmp *outicmp;           /* last output (icmp) packet */
321 #endif
322
323         int rcvsock;                    /* receive (icmp) socket file descriptor */
324         int sndsock;                    /* send (udp/icmp) socket file descriptor */
325
326         int packlen;                    /* total length of packet */
327         int minpacket;                  /* min ip packet size */
328         int maxpacket; // 32 * 1024;    /* max ip packet size */
329         int pmtu;                       /* Path MTU Discovery (RFC1191) */
330
331         char *hostname;
332
333         uint16_t ident;
334         uint16_t port; // 32768 + 666;  /* start udp dest port # for probe packets */
335
336         int waittime; // 5;             /* time to wait for response (in seconds) */
337         int doipcksum; // 1;            /* calculate ip checksums by default */
338
339 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
340         int optlen;                     /* length of ip options */
341 #else
342 #define optlen 0
343 #endif
344
345         struct sockaddr_storage whereto;        /* Who to try to reach */
346         struct sockaddr_storage wherefrom;      /* Who we are */
347         /* last inbound (icmp) packet */
348         unsigned char packet[512];
349 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
350         /* Maximum number of gateways (include room for one noop) */
351 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
352         /* loose source route gateway list (including room for final destination) */
353         uint32_t gwlist[NGATEWAYS + 1];
354 #endif
355 };
356
357 #define G (*ptr_to_globals)
358 #define outip     (G.outip    )
359 #define outudp    (G.outudp   )
360 #define outdata   (G.outdata  )
361 #define outicmp   (G.outicmp  )
362 #define rcvsock   (G.rcvsock  )
363 #define sndsock   (G.sndsock  )
364 #define packlen   (G.packlen  )
365 #define minpacket (G.minpacket)
366 #define maxpacket (G.maxpacket)
367 #define pmtu      (G.pmtu     )
368 #define hostname  (G.hostname )
369 #define ident     (G.ident    )
370 #define port      (G.port     )
371 #define waittime  (G.waittime )
372 #define doipcksum (G.doipcksum)
373 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
374 #define optlen    (G.optlen   )
375 #endif
376 #define packet    (G.packet   )
377 #define whereto   (G.whereto  )
378 #define wherefrom (G.wherefrom)
379 #define gwlist    (G.gwlist   )
380 #define INIT_G() do { \
381         PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
382         maxpacket = 32 * 1024; \
383         port = 32768 + 666; \
384         waittime = 5; \
385         doipcksum = 1; \
386 } while (0)
387
388
389 /*
390  * Return the interface list
391  */
392 static int
393 ifaddrlist(struct IFADDRLIST **ipaddrp)
394 {
395         enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) };
396
397         int fd, nipaddr;
398 #ifdef HAVE_SOCKADDR_SA_LEN
399         int n;
400 #endif
401         struct ifreq *ifrp, *ifend, *ifnext;
402         struct sockaddr_in *addr_sin;
403         struct IFADDRLIST *al;
404         struct ifconf ifc;
405         struct ifreq ifr;
406         /* Was on stack, but 32k is a bit too much: */
407         struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0]));
408         struct IFADDRLIST *st_ifaddrlist;
409
410         fd = xsocket(AF_INET, SOCK_DGRAM, 0);
411
412         ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]);
413         ifc.ifc_buf = (caddr_t)ibuf;
414
415         if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
416          || ifc.ifc_len < sizeof(struct ifreq)
417         ) {
418                 if (errno == EINVAL)
419                         bb_error_msg_and_die(
420                             "SIOCGIFCONF: ifreq struct too small (%u bytes)",
421                             (unsigned)(IFREQ_BUFSIZE * sizeof(ibuf[0])));
422                 bb_perror_msg_and_die("SIOCGIFCONF");
423         }
424         ifrp = ibuf;
425         ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
426
427         nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
428         st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST));
429         al = st_ifaddrlist;
430         nipaddr = 0;
431
432         for (; ifrp < ifend; ifrp = ifnext) {
433 #ifdef HAVE_SOCKADDR_SA_LEN
434                 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
435                 if (n < sizeof(*ifrp))
436                         ifnext = ifrp + 1;
437                 else
438                         ifnext = (struct ifreq *)((char *)ifrp + n);
439                 if (ifrp->ifr_addr.sa_family != AF_INET)
440                         continue;
441 #else
442                 ifnext = ifrp + 1;
443 #endif
444                 /*
445                  * Need a template to preserve address info that is
446                  * used below to locate the next entry.  (Otherwise,
447                  * SIOCGIFFLAGS stomps over it because the requests
448                  * are returned in a union.)
449                  */
450                 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
451                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
452                         if (errno == ENXIO)
453                                 continue;
454                         bb_perror_msg_and_die("SIOCGIFFLAGS: %.*s",
455                             (int)sizeof(ifr.ifr_name), ifr.ifr_name);
456                 }
457
458                 /* Must be up */
459                 if ((ifr.ifr_flags & IFF_UP) == 0)
460                         continue;
461
462                 safe_strncpy(al->device, ifr.ifr_name, sizeof(ifr.ifr_name) + 1);
463 #ifdef sun
464                 /* Ignore sun virtual interfaces */
465                 if (strchr(al->device, ':') != NULL)
466                         continue;
467 #endif
468                 ioctl_or_perror_and_die(fd, SIOCGIFADDR, (char *)&ifr,
469                                 "SIOCGIFADDR: %s", al->device);
470
471                 addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
472                 al->addr = addr_sin->sin_addr.s_addr;
473                 ++al;
474                 ++nipaddr;
475         }
476         if (nipaddr == 0)
477                 bb_error_msg_and_die("can't find any network interfaces");
478
479         free(ibuf);
480         close(fd);
481         *ipaddrp = st_ifaddrlist;
482         return nipaddr;
483 }
484
485
486 static void
487 setsin(struct sockaddr_in *addr_sin, uint32_t addr)
488 {
489         memset(addr_sin, 0, sizeof(*addr_sin));
490 #ifdef HAVE_SOCKADDR_SA_LEN
491         addr_sin->sin_len = sizeof(*addr_sin);
492 #endif
493         addr_sin->sin_family = AF_INET;
494         addr_sin->sin_addr.s_addr = addr;
495 }
496
497
498 /*
499  * Return the source address for the given destination address
500  */
501 static void
502 findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
503 {
504         int i, n;
505         FILE *f;
506         uint32_t mask;
507         uint32_t dest, tmask;
508         struct IFADDRLIST *al;
509         char buf[256], tdevice[256], device[256];
510
511         f = xfopen("/proc/net/route", "r");
512
513         /* Find the appropriate interface */
514         n = 0;
515         mask = 0;
516         device[0] = '\0';
517         while (fgets(buf, sizeof(buf), f) != NULL) {
518                 ++n;
519                 if (n == 1 && strncmp(buf, "Iface", 5) == 0)
520                         continue;
521                 i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
522                                         tdevice, &dest, &tmask);
523                 if (i != 3)
524                         bb_error_msg_and_die("junk in buffer");
525                 if ((to->sin_addr.s_addr & tmask) == dest
526                  && (tmask > mask || mask == 0)
527                 ) {
528                         mask = tmask;
529                         strcpy(device, tdevice);
530                 }
531         }
532         fclose(f);
533
534         if (device[0] == '\0')
535                 bb_error_msg_and_die("can't find interface");
536
537         /* Get the interface address list */
538         n = ifaddrlist(&al);
539
540         /* Find our appropriate source address */
541         for (i = n; i > 0; --i, ++al)
542                 if (strcmp(device, al->device) == 0)
543                         break;
544         if (i <= 0)
545                 bb_error_msg_and_die("can't find interface %s", device);
546
547         setsin(from, al->addr);
548 }
549
550 /*
551 "Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
552 "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
553 "\t[-w waittime] [-z pausemsecs] host [packetlen]"
554
555 */
556
557 static int
558 wait_for_reply(int sock, struct sockaddr_in *fromp)
559 {
560         struct pollfd pfd[1];
561         int cc = 0;
562         socklen_t fromlen = sizeof(*fromp);
563
564         pfd[0].fd = sock;
565         pfd[0].events = POLLIN;
566         if (safe_poll(pfd, 1, waittime * 1000) > 0)
567                 cc = recvfrom(sock, packet, sizeof(packet), 0,
568                             (struct sockaddr *)fromp, &fromlen);
569         return cc;
570 }
571
572 /*
573  * Checksum routine for Internet Protocol family headers (C Version)
574  */
575 static uint16_t
576 in_cksum(uint16_t *addr, int len)
577 {
578         int nleft = len;
579         uint16_t *w = addr;
580         uint16_t answer;
581         int sum = 0;
582
583         /*
584          *  Our algorithm is simple, using a 32 bit accumulator (sum),
585          *  we add sequential 16 bit words to it, and at the end, fold
586          *  back all the carry bits from the top 16 bits into the lower
587          *  16 bits.
588          */
589         while (nleft > 1)  {
590                 sum += *w++;
591                 nleft -= 2;
592         }
593
594         /* mop up an odd byte, if necessary */
595         if (nleft == 1)
596                 sum += *(unsigned char *)w;
597
598         /*
599          * add back carry outs from top 16 bits to low 16 bits
600          */
601         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
602         sum += (sum >> 16);                     /* add carry */
603         answer = ~sum;                          /* truncate to 16 bits */
604         return answer;
605 }
606
607
608 static void
609 send_probe(int seq, int ttl)
610 {
611         int cc;
612         struct udpiphdr *ui, *oui;
613         struct ip tip;
614
615         outip->ip_ttl = ttl;
616         outip->ip_id = htons(ident + seq);
617
618         /*
619          * In most cases, the kernel will recalculate the ip checksum.
620          * But we must do it anyway so that the udp checksum comes out
621          * right.
622          */
623         if (doipcksum) {
624                 outip->ip_sum =
625                     in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
626                 if (outip->ip_sum == 0)
627                         outip->ip_sum = 0xffff;
628         }
629
630         /* Payload */
631         outdata->seq = seq;
632         outdata->ttl = ttl;
633 // UNUSED: was storing gettimeofday's result there, but never ever checked it
634         /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
635
636 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
637         if (useicmp)
638                 outicmp->icmp_seq = htons(seq);
639         else
640 #endif
641                 outudp->dest = htons(port + seq);
642
643 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
644         if (useicmp) {
645                 /* Always calculate checksum for icmp packets */
646                 outicmp->icmp_cksum = 0;
647                 outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp,
648                     packlen - (sizeof(*outip) + optlen));
649                 if (outicmp->icmp_cksum == 0)
650                         outicmp->icmp_cksum = 0xffff;
651         } else
652 #endif
653         if (doipcksum) {
654                 /* Checksum (we must save and restore ip header) */
655                 tip = *outip;
656                 ui = (struct udpiphdr *)outip;
657                 oui = (struct udpiphdr *)&tip;
658                 /* Easier to zero and put back things that are ok */
659                 memset((char *)ui, 0, sizeof(ui->ui_i));
660                 ui->ui_src = oui->ui_src;
661                 ui->ui_dst = oui->ui_dst;
662                 ui->ui_pr = oui->ui_pr;
663                 ui->ui_len = outudp->len;
664                 outudp->check = 0;
665                 outudp->check = in_cksum((uint16_t *)ui, packlen);
666                 if (outudp->check == 0)
667                         outudp->check = 0xffff;
668                 *outip = tip;
669         }
670
671 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
672         /* XXX undocumented debugging hack */
673         if (verbose > 1) {
674                 const uint16_t *sp;
675                 int nshorts, i;
676
677                 sp = (uint16_t *)outip;
678                 nshorts = (unsigned)packlen / sizeof(uint16_t);
679                 i = 0;
680                 printf("[ %d bytes", packlen);
681                 while (--nshorts >= 0) {
682                         if ((i++ % 8) == 0)
683                                 printf("\n\t");
684                         printf(" %04x", ntohs(*sp));
685                         sp++;
686                 }
687                 if (packlen & 1) {
688                         if ((i % 8) == 0)
689                                 printf("\n\t");
690                         printf(" %02x", *(unsigned char *)sp);
691                 }
692                 printf("]\n");
693         }
694 #endif
695
696 #if !defined(IP_HDRINCL) && defined(IP_TTL)
697         if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
698             (char *)&ttl, sizeof(ttl)) < 0) {
699                 bb_perror_msg_and_die("setsockopt ttl %d", ttl);
700         }
701 #endif
702
703         cc = xsendto(sndsock, (char *)outip,
704             packlen, (struct sockaddr *)&whereto, sizeof(whereto));
705         if (cc != packlen)  {
706                 bb_info_msg("wrote %s %d chars, ret=%d", hostname, packlen, cc);
707         }
708 }
709
710 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
711 /*
712  * Convert an ICMP "type" field to a printable string.
713  */
714 static inline const char *
715 pr_type(unsigned char t)
716 {
717         static const char *const ttab[] = {
718         "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
719         "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
720         "Echo",         "Router Advert", "Router Solicit", "Time Exceeded",
721         "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
722         "Info Reply",   "Mask Request", "Mask Reply"
723         };
724
725         if (t > 18)
726                 return "OUT-OF-RANGE";
727
728         return ttab[t];
729 }
730 #endif
731
732 static int
733 packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
734 {
735         struct icmp *icp;
736         unsigned char type, code;
737         int hlen;
738         struct ip *ip;
739
740         ip = (struct ip *) buf;
741         hlen = ip->ip_hl << 2;
742         if (cc < hlen + ICMP_MINLEN) {
743 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
744                 if (verbose)
745                         printf("packet too short (%d bytes) from %s\n", cc,
746                                 inet_ntoa(from->sin_addr));
747 #endif
748                 return 0;
749         }
750         cc -= hlen;
751         icp = (struct icmp *)(buf + hlen);
752         type = icp->icmp_type;
753         code = icp->icmp_code;
754         /* Path MTU Discovery (RFC1191) */
755         if (code != ICMP_UNREACH_NEEDFRAG)
756                 pmtu = 0;
757         else {
758                 pmtu = ntohs(icp->icmp_nextmtu);
759         }
760         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
761             type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
762                 struct ip *hip;
763                 struct udphdr *up;
764
765                 hip = &icp->icmp_ip;
766                 hlen = hip->ip_hl << 2;
767 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
768                 if (useicmp) {
769                         struct icmp *hicmp;
770
771                         /* XXX */
772                         if (type == ICMP_ECHOREPLY &&
773                             icp->icmp_id == htons(ident) &&
774                             icp->icmp_seq == htons(seq))
775                                 return -2;
776
777                         hicmp = (struct icmp *)((unsigned char *)hip + hlen);
778                         /* XXX 8 is a magic number */
779                         if (hlen + 8 <= cc &&
780                             hip->ip_p == IPPROTO_ICMP &&
781                             hicmp->icmp_id == htons(ident) &&
782                             hicmp->icmp_seq == htons(seq))
783                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
784                 } else
785 #endif
786                 {
787                         up = (struct udphdr *)((unsigned char *)hip + hlen);
788                         /* XXX 8 is a magic number */
789                         if (hlen + 12 <= cc &&
790                             hip->ip_p == IPPROTO_UDP &&
791                             up->source == htons(ident) &&
792                             up->dest == htons(port + seq))
793                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
794                 }
795         }
796 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
797         if (verbose) {
798                 int i;
799                 uint32_t *lp = (uint32_t *)&icp->icmp_ip;
800
801                 printf("\n%d bytes from %s to "
802                        "%s: icmp type %d (%s) code %d\n",
803                     cc, inet_ntoa(from->sin_addr),
804                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
805                 for (i = 4; i < cc; i += sizeof(*lp))
806                         printf("%2d: x%8.8x\n", i, *lp++);
807         }
808 #endif
809         return 0;
810 }
811
812
813 /*
814  * Construct an Internet address representation.
815  * If the nflag has been supplied, give
816  * numeric value, otherwise try for symbolic name.
817  */
818 static inline void
819 print_inetname(struct sockaddr_in *from)
820 {
821         const char *ina;
822
823         ina = inet_ntoa(from->sin_addr);
824         if (nflag)
825                 printf(" %s", ina);
826         else {
827                 char *n = NULL;
828                 if (from->sin_addr.s_addr != INADDR_ANY)
829                         n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
830                 printf(" %s (%s)", (n ? n : ina), ina);
831                 free(n);
832         }
833 }
834
835 static inline void
836 print(unsigned char *buf, int cc, struct sockaddr_in *from)
837 {
838         struct ip *ip;
839         int hlen;
840
841         ip = (struct ip *) buf;
842         hlen = ip->ip_hl << 2;
843         cc -= hlen;
844
845         print_inetname(from);
846 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
847         if (verbose)
848                 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
849 #endif
850 }
851
852
853 static struct hostinfo *
854 gethostinfo(const char *host)
855 {
856         int n;
857         struct hostent *hp;
858         struct hostinfo *hi;
859         char **p;
860         uint32_t addr, *ap;
861
862         hi = xzalloc(sizeof(*hi));
863         addr = inet_addr(host);
864         if (addr != 0xffffffff) {
865                 hi->name = xstrdup(host);
866                 hi->n = 1;
867                 hi->addrs = xzalloc(sizeof(hi->addrs[0]));
868                 hi->addrs[0] = addr;
869                 return hi;
870         }
871
872         hp = xgethostbyname(host);
873         if (hp->h_addrtype != AF_INET || hp->h_length != 4)
874                 bb_perror_msg_and_die("bad host %s", host);
875         hi->name = xstrdup(hp->h_name);
876         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
877                 continue;
878         hi->n = n;
879         hi->addrs = xzalloc(n * sizeof(hi->addrs[0]));
880         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
881                 memcpy(ap, *p, sizeof(*ap));
882         return hi;
883 }
884
885 static void
886 freehostinfo(struct hostinfo *hi)
887 {
888         free(hi->name);
889         free(hi->addrs);
890         free(hi);
891 }
892
893 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
894 static void
895 getaddr(uint32_t *ap, const char *host)
896 {
897         struct hostinfo *hi;
898
899         hi = gethostinfo(host);
900         *ap = hi->addrs[0];
901         freehostinfo(hi);
902 }
903 #endif
904
905 static void
906 print_delta_ms(unsigned t1p, unsigned t2p)
907 {
908         unsigned tt = t2p - t1p;
909         printf("  %u.%03u ms", tt/1000, tt%1000);
910 }
911
912 int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
913 int traceroute_main(int argc, char **argv)
914 {
915         int code, n;
916         unsigned char *outp;
917         uint32_t *ap;
918         struct sockaddr_in *from;
919         struct sockaddr_in *to;
920         struct hostinfo *hi;
921         int ttl, probe, i;
922         int seq = 0;
923         int tos = 0;
924         char *tos_str;
925         char *source;
926         unsigned op;
927 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
928         int lsrr = 0;
929 #endif
930         uint16_t off = 0;
931         struct IFADDRLIST *al;
932         char *device;
933         int max_ttl = 30;
934         char *max_ttl_str;
935         char *port_str;
936         int nprobes = 3;
937         char *nprobes_str;
938         char *waittime_str;
939         unsigned pausemsecs = 0;
940         char *pausemsecs_str;
941         int first_ttl = 1;
942         char *first_ttl_str;
943 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
944         llist_t *source_route_list = NULL;
945 #endif
946
947         INIT_G();
948         from = (struct sockaddr_in *)&wherefrom;
949         to = (struct sockaddr_in *)&whereto;
950
951         //opterr = 0;
952 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
953         opt_complementary = "x-x:g::";
954 #else
955         opt_complementary = "x-x";
956 #endif
957
958         op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
959 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
960                                         "g:"
961 #endif
962                 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
963                 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
964 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
965                 , &source_route_list
966 #endif
967         );
968
969         if (op & OPT_DONT_FRAGMNT)
970                 off = IP_DF;
971         if (op & OPT_IP_CHKSUM) {
972                 doipcksum = 0;
973                 bb_error_msg("warning: ip checksums disabled");
974         }
975         if (op & OPT_TOS)
976                 tos = xatou_range(tos_str, 0, 255);
977         if (op & OPT_MAX_TTL)
978                 max_ttl = xatou_range(max_ttl_str, 1, 255);
979         if (op & OPT_PORT)
980                 port = xatou16(port_str);
981         if (op & OPT_NPROBES)
982                 nprobes = xatou_range(nprobes_str, 1, INT_MAX);
983         if (op & OPT_SOURCE) {
984                 /*
985                  * set the ip source address of the outbound
986                  * probe (e.g., on a multi-homed host).
987                  */
988                 if (getuid())
989                         bb_error_msg_and_die("-s %s: permission denied", source);
990         }
991         if (op & OPT_WAITTIME)
992                 waittime = xatou_range(waittime_str, 2, 24 * 60 * 60);
993         if (op & OPT_PAUSE_MS)
994                 pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000);
995         if (op & OPT_FIRST_TTL)
996                 first_ttl = xatou_range(first_ttl_str, 1, 255);
997
998 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
999         if (source_route_list) {
1000                 llist_t *l_sr;
1001
1002                 l_sr = source_route_list;
1003                 while (l_sr) {
1004                         if (lsrr >= NGATEWAYS)
1005                                 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
1006                         getaddr(gwlist + lsrr, l_sr->data);
1007                         ++lsrr;
1008                         l_sr = l_sr->link;
1009                         free(source_route_list);
1010                         source_route_list = l_sr;
1011                 }
1012                 optlen = (lsrr + 1) * sizeof(gwlist[0]);
1013         }
1014 #endif
1015
1016         if (first_ttl > max_ttl) {
1017                 bb_error_msg_and_die(
1018                     "first ttl (%d) may not be greater than max ttl (%d)",
1019                     first_ttl, max_ttl);
1020         }
1021
1022         minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
1023
1024 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
1025         if (useicmp)
1026                 minpacket += 8;                 /* XXX magic number */
1027         else
1028 #endif
1029                 minpacket += sizeof(*outudp);
1030         packlen = minpacket;                    /* minimum sized packet */
1031
1032         /* Process destination and optional packet size */
1033         switch (argc - optind) {
1034
1035         case 2:
1036                 packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket);
1037                 /* Fall through */
1038
1039         case 1:
1040                 hostname = argv[optind];
1041                 hi = gethostinfo(hostname);
1042                 setsin(to, hi->addrs[0]);
1043                 if (hi->n > 1)
1044                         bb_error_msg("warning: %s has multiple addresses; using %s",
1045                                 hostname, inet_ntoa(to->sin_addr));
1046                 hostname = hi->name;
1047                 hi->name = NULL;
1048                 freehostinfo(hi);
1049                 break;
1050
1051         default:
1052                 bb_show_usage();
1053         }
1054
1055         /* Ensure the socket fds won't be 0, 1 or 2 */
1056         bb_sanitize_stdio();
1057
1058         rcvsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
1059
1060 #if TRACEROUTE_SO_DEBUG
1061         if (op & OPT_DEBUG)
1062                 setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
1063                                 &const_int_1, sizeof(const_int_1));
1064 #endif
1065         if (op & OPT_BYPASS_ROUTE)
1066                 setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
1067                                 &const_int_1, sizeof(const_int_1));
1068
1069         sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
1070
1071 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
1072 #if defined(IP_OPTIONS)
1073         if (lsrr > 0) {
1074                 unsigned char optlist[MAX_IPOPTLEN];
1075
1076                 /* final hop */
1077                 gwlist[lsrr] = to->sin_addr.s_addr;
1078                 ++lsrr;
1079
1080                 /* force 4 byte alignment */
1081                 optlist[0] = IPOPT_NOP;
1082                 /* loose source route option */
1083                 optlist[1] = IPOPT_LSRR;
1084                 i = lsrr * sizeof(gwlist[0]);
1085                 optlist[2] = i + 3;
1086                 /* Pointer to LSRR addresses */
1087                 optlist[3] = IPOPT_MINOFF;
1088                 memcpy(optlist + 4, gwlist, i);
1089
1090                 if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
1091                     (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
1092                         bb_perror_msg_and_die("IP_OPTIONS");
1093                 }
1094         }
1095 #endif /* IP_OPTIONS */
1096 #endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
1097
1098 #ifdef SO_SNDBUF
1099         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
1100                 bb_perror_msg_and_die("SO_SNDBUF");
1101         }
1102 #endif
1103 #ifdef IP_HDRINCL
1104         if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0
1105          && errno != ENOPROTOOPT
1106         ) {
1107                 bb_perror_msg_and_die("IP_HDRINCL");
1108         }
1109 #else
1110 #ifdef IP_TOS
1111         if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
1112                 bb_perror_msg_and_die("setsockopt tos %d", tos);
1113         }
1114 #endif
1115 #endif
1116 #if TRACEROUTE_SO_DEBUG
1117         if (op & OPT_DEBUG)
1118                 setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
1119                                 &const_int_1, sizeof(const_int_1));
1120 #endif
1121         if (op & OPT_BYPASS_ROUTE)
1122                 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
1123                                 &const_int_1, sizeof(const_int_1));
1124
1125         /* Revert to non-privileged user after opening sockets */
1126         xsetgid(getgid());
1127         xsetuid(getuid());
1128
1129         outip = xzalloc(packlen);
1130
1131         outip->ip_v = IPVERSION;
1132         if (tos_str)
1133                 outip->ip_tos = tos;
1134         outip->ip_len = htons(packlen);
1135         outip->ip_off = htons(off);
1136         outp = (unsigned char *)(outip + 1);
1137         outip->ip_dst = to->sin_addr;
1138
1139         outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
1140         ident = (getpid() & 0xffff) | 0x8000;
1141 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
1142         if (useicmp) {
1143                 outip->ip_p = IPPROTO_ICMP;
1144                 outicmp = (struct icmp *)outp;
1145                 outicmp->icmp_type = ICMP_ECHO;
1146                 outicmp->icmp_id = htons(ident);
1147                 outdata = (outdata_t *)(outp + 8); /* XXX magic number */
1148         } else
1149 #endif
1150         {
1151                 outip->ip_p = IPPROTO_UDP;
1152                 outudp = (struct udphdr *)outp;
1153                 outudp->source = htons(ident);
1154                 outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen)));
1155                 outdata = (outdata_t *)(outudp + 1);
1156         }
1157
1158         /* Get the interface address list */
1159         n = ifaddrlist(&al);
1160
1161         /* Look for a specific device */
1162         if (op & OPT_DEVICE) {
1163                 for (i = n; i > 0; --i, ++al)
1164                         if (strcmp(device, al->device) == 0)
1165                                 goto found_dev;
1166                 bb_error_msg_and_die("can't find interface %s", device);
1167         }
1168  found_dev:
1169
1170         /* Determine our source address */
1171         if (!(op & OPT_SOURCE)) {
1172                 /*
1173                  * If a device was specified, use the interface address.
1174                  * Otherwise, try to determine our source address.
1175                  */
1176                 if (op & OPT_DEVICE)
1177                         setsin(from, al->addr);
1178                 findsaddr(to, from);
1179         } else {
1180                 hi = gethostinfo(source);
1181                 source = hi->name;
1182                 hi->name = NULL;
1183                 /*
1184                  * If the device was specified make sure it
1185                  * corresponds to the source address specified.
1186                  * Otherwise, use the first address (and warn if
1187                  * there are more than one).
1188                  */
1189                 if (op & OPT_DEVICE) {
1190                         for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
1191                                 if (*ap == al->addr)
1192                                         goto found_dev2;
1193                         bb_error_msg_and_die("%s is not on interface %s",
1194                                         source, device);
1195  found_dev2:
1196                         setsin(from, *ap);
1197                 } else {
1198                         setsin(from, hi->addrs[0]);
1199                         if (hi->n > 1)
1200                                 bb_error_msg(
1201                         "warning: %s has multiple addresses; using %s",
1202                                     source, inet_ntoa(from->sin_addr));
1203                 }
1204                 freehostinfo(hi);
1205         }
1206
1207         outip->ip_src = from->sin_addr;
1208 #ifndef IP_HDRINCL
1209         xbind(sndsock, (struct sockaddr *)from, sizeof(*from));
1210 #endif
1211
1212         printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
1213         if (op & OPT_SOURCE)
1214                 printf(" from %s", source);
1215         printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
1216         fflush(stdout);
1217
1218         for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
1219                 uint32_t lastaddr = 0;
1220                 int gotlastaddr = 0;
1221                 int got_there = 0;
1222                 int unreachable = 0;
1223                 int sentfirst = 0;
1224
1225                 printf("%2d ", ttl);
1226                 for (probe = 0; probe < nprobes; ++probe) {
1227                         int cc;
1228                         unsigned t1;
1229                         unsigned t2;
1230                         struct ip *ip;
1231
1232                         if (sentfirst && pausemsecs > 0)
1233                                 usleep(pausemsecs * 1000);
1234                         t1 = monotonic_us();
1235                         send_probe(++seq, ttl);
1236                         ++sentfirst;
1237                         while ((cc = wait_for_reply(rcvsock, from)) != 0) {
1238                                 t2 = monotonic_us();
1239                                 i = packet_ok(packet, cc, from, seq);
1240                                 /* Skip short packet */
1241                                 if (i == 0)
1242                                         continue;
1243                                 if (!gotlastaddr ||
1244                                     from->sin_addr.s_addr != lastaddr) {
1245                                         print(packet, cc, from);
1246                                         lastaddr = from->sin_addr.s_addr;
1247                                         ++gotlastaddr;
1248                                 }
1249                                 print_delta_ms(t1, t2);
1250                                 ip = (struct ip *)packet;
1251                                 if (op & OPT_TTL_FLAG)
1252                                         printf(" (%d)", ip->ip_ttl);
1253                                 if (i == -2) {
1254                                         if (ip->ip_ttl <= 1)
1255                                                 printf(" !");
1256                                         ++got_there;
1257                                         break;
1258                                 }
1259                                 /* time exceeded in transit */
1260                                 if (i == -1)
1261                                         break;
1262                                 code = i - 1;
1263                                 switch (code) {
1264
1265                                 case ICMP_UNREACH_PORT:
1266                                         if (ip->ip_ttl <= 1)
1267                                                 printf(" !");
1268                                         ++got_there;
1269                                         break;
1270
1271                                 case ICMP_UNREACH_NET:
1272                                         ++unreachable;
1273                                         printf(" !N");
1274                                         break;
1275
1276                                 case ICMP_UNREACH_HOST:
1277                                         ++unreachable;
1278                                         printf(" !H");
1279                                         break;
1280
1281                                 case ICMP_UNREACH_PROTOCOL:
1282                                         ++got_there;
1283                                         printf(" !P");
1284                                         break;
1285
1286                                 case ICMP_UNREACH_NEEDFRAG:
1287                                         ++unreachable;
1288                                         printf(" !F-%d", pmtu);
1289                                         break;
1290
1291                                 case ICMP_UNREACH_SRCFAIL:
1292                                         ++unreachable;
1293                                         printf(" !S");
1294                                         break;
1295
1296                                 case ICMP_UNREACH_FILTER_PROHIB:
1297                                 case ICMP_UNREACH_NET_PROHIB:   /* misuse */
1298                                         ++unreachable;
1299                                         printf(" !A");
1300                                         break;
1301
1302                                 case ICMP_UNREACH_HOST_PROHIB:
1303                                         ++unreachable;
1304                                         printf(" !C");
1305                                         break;
1306
1307                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1308                                         ++unreachable;
1309                                         printf(" !V");
1310                                         break;
1311
1312                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1313                                         ++unreachable;
1314                                         printf(" !C");
1315                                         break;
1316
1317                                 case ICMP_UNREACH_NET_UNKNOWN:
1318                                 case ICMP_UNREACH_HOST_UNKNOWN:
1319                                         ++unreachable;
1320                                         printf(" !U");
1321                                         break;
1322
1323                                 case ICMP_UNREACH_ISOLATED:
1324                                         ++unreachable;
1325                                         printf(" !I");
1326                                         break;
1327
1328                                 case ICMP_UNREACH_TOSNET:
1329                                 case ICMP_UNREACH_TOSHOST:
1330                                         ++unreachable;
1331                                         printf(" !T");
1332                                         break;
1333
1334                                 default:
1335                                         ++unreachable;
1336                                         printf(" !<%d>", code);
1337                                         break;
1338                                 }
1339                                 break;
1340                         }
1341                         if (cc == 0)
1342                                 printf(" *");
1343                         (void)fflush(stdout);
1344                 }
1345                 bb_putchar('\n');
1346                 if (got_there ||
1347                     (unreachable > 0 && unreachable >= nprobes - 1))
1348                         break;
1349         }
1350         return 0;
1351 }