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