Initial public busybox upstream commit
[busybox4maemo] / 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         SET_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 #if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
733 #define packet_ok(buf, cc, from, seq) \
734         packet_ok(buf, cc, seq)
735 #endif
736 static int
737 packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
738 {
739         struct icmp *icp;
740         unsigned char type, code;
741         int hlen;
742         struct ip *ip;
743
744         ip = (struct ip *) buf;
745         hlen = ip->ip_hl << 2;
746         if (cc < hlen + ICMP_MINLEN) {
747 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
748                 if (verbose)
749                         printf("packet too short (%d bytes) from %s\n", cc,
750                                 inet_ntoa(from->sin_addr));
751 #endif
752                 return 0;
753         }
754         cc -= hlen;
755         icp = (struct icmp *)(buf + hlen);
756         type = icp->icmp_type;
757         code = icp->icmp_code;
758         /* Path MTU Discovery (RFC1191) */
759         if (code != ICMP_UNREACH_NEEDFRAG)
760                 pmtu = 0;
761         else {
762                 pmtu = ntohs(icp->icmp_nextmtu);
763         }
764         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
765             type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
766                 struct ip *hip;
767                 struct udphdr *up;
768
769                 hip = &icp->icmp_ip;
770                 hlen = hip->ip_hl << 2;
771 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
772                 if (useicmp) {
773                         struct icmp *hicmp;
774
775                         /* XXX */
776                         if (type == ICMP_ECHOREPLY &&
777                             icp->icmp_id == htons(ident) &&
778                             icp->icmp_seq == htons(seq))
779                                 return -2;
780
781                         hicmp = (struct icmp *)((unsigned char *)hip + hlen);
782                         /* XXX 8 is a magic number */
783                         if (hlen + 8 <= cc &&
784                             hip->ip_p == IPPROTO_ICMP &&
785                             hicmp->icmp_id == htons(ident) &&
786                             hicmp->icmp_seq == htons(seq))
787                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
788                 } else
789 #endif
790                 {
791                         up = (struct udphdr *)((unsigned char *)hip + hlen);
792                         /* XXX 8 is a magic number */
793                         if (hlen + 12 <= cc &&
794                             hip->ip_p == IPPROTO_UDP &&
795                             up->source == htons(ident) &&
796                             up->dest == htons(port + seq))
797                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
798                 }
799         }
800 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
801         if (verbose) {
802                 int i;
803                 uint32_t *lp = (uint32_t *)&icp->icmp_ip;
804
805                 printf("\n%d bytes from %s to "
806                        "%s: icmp type %d (%s) code %d\n",
807                     cc, inet_ntoa(from->sin_addr),
808                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
809                 for (i = 4; i < cc; i += sizeof(*lp))
810                         printf("%2d: x%8.8x\n", i, *lp++);
811         }
812 #endif
813         return 0;
814 }
815
816
817 /*
818  * Construct an Internet address representation.
819  * If the nflag has been supplied, give
820  * numeric value, otherwise try for symbolic name.
821  */
822 static inline void
823 print_inetname(struct sockaddr_in *from)
824 {
825         const char *ina;
826
827         ina = inet_ntoa(from->sin_addr);
828         if (nflag)
829                 printf(" %s", ina);
830         else {
831                 char *n = NULL;
832                 if (from->sin_addr.s_addr != INADDR_ANY)
833                         n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
834                 printf(" %s (%s)", (n ? n : ina), ina);
835                 free(n);
836         }
837 }
838
839 static inline void
840 print(unsigned char *buf, int cc, struct sockaddr_in *from)
841 {
842         struct ip *ip;
843         int hlen;
844
845         ip = (struct ip *) buf;
846         hlen = ip->ip_hl << 2;
847         cc -= hlen;
848
849         print_inetname(from);
850 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
851         if (verbose)
852                 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
853 #endif
854 }
855
856
857 static struct hostinfo *
858 gethostinfo(const char *host)
859 {
860         int n;
861         struct hostent *hp;
862         struct hostinfo *hi;
863         char **p;
864         uint32_t addr, *ap;
865
866         hi = xzalloc(sizeof(*hi));
867         addr = inet_addr(host);
868         if (addr != 0xffffffff) {
869                 hi->name = xstrdup(host);
870                 hi->n = 1;
871                 hi->addrs = xzalloc(sizeof(hi->addrs[0]));
872                 hi->addrs[0] = addr;
873                 return hi;
874         }
875
876         hp = xgethostbyname(host);
877         if (hp->h_addrtype != AF_INET || hp->h_length != 4)
878                 bb_perror_msg_and_die("bad host %s", host);
879         hi->name = xstrdup(hp->h_name);
880         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
881                 continue;
882         hi->n = n;
883         hi->addrs = xzalloc(n * sizeof(hi->addrs[0]));
884         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
885                 memcpy(ap, *p, sizeof(*ap));
886         return hi;
887 }
888
889 static void
890 freehostinfo(struct hostinfo *hi)
891 {
892         free(hi->name);
893         free(hi->addrs);
894         free(hi);
895 }
896
897 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
898 static void
899 getaddr(uint32_t *ap, const char *host)
900 {
901         struct hostinfo *hi;
902
903         hi = gethostinfo(host);
904         *ap = hi->addrs[0];
905         freehostinfo(hi);
906 }
907 #endif
908
909 static void
910 print_delta_ms(unsigned t1p, unsigned t2p)
911 {
912         unsigned tt = t2p - t1p;
913         printf("  %u.%03u ms", tt/1000, tt%1000);
914 }
915
916 int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
917 int traceroute_main(int argc, char **argv)
918 {
919         int code, n;
920         unsigned char *outp;
921         uint32_t *ap;
922         struct sockaddr_in *from;
923         struct sockaddr_in *to;
924         struct hostinfo *hi;
925         int ttl, probe, i;
926         int seq = 0;
927         int tos = 0;
928         char *tos_str;
929         char *source;
930         unsigned op;
931 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
932         int lsrr = 0;
933 #endif
934         uint16_t off = 0;
935         struct IFADDRLIST *al;
936         char *device;
937         int max_ttl = 30;
938         char *max_ttl_str;
939         char *port_str;
940         int nprobes = 3;
941         char *nprobes_str;
942         char *waittime_str;
943         unsigned pausemsecs = 0;
944         char *pausemsecs_str;
945         int first_ttl = 1;
946         char *first_ttl_str;
947 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
948         llist_t *source_route_list = NULL;
949 #endif
950
951         INIT_G();
952         from = (struct sockaddr_in *)&wherefrom;
953         to = (struct sockaddr_in *)&whereto;
954
955         //opterr = 0;
956 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
957         opt_complementary = "x-x:g::";
958 #else
959         opt_complementary = "x-x";
960 #endif
961
962         op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
963 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
964                                         "g:"
965 #endif
966                 , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
967                 , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
968 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
969                 , &source_route_list
970 #endif
971         );
972
973         if (op & OPT_DONT_FRAGMNT)
974                 off = IP_DF;
975         if (op & OPT_IP_CHKSUM) {
976                 doipcksum = 0;
977                 bb_error_msg("warning: ip checksums disabled");
978         }
979         if (op & OPT_TOS)
980                 tos = xatou_range(tos_str, 0, 255);
981         if (op & OPT_MAX_TTL)
982                 max_ttl = xatou_range(max_ttl_str, 1, 255);
983         if (op & OPT_PORT)
984                 port = xatou16(port_str);
985         if (op & OPT_NPROBES)
986                 nprobes = xatou_range(nprobes_str, 1, INT_MAX);
987         if (op & OPT_SOURCE) {
988                 /*
989                  * set the ip source address of the outbound
990                  * probe (e.g., on a multi-homed host).
991                  */
992                 if (getuid())
993                         bb_error_msg_and_die("-s %s: permission denied", source);
994         }
995         if (op & OPT_WAITTIME)
996                 waittime = xatou_range(waittime_str, 2, 24 * 60 * 60);
997         if (op & OPT_PAUSE_MS)
998                 pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000);
999         if (op & OPT_FIRST_TTL)
1000                 first_ttl = xatou_range(first_ttl_str, 1, 255);
1001
1002 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
1003         if (source_route_list) {
1004                 llist_t *l_sr;
1005
1006                 l_sr = source_route_list;
1007                 while (l_sr) {
1008                         if (lsrr >= NGATEWAYS)
1009                                 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
1010                         getaddr(gwlist + lsrr, l_sr->data);
1011                         ++lsrr;
1012                         l_sr = l_sr->link;
1013                         free(source_route_list);
1014                         source_route_list = l_sr;
1015                 }
1016                 optlen = (lsrr + 1) * sizeof(gwlist[0]);
1017         }
1018 #endif
1019
1020         if (first_ttl > max_ttl) {
1021                 bb_error_msg_and_die(
1022                     "first ttl (%d) may not be greater than max ttl (%d)",
1023                     first_ttl, max_ttl);
1024         }
1025
1026         minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
1027
1028 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
1029         if (useicmp)
1030                 minpacket += 8;                 /* XXX magic number */
1031         else
1032 #endif
1033                 minpacket += sizeof(*outudp);
1034         packlen = minpacket;                    /* minimum sized packet */
1035
1036         /* Process destination and optional packet size */
1037         switch (argc - optind) {
1038
1039         case 2:
1040                 packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket);
1041                 /* Fall through */
1042
1043         case 1:
1044                 hostname = argv[optind];
1045                 hi = gethostinfo(hostname);
1046                 setsin(to, hi->addrs[0]);
1047                 if (hi->n > 1)
1048                         bb_error_msg("warning: %s has multiple addresses; using %s",
1049                                 hostname, inet_ntoa(to->sin_addr));
1050                 hostname = hi->name;
1051                 hi->name = NULL;
1052                 freehostinfo(hi);
1053                 break;
1054
1055         default:
1056                 bb_show_usage();
1057         }
1058
1059         /* Ensure the socket fds won't be 0, 1 or 2 */
1060         bb_sanitize_stdio();
1061
1062         rcvsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
1063
1064 #if TRACEROUTE_SO_DEBUG
1065         if (op & OPT_DEBUG)
1066                 setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
1067                                 &const_int_1, sizeof(const_int_1));
1068 #endif
1069         if (op & OPT_BYPASS_ROUTE)
1070                 setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
1071                                 &const_int_1, sizeof(const_int_1));
1072
1073         sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
1074
1075 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
1076 #if defined(IP_OPTIONS)
1077         if (lsrr > 0) {
1078                 unsigned char optlist[MAX_IPOPTLEN];
1079
1080                 /* final hop */
1081                 gwlist[lsrr] = to->sin_addr.s_addr;
1082                 ++lsrr;
1083
1084                 /* force 4 byte alignment */
1085                 optlist[0] = IPOPT_NOP;
1086                 /* loose source route option */
1087                 optlist[1] = IPOPT_LSRR;
1088                 i = lsrr * sizeof(gwlist[0]);
1089                 optlist[2] = i + 3;
1090                 /* Pointer to LSRR addresses */
1091                 optlist[3] = IPOPT_MINOFF;
1092                 memcpy(optlist + 4, gwlist, i);
1093
1094                 if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
1095                     (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
1096                         bb_perror_msg_and_die("IP_OPTIONS");
1097                 }
1098         }
1099 #endif /* IP_OPTIONS */
1100 #endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
1101
1102 #ifdef SO_SNDBUF
1103         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
1104                 bb_perror_msg_and_die("SO_SNDBUF");
1105         }
1106 #endif
1107 #ifdef IP_HDRINCL
1108         if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0
1109          && errno != ENOPROTOOPT
1110         ) {
1111                 bb_perror_msg_and_die("IP_HDRINCL");
1112         }
1113 #else
1114 #ifdef IP_TOS
1115         if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
1116                 bb_perror_msg_and_die("setsockopt tos %d", tos);
1117         }
1118 #endif
1119 #endif
1120 #if TRACEROUTE_SO_DEBUG
1121         if (op & OPT_DEBUG)
1122                 setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
1123                                 &const_int_1, sizeof(const_int_1));
1124 #endif
1125         if (op & OPT_BYPASS_ROUTE)
1126                 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
1127                                 &const_int_1, sizeof(const_int_1));
1128
1129         /* Revert to non-privileged user after opening sockets */
1130         xsetgid(getgid());
1131         xsetuid(getuid());
1132
1133         outip = xzalloc(packlen);
1134
1135         outip->ip_v = IPVERSION;
1136         if (tos_str)
1137                 outip->ip_tos = tos;
1138         outip->ip_len = htons(packlen);
1139         outip->ip_off = htons(off);
1140         outp = (unsigned char *)(outip + 1);
1141         outip->ip_dst = to->sin_addr;
1142
1143         outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
1144         ident = (getpid() & 0xffff) | 0x8000;
1145 #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
1146         if (useicmp) {
1147                 outip->ip_p = IPPROTO_ICMP;
1148                 outicmp = (struct icmp *)outp;
1149                 outicmp->icmp_type = ICMP_ECHO;
1150                 outicmp->icmp_id = htons(ident);
1151                 outdata = (outdata_t *)(outp + 8); /* XXX magic number */
1152         } else
1153 #endif
1154         {
1155                 outip->ip_p = IPPROTO_UDP;
1156                 outudp = (struct udphdr *)outp;
1157                 outudp->source = htons(ident);
1158                 outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen)));
1159                 outdata = (outdata_t *)(outudp + 1);
1160         }
1161
1162         /* Get the interface address list */
1163         n = ifaddrlist(&al);
1164
1165         /* Look for a specific device */
1166         if (op & OPT_DEVICE) {
1167                 for (i = n; i > 0; --i, ++al)
1168                         if (strcmp(device, al->device) == 0)
1169                                 goto found_dev;
1170                 bb_error_msg_and_die("can't find interface %s", device);
1171         }
1172  found_dev:
1173
1174         /* Determine our source address */
1175         if (!(op & OPT_SOURCE)) {
1176                 /*
1177                  * If a device was specified, use the interface address.
1178                  * Otherwise, try to determine our source address.
1179                  */
1180                 if (op & OPT_DEVICE)
1181                         setsin(from, al->addr);
1182                 findsaddr(to, from);
1183         } else {
1184                 hi = gethostinfo(source);
1185                 source = hi->name;
1186                 hi->name = NULL;
1187                 /*
1188                  * If the device was specified make sure it
1189                  * corresponds to the source address specified.
1190                  * Otherwise, use the first address (and warn if
1191                  * there are more than one).
1192                  */
1193                 if (op & OPT_DEVICE) {
1194                         for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
1195                                 if (*ap == al->addr)
1196                                         goto found_dev2;
1197                         bb_error_msg_and_die("%s is not on interface %s",
1198                                         source, device);
1199  found_dev2:
1200                         setsin(from, *ap);
1201                 } else {
1202                         setsin(from, hi->addrs[0]);
1203                         if (hi->n > 1)
1204                                 bb_error_msg(
1205                         "warning: %s has multiple addresses; using %s",
1206                                     source, inet_ntoa(from->sin_addr));
1207                 }
1208                 freehostinfo(hi);
1209         }
1210
1211         outip->ip_src = from->sin_addr;
1212 #ifndef IP_HDRINCL
1213         xbind(sndsock, (struct sockaddr *)from, sizeof(*from));
1214 #endif
1215
1216         printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
1217         if (op & OPT_SOURCE)
1218                 printf(" from %s", source);
1219         printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
1220         fflush(stdout);
1221
1222         for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
1223                 uint32_t lastaddr = 0;
1224                 int gotlastaddr = 0;
1225                 int got_there = 0;
1226                 int unreachable = 0;
1227                 int sentfirst = 0;
1228
1229                 printf("%2d ", ttl);
1230                 for (probe = 0; probe < nprobes; ++probe) {
1231                         int cc;
1232                         unsigned t1;
1233                         unsigned t2;
1234                         struct ip *ip;
1235
1236                         if (sentfirst && pausemsecs > 0)
1237                                 usleep(pausemsecs * 1000);
1238                         t1 = monotonic_us();
1239                         send_probe(++seq, ttl);
1240                         ++sentfirst;
1241                         while ((cc = wait_for_reply(rcvsock, from)) != 0) {
1242                                 t2 = monotonic_us();
1243                                 i = packet_ok(packet, cc, from, seq);
1244                                 /* Skip short packet */
1245                                 if (i == 0)
1246                                         continue;
1247                                 if (!gotlastaddr ||
1248                                     from->sin_addr.s_addr != lastaddr) {
1249                                         print(packet, cc, from);
1250                                         lastaddr = from->sin_addr.s_addr;
1251                                         ++gotlastaddr;
1252                                 }
1253                                 print_delta_ms(t1, t2);
1254                                 ip = (struct ip *)packet;
1255                                 if (op & OPT_TTL_FLAG)
1256                                         printf(" (%d)", ip->ip_ttl);
1257                                 if (i == -2) {
1258                                         if (ip->ip_ttl <= 1)
1259                                                 printf(" !");
1260                                         ++got_there;
1261                                         break;
1262                                 }
1263                                 /* time exceeded in transit */
1264                                 if (i == -1)
1265                                         break;
1266                                 code = i - 1;
1267                                 switch (code) {
1268
1269                                 case ICMP_UNREACH_PORT:
1270                                         if (ip->ip_ttl <= 1)
1271                                                 printf(" !");
1272                                         ++got_there;
1273                                         break;
1274
1275                                 case ICMP_UNREACH_NET:
1276                                         ++unreachable;
1277                                         printf(" !N");
1278                                         break;
1279
1280                                 case ICMP_UNREACH_HOST:
1281                                         ++unreachable;
1282                                         printf(" !H");
1283                                         break;
1284
1285                                 case ICMP_UNREACH_PROTOCOL:
1286                                         ++got_there;
1287                                         printf(" !P");
1288                                         break;
1289
1290                                 case ICMP_UNREACH_NEEDFRAG:
1291                                         ++unreachable;
1292                                         printf(" !F-%d", pmtu);
1293                                         break;
1294
1295                                 case ICMP_UNREACH_SRCFAIL:
1296                                         ++unreachable;
1297                                         printf(" !S");
1298                                         break;
1299
1300                                 case ICMP_UNREACH_FILTER_PROHIB:
1301                                 case ICMP_UNREACH_NET_PROHIB:   /* misuse */
1302                                         ++unreachable;
1303                                         printf(" !A");
1304                                         break;
1305
1306                                 case ICMP_UNREACH_HOST_PROHIB:
1307                                         ++unreachable;
1308                                         printf(" !C");
1309                                         break;
1310
1311                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1312                                         ++unreachable;
1313                                         printf(" !V");
1314                                         break;
1315
1316                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1317                                         ++unreachable;
1318                                         printf(" !C");
1319                                         break;
1320
1321                                 case ICMP_UNREACH_NET_UNKNOWN:
1322                                 case ICMP_UNREACH_HOST_UNKNOWN:
1323                                         ++unreachable;
1324                                         printf(" !U");
1325                                         break;
1326
1327                                 case ICMP_UNREACH_ISOLATED:
1328                                         ++unreachable;
1329                                         printf(" !I");
1330                                         break;
1331
1332                                 case ICMP_UNREACH_TOSNET:
1333                                 case ICMP_UNREACH_TOSHOST:
1334                                         ++unreachable;
1335                                         printf(" !T");
1336                                         break;
1337
1338                                 default:
1339                                         ++unreachable;
1340                                         printf(" !<%d>", code);
1341                                         break;
1342                                 }
1343                                 break;
1344                         }
1345                         if (cc == 0)
1346                                 printf(" *");
1347                         (void)fflush(stdout);
1348                 }
1349                 bb_putchar('\n');
1350                 if (got_there ||
1351                     (unreachable > 0 && unreachable >= nprobes - 1))
1352                         break;
1353         }
1354         return 0;
1355 }