0abd9047d55e45088999c582b2126317e4f73e6e
[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 <memory.h>
209 #include <stdio.h>
210 #include <stdlib.h>
211 #include <string.h>
212 #include <unistd.h>
213 #include <fcntl.h>
214 #include <malloc.h>
215 #include <netdb.h>
216 #include <endian.h>
217 #include <getopt.h>
218
219 #include <sys/param.h>
220 #include <sys/file.h>
221 #include <sys/ioctl.h>
222 #include <sys/socket.h>
223 #include <sys/time.h>                           /* concession to AIX */
224 #include <sys/select.h>
225 #include "inet_common.h"
226
227 #include <net/if.h>
228 #include <netinet/in.h>
229 #include <arpa/inet.h>
230 #include <netinet/udp.h>
231 #include <netinet/ip.h>
232 #include <netinet/ip_icmp.h>
233
234 #include "busybox.h"
235
236
237 /*
238  * Definitions for internet protocol version 4.
239  * Per RFC 791, September 1981.
240  */
241 #define IPVERSION       4
242
243 /*
244  * Overlay for ip header used by other protocols (tcp, udp).
245  */
246 struct ipovly {
247         unsigned char  ih_x1[9];               /* (unused) */
248         unsigned char  ih_pr;                  /* protocol */
249         short   ih_len;                 /* protocol length */
250         struct  in_addr ih_src;         /* source internet address */
251         struct  in_addr ih_dst;         /* destination internet address */
252 };
253
254 /*
255  * UDP kernel structures and variables.
256  */
257 struct  udpiphdr {
258         struct  ipovly ui_i;            /* overlaid ip structure */
259         struct  udphdr ui_u;            /* udp header */
260 };
261 #define ui_next         ui_i.ih_next
262 #define ui_prev         ui_i.ih_prev
263 #define ui_x1           ui_i.ih_x1
264 #define ui_pr           ui_i.ih_pr
265 #define ui_len          ui_i.ih_len
266 #define ui_src          ui_i.ih_src
267 #define ui_dst          ui_i.ih_dst
268 #define ui_sport        ui_u.uh_sport
269 #define ui_dport        ui_u.uh_dport
270 #define ui_ulen         ui_u.uh_ulen
271 #define ui_sum          ui_u.uh_sum
272
273
274 /* Host name and address list */
275 struct hostinfo {
276         char *name;
277         int n;
278         u_int32_t *addrs;
279 };
280
281 /* Data section of the probe packet */
282 struct outdata {
283         unsigned char seq;             /* sequence number of this packet */
284         unsigned char ttl;             /* ttl packet left with */
285         struct timeval tv ATTRIBUTE_PACKED; /* time packet left */
286 };
287
288 struct IFADDRLIST {
289         u_int32_t addr;
290         char device[sizeof(struct ifreq)];
291 };
292
293
294 static const char route[] = "/proc/net/route";
295
296 /* last inbound (icmp) packet */
297 static unsigned char  packet[512] ATTRIBUTE_ALIGNED(32);
298
299 static struct ip *outip;               /* last output (udp) packet */
300 static struct udphdr *outudp;          /* last output (udp) packet */
301 static struct outdata *outdata;        /* last output (udp) packet */
302
303 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
304 static struct icmp *outicmp;           /* last output (icmp) packet */
305 #endif
306
307 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
308 /* Maximum number of gateways (include room for one noop) */
309 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
310 /* loose source route gateway list (including room for final destination) */
311 static u_int32_t gwlist[NGATEWAYS + 1];
312 #endif
313
314 static int s;                          /* receive (icmp) socket file descriptor */
315 static int sndsock;                    /* send (udp/icmp) socket file descriptor */
316
317 static struct sockaddr_storage whereto;        /* Who to try to reach */
318 static struct sockaddr_storage wherefrom;      /* Who we are */
319 static int packlen;                    /* total length of packet */
320 static int minpacket;                  /* min ip packet size */
321 static int maxpacket = 32 * 1024;      /* max ip packet size */
322 static int pmtu;                       /* Path MTU Discovery (RFC1191) */
323
324 static char *hostname;
325
326 static u_short ident;
327 static u_short port = 32768 + 666;     /* start udp dest port # for probe packets */
328
329 static int waittime = 5;               /* time to wait for response (in seconds) */
330 static int nflag;                      /* print addresses numerically */
331 static int doipcksum = 1;              /* calculate ip checksums by default */
332
333 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
334 static int optlen;                     /* length of ip options */
335 #else
336 #define optlen 0
337 #endif
338
339 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
340 static int useicmp;                    /* use icmp echo instead of udp packets */
341 #endif
342 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
343 static int verbose;
344 #endif
345
346 /*
347  * Return the interface list
348  */
349 static int
350 ifaddrlist(struct IFADDRLIST **ipaddrp)
351 {
352         int fd, nipaddr;
353 #ifdef HAVE_SOCKADDR_SA_LEN
354         int n;
355 #endif
356         struct ifreq *ifrp, *ifend, *ifnext;
357         struct sockaddr_in *addr_sin;
358         struct IFADDRLIST *al;
359         struct ifconf ifc;
360         struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr;
361         struct IFADDRLIST *st_ifaddrlist;
362
363         fd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
364
365         ifc.ifc_len = sizeof(ibuf);
366         ifc.ifc_buf = (caddr_t)ibuf;
367
368         if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
369             ifc.ifc_len < sizeof(struct ifreq)) {
370                 if (errno == EINVAL)
371                         bb_error_msg_and_die(
372                             "SIOCGIFCONF: ifreq struct too small (%d bytes)",
373                             (int)sizeof(ibuf));
374                 else
375                         bb_perror_msg_and_die("SIOCGIFCONF");
376         }
377         ifrp = ibuf;
378         ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
379
380         nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
381         st_ifaddrlist = xcalloc(nipaddr, sizeof(struct IFADDRLIST));
382         al = st_ifaddrlist;
383         nipaddr = 0;
384
385         for (; ifrp < ifend; ifrp = ifnext) {
386 #ifdef HAVE_SOCKADDR_SA_LEN
387                 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
388                 if (n < sizeof(*ifrp))
389                         ifnext = ifrp + 1;
390                 else
391                         ifnext = (struct ifreq *)((char *)ifrp + n);
392                 if (ifrp->ifr_addr.sa_family != AF_INET)
393                         continue;
394 #else
395                 ifnext = ifrp + 1;
396 #endif
397                 /*
398                  * Need a template to preserve address info that is
399                  * used below to locate the next entry.  (Otherwise,
400                  * SIOCGIFFLAGS stomps over it because the requests
401                  * are returned in a union.)
402                  */
403                 strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
404                 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
405                         if (errno == ENXIO)
406                                 continue;
407                         bb_perror_msg_and_die("SIOCGIFFLAGS: %.*s",
408                             (int)sizeof(ifr.ifr_name), ifr.ifr_name);
409                 }
410
411                 /* Must be up */
412                 if ((ifr.ifr_flags & IFF_UP) == 0)
413                         continue;
414
415                 safe_strncpy(al->device, ifr.ifr_name, sizeof(ifr.ifr_name) + 1);
416 #ifdef sun
417                 /* Ignore sun virtual interfaces */
418                 if (strchr(al->device, ':') != NULL)
419                         continue;
420 #endif
421                 if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)
422                         bb_perror_msg_and_die("SIOCGIFADDR: %s", al->device);
423
424                 addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
425                 al->addr = addr_sin->sin_addr.s_addr;
426                 ++al;
427                 ++nipaddr;
428         }
429         if(nipaddr == 0)
430             bb_error_msg_and_die ("Can't find any network interfaces");
431         (void)close(fd);
432
433         *ipaddrp = st_ifaddrlist;
434         return nipaddr;
435 }
436
437
438 static void
439 setsin(struct sockaddr_in *addr_sin, u_int32_t addr)
440 {
441         memset(addr_sin, 0, sizeof(*addr_sin));
442 #ifdef HAVE_SOCKADDR_SA_LEN
443         addr_sin->sin_len = sizeof(*addr_sin);
444 #endif
445         addr_sin->sin_family = AF_INET;
446         addr_sin->sin_addr.s_addr = addr;
447 }
448
449
450 /*
451  * Return the source address for the given destination address
452  */
453 static void
454 findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
455 {
456         int i, n;
457         FILE *f;
458         u_int32_t mask;
459         u_int32_t dest, tmask;
460         struct IFADDRLIST *al;
461         char buf[256], tdevice[256], device[256];
462
463         f = bb_xfopen(route, "r");
464
465         /* Find the appropriate interface */
466         n = 0;
467         mask = 0;
468         device[0] = '\0';
469         while (fgets(buf, sizeof(buf), f) != NULL) {
470                 ++n;
471                 if (n == 1 && strncmp(buf, "Iface", 5) == 0)
472                         continue;
473                 if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
474                     tdevice, &dest, &tmask)) != 3)
475                         bb_error_msg_and_die ("junk in buffer");
476                 if ((to->sin_addr.s_addr & tmask) == dest &&
477                     (tmask > mask || mask == 0)) {
478                         mask = tmask;
479                         strcpy(device, tdevice);
480                 }
481         }
482         fclose(f);
483
484         if (device[0] == '\0')
485                 bb_error_msg_and_die ("Can't find interface");
486
487         /* Get the interface address list */
488         n = ifaddrlist(&al);
489
490         /* Find our appropriate source address */
491         for (i = n; i > 0; --i, ++al)
492                 if (strcmp(device, al->device) == 0)
493                         break;
494         if (i <= 0)
495                 bb_error_msg_and_die("Can't find interface %s", device);
496
497         setsin(from, al->addr);
498 }
499
500 /*
501 "Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
502 "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
503 "\t[-w waittime] [-z pausemsecs] host [packetlen]"
504
505 */
506
507 /* String to value with optional min and max. Handles decimal and hex. */
508 static int
509 str2val(const char *str, const char *what, int mi, int ma)
510 {
511         const char *cp;
512         int val;
513         char *ep;
514
515         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
516                 cp = str + 2;
517                 val = (int)strtol(cp, &ep, 16);
518         } else
519                 val = (int)strtol(str, &ep, 10);
520         if (*ep != '\0') {
521                 bb_error_msg_and_die("\"%s\" bad value for %s \n", str, what);
522         }
523         if (val < mi && mi >= 0) {
524                 if (mi == 0)
525                         bb_error_msg_and_die("%s must be >= %d\n", what, mi);
526                 else
527                         bb_error_msg_and_die("%s must be > %d\n", what, mi - 1);
528         }
529         if (val > ma && ma >= 0)
530                 bb_error_msg_and_die("%s must be <= %d\n", what, ma);
531         return val;
532 }
533
534
535 /*
536  * Subtract 2 timeval structs:  out = out - in.
537  * Out is assumed to be >= in.
538  */
539 static inline void
540 tvsub(struct timeval *out, struct timeval *in)
541 {
542
543         if ((out->tv_usec -= in->tv_usec) < 0)   {
544                 --out->tv_sec;
545                 out->tv_usec += 1000000;
546         }
547         out->tv_sec -= in->tv_sec;
548 }
549
550 static int
551 wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp)
552 {
553         fd_set fds;
554         struct timeval now, wait;
555         struct timezone tz;
556         int cc = 0;
557         socklen_t fromlen = sizeof(*fromp);
558
559         FD_ZERO(&fds);
560         FD_SET(sock, &fds);
561
562         wait.tv_sec = tp->tv_sec + waittime;
563         wait.tv_usec = tp->tv_usec;
564         (void)gettimeofday(&now, &tz);
565         tvsub(&wait, &now);
566
567         if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
568                 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
569                             (struct sockaddr *)fromp, &fromlen);
570
571         return cc;
572 }
573
574 /*
575  * Checksum routine for Internet Protocol family headers (C Version)
576  */
577 static u_short
578 in_cksum(u_short *addr, int len)
579 {
580         int nleft = len;
581         u_short *w = addr;
582         u_short answer;
583         int sum = 0;
584
585         /*
586          *  Our algorithm is simple, using a 32 bit accumulator (sum),
587          *  we add sequential 16 bit words to it, and at the end, fold
588          *  back all the carry bits from the top 16 bits into the lower
589          *  16 bits.
590          */
591         while (nleft > 1)  {
592                 sum += *w++;
593                 nleft -= 2;
594         }
595
596         /* mop up an odd byte, if necessary */
597         if (nleft == 1)
598                 sum += *(unsigned char *)w;
599
600         /*
601          * add back carry outs from top 16 bits to low 16 bits
602          */
603         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
604         sum += (sum >> 16);                     /* add carry */
605         answer = ~sum;                          /* truncate to 16 bits */
606         return answer;
607 }
608
609
610 static void
611 send_probe(int seq, int ttl, struct timeval *tp)
612 {
613         int cc;
614         struct udpiphdr *ui, *oui;
615         struct ip tip;
616
617         outip->ip_ttl = ttl;
618         outip->ip_id = htons(ident + seq);
619
620         /*
621          * In most cases, the kernel will recalculate the ip checksum.
622          * But we must do it anyway so that the udp checksum comes out
623          * right.
624          */
625         if (doipcksum) {
626                 outip->ip_sum =
627                     in_cksum((u_short *)outip, sizeof(*outip) + optlen);
628                 if (outip->ip_sum == 0)
629                         outip->ip_sum = 0xffff;
630         }
631
632         /* Payload */
633         outdata->seq = seq;
634         outdata->ttl = ttl;
635         memcpy(&outdata->tv, tp, sizeof(outdata->tv));
636
637 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
638         if (useicmp)
639                 outicmp->icmp_seq = htons(seq);
640         else
641 #endif
642                 outudp->dest = htons(port + seq);
643
644 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
645         if (useicmp) {
646                 /* Always calculate checksum for icmp packets */
647                 outicmp->icmp_cksum = 0;
648                 outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
649                     packlen - (sizeof(*outip) + optlen));
650                 if (outicmp->icmp_cksum == 0)
651                         outicmp->icmp_cksum = 0xffff;
652         } else
653 #endif
654                if (doipcksum) {
655                 /* Checksum (we must save and restore ip header) */
656                 tip = *outip;
657                 ui = (struct udpiphdr *)outip;
658                 oui = (struct udpiphdr *)&tip;
659                 /* Easier to zero and put back things that are ok */
660                 memset((char *)ui, 0, sizeof(ui->ui_i));
661                 ui->ui_src = oui->ui_src;
662                 ui->ui_dst = oui->ui_dst;
663                 ui->ui_pr = oui->ui_pr;
664                 ui->ui_len = outudp->len;
665                 outudp->check = 0;
666                 outudp->check = in_cksum((u_short *)ui, packlen);
667                 if (outudp->check == 0)
668                         outudp->check = 0xffff;
669                 *outip = tip;
670         }
671
672 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
673         /* XXX undocumented debugging hack */
674         if (verbose > 1) {
675                 const u_short *sp;
676                 int nshorts, i;
677
678                 sp = (u_short *)outip;
679                 nshorts = (u_int)packlen / sizeof(u_short);
680                 i = 0;
681                 printf("[ %d bytes", packlen);
682                 while (--nshorts >= 0) {
683                         if ((i++ % 8) == 0)
684                                 printf("\n\t");
685                         printf(" %04x", ntohs(*sp));
686                         sp++;
687                 }
688                 if (packlen & 1) {
689                         if ((i % 8) == 0)
690                                 printf("\n\t");
691                         printf(" %02x", *(unsigned char *)sp);
692                 }
693                 printf("]\n");
694         }
695 #endif
696
697 #if !defined(IP_HDRINCL) && defined(IP_TTL)
698         if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
699             (char *)&ttl, sizeof(ttl)) < 0) {
700                 bb_perror_msg_and_die("setsockopt ttl %d", ttl);
701         }
702 #endif
703
704         cc = sendto(sndsock, (char *)outip,
705             packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto));
706         if (cc < 0 || cc != packlen)  {
707                 if (cc < 0)
708                         bb_perror_msg_and_die("sendto");
709                 printf("%s: wrote %s %d chars, ret=%d\n",
710                     bb_applet_name, hostname, packlen, cc);
711                 (void)fflush(stdout);
712         }
713 }
714
715 static inline double
716 deltaT(struct timeval *t1p, struct timeval *t2p)
717 {
718         double dt;
719
720         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
721              (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
722         return dt;
723 }
724
725 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
726 /*
727  * Convert an ICMP "type" field to a printable string.
728  */
729 static inline const char *
730 pr_type(unsigned char t)
731 {
732         static const char * const ttab[] = {
733         "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
734         "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
735         "Echo",         "Router Advert", "Router Solicit", "Time Exceeded",
736         "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
737         "Info Reply",   "Mask Request", "Mask Reply"
738         };
739
740         if (t > 18)
741                 return "OUT-OF-RANGE";
742
743         return ttab[t];
744 }
745 #endif
746
747 static int
748 packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
749 {
750         struct icmp *icp;
751         unsigned char type, code;
752         int hlen;
753         struct ip *ip;
754
755         ip = (struct ip *) buf;
756         hlen = ip->ip_hl << 2;
757         if (cc < hlen + ICMP_MINLEN) {
758 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
759                 if (verbose)
760                         printf("packet too short (%d bytes) from %s\n", cc,
761                                 inet_ntoa(from->sin_addr));
762 #endif
763                 return 0;
764         }
765         cc -= hlen;
766         icp = (struct icmp *)(buf + hlen);
767         type = icp->icmp_type;
768         code = icp->icmp_code;
769         /* Path MTU Discovery (RFC1191) */
770         if (code != ICMP_UNREACH_NEEDFRAG)
771                 pmtu = 0;
772         else {
773                 pmtu = ntohs(icp->icmp_nextmtu);
774         }
775         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
776             type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
777                 struct ip *hip;
778                 struct udphdr *up;
779
780                 hip = &icp->icmp_ip;
781                 hlen = hip->ip_hl << 2;
782 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
783                 if (useicmp) {
784                         struct icmp *hicmp;
785
786                         /* XXX */
787                         if (type == ICMP_ECHOREPLY &&
788                             icp->icmp_id == htons(ident) &&
789                             icp->icmp_seq == htons(seq))
790                                 return -2;
791
792                         hicmp = (struct icmp *)((unsigned char *)hip + hlen);
793                         /* XXX 8 is a magic number */
794                         if (hlen + 8 <= cc &&
795                             hip->ip_p == IPPROTO_ICMP &&
796                             hicmp->icmp_id == htons(ident) &&
797                             hicmp->icmp_seq == htons(seq))
798                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
799                 } else
800 #endif
801                       {
802                         up = (struct udphdr *)((unsigned char *)hip + hlen);
803                         /* XXX 8 is a magic number */
804                         if (hlen + 12 <= cc &&
805                             hip->ip_p == IPPROTO_UDP &&
806                             up->source == htons(ident) &&
807                             up->dest == htons(port + seq))
808                                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
809                 }
810         }
811 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
812         if (verbose) {
813                 int i;
814                 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
815
816                 printf("\n%d bytes from %s to "
817                        "%s: icmp type %d (%s) code %d\n",
818                     cc, inet_ntoa(from->sin_addr),
819                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
820                 for (i = 4; i < cc ; i += sizeof(*lp))
821                         printf("%2d: x%8.8x\n", i, *lp++);
822         }
823 #endif
824         return 0;
825 }
826
827
828 /*
829  * Construct an Internet address representation.
830  * If the nflag has been supplied, give
831  * numeric value, otherwise try for symbolic name.
832  */
833 static inline void
834 inetname(struct sockaddr_in *from)
835 {
836         const char *n = NULL;
837         const char *ina;
838         char name[257];
839
840         if (!nflag && from->sin_addr.s_addr != INADDR_ANY) {
841                 if(INET_rresolve(name, sizeof(name), from, 0x4000, 0xffffffff) >= 0)
842                         n = name;
843         }
844         ina = inet_ntoa(from->sin_addr);
845         if (nflag)
846                 printf(" %s", ina);
847         else
848                 printf(" %s (%s)", (n ? n : ina), ina);
849 }
850
851 static inline void
852 print(unsigned char *buf, int cc, struct sockaddr_in *from)
853 {
854         struct ip *ip;
855         int hlen;
856
857         ip = (struct ip *) buf;
858         hlen = ip->ip_hl << 2;
859         cc -= hlen;
860
861         inetname(from);
862 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
863         if (verbose)
864                 printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
865 #endif
866 }
867
868
869 static struct hostinfo *
870 gethostinfo(const char *host)
871 {
872         int n;
873         struct hostent *hp;
874         struct hostinfo *hi;
875         char **p;
876         u_int32_t addr, *ap;
877
878         hi = xcalloc(1, sizeof(*hi));
879         addr = inet_addr(host);
880         if ((int32_t)addr != -1) {
881                 hi->name = bb_xstrdup(host);
882                 hi->n = 1;
883                 hi->addrs = xcalloc(1, sizeof(hi->addrs[0]));
884                 hi->addrs[0] = addr;
885                 return hi;
886         }
887
888         hp = xgethostbyname(host);
889         if (hp->h_addrtype != AF_INET || hp->h_length != 4)
890                 bb_perror_msg_and_die("bad host %s", host);
891         hi->name = bb_xstrdup(hp->h_name);
892         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
893                 continue;
894         hi->n = n;
895         hi->addrs = xcalloc(n, sizeof(hi->addrs[0]));
896         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
897                 memcpy(ap, *p, sizeof(*ap));
898         return hi;
899 }
900
901 static void
902 freehostinfo(struct hostinfo *hi)
903 {
904         free(hi->name);
905         hi->name = NULL;
906         free((char *)hi->addrs);
907         free((char *)hi);
908 }
909
910 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
911 static void
912 getaddr(u_int32_t *ap, const char *host)
913 {
914         struct hostinfo *hi;
915
916         hi = gethostinfo(host);
917         *ap = hi->addrs[0];
918         freehostinfo(hi);
919 }
920 #endif
921
922
923 int
924 traceroute_main(int argc, char *argv[])
925 {
926         int code, n;
927         char *cp;
928         unsigned char *outp;
929         u_int32_t *ap;
930         struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
931         struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
932         struct hostinfo *hi;
933         int on = 1;
934         struct protoent *pe;
935         int ttl, probe, i;
936         int seq = 0;
937         int tos = 0;
938         char *tos_str = NULL;
939         char *source = NULL;
940         unsigned long op;
941
942 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
943         int lsrr = 0;
944 #endif
945         u_short off = 0;
946         struct IFADDRLIST *al;
947         int uid = getuid();
948         char *device = NULL;
949         int max_ttl = 30;
950         char *max_ttl_str = NULL;
951         char *port_str = NULL;
952         int nprobes = 3;
953         char *nprobes_str = NULL;
954         char *waittime_str = NULL;
955         u_int pausemsecs = 0;
956         char *pausemsecs_str = NULL;
957         int first_ttl = 1;
958         char *first_ttl_str = NULL;
959 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
960         llist_t *sourse_route_list = NULL;
961 #endif
962
963         opterr = 0;
964 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
965         bb_opt_complementally = "x-x:g::";
966 #else
967         bb_opt_complementally = "x-x";
968 #endif
969
970         op = bb_getopt_ulflags(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
971 #define USAGE_OP_DONT_FRAGMNT (1<<0)    /* F  */
972 #define USAGE_OP_USE_ICMP     (1<<1)    /* I  */
973 #define USAGE_OP_TTL_FLAG     (1<<2)    /* l  */
974 #define USAGE_OP_ADDR_NUM     (1<<3)    /* n  */
975 #define USAGE_OP_BYPASS_ROUTE (1<<4)    /* r  */
976 #define USAGE_OP_DEBUG        (1<<5)    /* d */
977 #define USAGE_OP_VERBOSE      (1<<6)    /* v */
978 #define USAGE_OP_IP_CHKSUM    (1<<7)    /* x */
979
980 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
981                                         "g:"
982 #endif
983         , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str,
984         &source, &waittime_str, &pausemsecs_str, &first_ttl_str
985 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
986         , &sourse_route_list
987 #endif
988         );
989
990         if(op & USAGE_OP_DONT_FRAGMNT)
991                 off = IP_DF;
992 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
993         useicmp = op & USAGE_OP_USE_ICMP;
994 #endif
995         nflag = op & USAGE_OP_ADDR_NUM;
996 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
997         verbose = op &  USAGE_OP_VERBOSE;
998 #endif
999         if(op & USAGE_OP_IP_CHKSUM) {
1000                 doipcksum = 0;
1001                 bb_error_msg("Warning: ip checksums disabled");
1002         }
1003         if (tos_str)
1004                 tos = str2val(tos_str, "tos", 0, 255);
1005         if(max_ttl_str)
1006                 max_ttl = str2val(max_ttl_str, "max ttl", 1, 255);
1007         if(port_str)
1008                 port = (u_short)str2val(port_str, "port", 1, (1 << 16) - 1);
1009         if(nprobes_str)
1010                 nprobes = str2val(optarg, "nprobes", 1, -1);
1011         if(source) {
1012             /*
1013              * set the ip source address of the outbound
1014              * probe (e.g., on a multi-homed host).
1015              */
1016              if (uid)
1017                 bb_error_msg_and_die("-s %s: Permission denied", source);
1018         }
1019         if(waittime_str)
1020                 waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60);
1021         if(pausemsecs_str)
1022                 pausemsecs = str2val(pausemsecs_str, "pause msecs", 0, 60 * 60 * 1000);
1023         if(first_ttl_str)
1024                 first_ttl = str2val(first_ttl_str, "first ttl", 1, 255);
1025
1026 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
1027         if(sourse_route_list) {
1028                 llist_t *l_sr;
1029
1030                 for(l_sr = sourse_route_list; l_sr; ) {
1031                         if (lsrr >= NGATEWAYS)
1032                                 bb_error_msg_and_die("No more than %d gateways", NGATEWAYS);
1033                         getaddr(gwlist + lsrr, l_sr->data);
1034                         ++lsrr;
1035                         l_sr = l_sr->link;
1036                         free(sourse_route_list);
1037                         sourse_route_list = l_sr;
1038                 }
1039                 optlen = (lsrr + 1) * sizeof(gwlist[0]);
1040         }
1041 #endif
1042
1043         if (first_ttl > max_ttl) {
1044                 bb_error_msg_and_die(
1045                     "first ttl (%d) may not be greater than max ttl (%d)",
1046                     first_ttl, max_ttl);
1047         }
1048
1049         minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
1050
1051 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
1052         if (useicmp)
1053                 minpacket += 8;                 /* XXX magic number */
1054         else
1055 #endif
1056                 minpacket += sizeof(*outudp);
1057         packlen = minpacket;                    /* minimum sized packet */
1058
1059         /* Process destination and optional packet size */
1060         switch (argc - optind) {
1061
1062         case 2:
1063                 packlen = str2val(argv[optind + 1],
1064                     "packet length", minpacket, maxpacket);
1065                 /* Fall through */
1066
1067         case 1:
1068                 hostname = argv[optind];
1069                 hi = gethostinfo(hostname);
1070                 setsin(to, hi->addrs[0]);
1071                 if (hi->n > 1)
1072                         bb_error_msg(
1073                     "Warning: %s has multiple addresses; using %s",
1074                                 hostname, inet_ntoa(to->sin_addr));
1075                 hostname = hi->name;
1076                 hi->name = NULL;
1077                 freehostinfo(hi);
1078                 break;
1079
1080         default:
1081                 bb_show_usage();
1082         }
1083
1084         cp = "icmp";
1085         if ((pe = getprotobyname(cp)) == NULL)
1086                 bb_perror_msg_and_die("unknown protocol %s", cp);
1087
1088         /* Insure the socket fds won't be 0, 1 or 2 */
1089         do n = bb_xopen(bb_dev_null, O_RDONLY); while (n < 2);
1090         if (n > 2)
1091                 close(n);
1092
1093         s = bb_xsocket(AF_INET, SOCK_RAW, pe->p_proto);
1094
1095 #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
1096         if (op & USAGE_OP_DEBUG)
1097                 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
1098                     sizeof(on));
1099 #endif
1100         if (op & USAGE_OP_BYPASS_ROUTE)
1101                 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
1102                     sizeof(on));
1103
1104         sndsock = bb_xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
1105
1106 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
1107 #if defined(IP_OPTIONS)
1108         if (lsrr > 0) {
1109                 unsigned char optlist[MAX_IPOPTLEN];
1110
1111                 cp = "ip";
1112                 if ((pe = getprotobyname(cp)) == NULL)
1113                         bb_perror_msg_and_die("unknown protocol");
1114
1115                 /* final hop */
1116                 gwlist[lsrr] = to->sin_addr.s_addr;
1117                 ++lsrr;
1118
1119                 /* force 4 byte alignment */
1120                 optlist[0] = IPOPT_NOP;
1121                 /* loose source route option */
1122                 optlist[1] = IPOPT_LSRR;
1123                 i = lsrr * sizeof(gwlist[0]);
1124                 optlist[2] = i + 3;
1125                 /* Pointer to LSRR addresses */
1126                 optlist[3] = IPOPT_MINOFF;
1127                 memcpy(optlist + 4, gwlist, i);
1128
1129                 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
1130                     (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
1131                         bb_perror_msg_and_die("IP_OPTIONS");
1132                     }
1133         }
1134 #endif /* IP_OPTIONS */
1135 #endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
1136
1137 #ifdef SO_SNDBUF
1138         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
1139             sizeof(packlen)) < 0) {
1140                 bb_perror_msg_and_die("SO_SNDBUF");
1141         }
1142 #endif
1143 #ifdef IP_HDRINCL
1144         if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
1145             sizeof(on)) < 0 && errno != ENOPROTOOPT) {
1146                 bb_perror_msg_and_die("IP_HDRINCL");
1147         }
1148 #else
1149 #ifdef IP_TOS
1150         if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
1151             (char *)&tos, sizeof(tos)) < 0) {
1152                 bb_perror_msg_and_die("setsockopt tos %d", tos);
1153         }
1154 #endif
1155 #endif
1156 #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
1157         if (op & USAGE_OP_DEBUG)
1158                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
1159                     sizeof(on));
1160 #endif
1161         if (op & USAGE_OP_BYPASS_ROUTE)
1162                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
1163                     sizeof(on));
1164
1165         /* Revert to non-privileged user after opening sockets */
1166         setgid(getgid());
1167         setuid(uid);
1168
1169         outip = (struct ip *)xcalloc(1, (unsigned)packlen);
1170
1171         outip->ip_v = IPVERSION;
1172         if (tos_str)
1173                 outip->ip_tos = tos;
1174         outip->ip_len = htons(packlen);
1175         outip->ip_off = htons(off);
1176         outp = (unsigned char *)(outip + 1);
1177         outip->ip_dst = to->sin_addr;
1178
1179         outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
1180         ident = (getpid() & 0xffff) | 0x8000;
1181 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
1182         if (useicmp) {
1183                 outip->ip_p = IPPROTO_ICMP;
1184
1185                 outicmp = (struct icmp *)outp;
1186                 outicmp->icmp_type = ICMP_ECHO;
1187                 outicmp->icmp_id = htons(ident);
1188
1189                 outdata = (struct outdata *)(outp + 8); /* XXX magic number */
1190         } else
1191 #endif
1192                {
1193                 outip->ip_p = IPPROTO_UDP;
1194
1195                 outudp = (struct udphdr *)outp;
1196                 outudp->source = htons(ident);
1197                 outudp->len =
1198                     htons((u_short)(packlen - (sizeof(*outip) + optlen)));
1199                 outdata = (struct outdata *)(outudp + 1);
1200         }
1201
1202         /* Get the interface address list */
1203         n = ifaddrlist(&al);
1204
1205         /* Look for a specific device */
1206         if (device != NULL) {
1207                 for (i = n; i > 0; --i, ++al)
1208                         if (strcmp(device, al->device) == 0)
1209                                 break;
1210                 if (i <= 0) {
1211                         bb_error_msg_and_die("Can't find interface %s", device);
1212                 }
1213         }
1214
1215         /* Determine our source address */
1216         if (source == NULL) {
1217                 /*
1218                  * If a device was specified, use the interface address.
1219                  * Otherwise, try to determine our source address.
1220                  */
1221                 if (device != NULL)
1222                         setsin(from, al->addr);
1223                 findsaddr(to, from);
1224         } else {
1225                 hi = gethostinfo(source);
1226                 source = hi->name;
1227                 hi->name = NULL;
1228                 /*
1229                  * If the device was specified make sure it
1230                  * corresponds to the source address specified.
1231                  * Otherwise, use the first address (and warn if
1232                  * there are more than one).
1233                  */
1234                 if (device != NULL) {
1235                         for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
1236                                 if (*ap == al->addr)
1237                                         break;
1238                         if (i <= 0) {
1239                                 bb_error_msg_and_die(
1240                                     "%s is not on interface %s",
1241                                     source, device);
1242                         }
1243                         setsin(from, *ap);
1244                 } else {
1245                         setsin(from, hi->addrs[0]);
1246                         if (hi->n > 1)
1247                                 bb_error_msg(
1248                         "Warning: %s has multiple addresses; using %s",
1249                                     source, inet_ntoa(from->sin_addr));
1250                 }
1251                 freehostinfo(hi);
1252         }
1253
1254         outip->ip_src = from->sin_addr;
1255 #ifndef IP_HDRINCL
1256         if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
1257                 bb_perror_msg_and_die("bind");
1258         }
1259 #endif
1260
1261         fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
1262         if (source)
1263                 fprintf(stderr, " from %s", source);
1264         fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
1265         (void)fflush(stderr);
1266
1267         for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
1268                 u_int32_t lastaddr = 0;
1269                 int gotlastaddr = 0;
1270                 int got_there = 0;
1271                 int unreachable = 0;
1272                 int sentfirst = 0;
1273
1274                 printf("%2d ", ttl);
1275                 for (probe = 0; probe < nprobes; ++probe) {
1276                         int cc;
1277                         struct timeval t1, t2;
1278                         struct timezone tz;
1279                         struct ip *ip;
1280
1281                         if (sentfirst && pausemsecs > 0)
1282                                 usleep(pausemsecs * 1000);
1283                         (void)gettimeofday(&t1, &tz);
1284                         send_probe(++seq, ttl, &t1);
1285                         ++sentfirst;
1286                         while ((cc = wait_for_reply(s, from, &t1)) != 0) {
1287                                 (void)gettimeofday(&t2, &tz);
1288                                 i = packet_ok(packet, cc, from, seq);
1289                                 /* Skip short packet */
1290                                 if (i == 0)
1291                                         continue;
1292                                 if (!gotlastaddr ||
1293                                     from->sin_addr.s_addr != lastaddr) {
1294                                         print(packet, cc, from);
1295                                         lastaddr = from->sin_addr.s_addr;
1296                                         ++gotlastaddr;
1297                                 }
1298                                 printf("  %.3f ms", deltaT(&t1, &t2));
1299                                 ip = (struct ip *)packet;
1300                                 if (op & USAGE_OP_TTL_FLAG)
1301                                         printf(" (%d)", ip->ip_ttl);
1302                                 if (i == -2) {
1303                                         if (ip->ip_ttl <= 1)
1304                                                 printf(" !");
1305                                         ++got_there;
1306                                         break;
1307                                 }
1308                                 /* time exceeded in transit */
1309                                 if (i == -1)
1310                                         break;
1311                                 code = i - 1;
1312                                 switch (code) {
1313
1314                                 case ICMP_UNREACH_PORT:
1315                                         if (ip->ip_ttl <= 1)
1316                                                 printf(" !");
1317                                         ++got_there;
1318                                         break;
1319
1320                                 case ICMP_UNREACH_NET:
1321                                         ++unreachable;
1322                                         printf(" !N");
1323                                         break;
1324
1325                                 case ICMP_UNREACH_HOST:
1326                                         ++unreachable;
1327                                         printf(" !H");
1328                                         break;
1329
1330                                 case ICMP_UNREACH_PROTOCOL:
1331                                         ++got_there;
1332                                         printf(" !P");
1333                                         break;
1334
1335                                 case ICMP_UNREACH_NEEDFRAG:
1336                                         ++unreachable;
1337                                         printf(" !F-%d", pmtu);
1338                                         break;
1339
1340                                 case ICMP_UNREACH_SRCFAIL:
1341                                         ++unreachable;
1342                                         printf(" !S");
1343                                         break;
1344
1345                                 case ICMP_UNREACH_FILTER_PROHIB:
1346                                 case ICMP_UNREACH_NET_PROHIB:   /* misuse */
1347                                         ++unreachable;
1348                                         printf(" !A");
1349                                         break;
1350
1351                                 case ICMP_UNREACH_HOST_PROHIB:
1352                                         ++unreachable;
1353                                         printf(" !C");
1354                                         break;
1355
1356                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1357                                         ++unreachable;
1358                                         printf(" !V");
1359                                         break;
1360
1361                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1362                                         ++unreachable;
1363                                         printf(" !C");
1364                                         break;
1365
1366                                 case ICMP_UNREACH_NET_UNKNOWN:
1367                                 case ICMP_UNREACH_HOST_UNKNOWN:
1368                                         ++unreachable;
1369                                         printf(" !U");
1370                                         break;
1371
1372                                 case ICMP_UNREACH_ISOLATED:
1373                                         ++unreachable;
1374                                         printf(" !I");
1375                                         break;
1376
1377                                 case ICMP_UNREACH_TOSNET:
1378                                 case ICMP_UNREACH_TOSHOST:
1379                                         ++unreachable;
1380                                         printf(" !T");
1381                                         break;
1382
1383                                 default:
1384                                         ++unreachable;
1385                                         printf(" !<%d>", code);
1386                                         break;
1387                                 }
1388                                 break;
1389                         }
1390                         if (cc == 0)
1391                                 printf(" *");
1392                         (void)fflush(stdout);
1393                 }
1394                 putchar('\n');
1395                 if (got_there ||
1396                     (unreachable > 0 && unreachable >= nprobes - 1))
1397                         break;
1398         }
1399         return 0;
1400 }