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