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