* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-//#define version "1.4a12"
-
-
/*
* traceroute host - trace the route ip packets follow going to "host".
*
};
/* Data section of the probe packet */
-struct outdata {
+typedef struct outdata {
unsigned char seq; /* sequence number of this packet */
unsigned char ttl; /* ttl packet left with */
// UNUSED. Retaining to have the same packet size.
struct timeval tv_UNUSED ATTRIBUTE_PACKED; /* time packet left */
-};
+} outdata_t;
struct IFADDRLIST {
uint32_t addr;
};
-static struct ip *outip; /* last output (udp) packet */
-static struct udphdr *outudp; /* last output (udp) packet */
-static struct outdata *outdata; /* last output (udp) packet */
-
-#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
-static struct icmp *outicmp; /* last output (icmp) packet */
-#endif
-
-static int s; /* receive (icmp) socket file descriptor */
-static int sndsock; /* send (udp/icmp) socket file descriptor */
-
-static int packlen; /* total length of packet */
-static int minpacket; /* min ip packet size */
-static int maxpacket = 32 * 1024; /* max ip packet size */
-static int pmtu; /* Path MTU Discovery (RFC1191) */
-
-static char *hostname;
-
-static uint16_t ident;
-static uint16_t port = 32768 + 666; /* start udp dest port # for probe packets */
-
-static int waittime = 5; /* time to wait for response (in seconds) */
-static int doipcksum = 1; /* calculate ip checksums by default */
-
-#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
-static int optlen; /* length of ip options */
-#else
-#define optlen 0
-#endif
-
-
/* Keep in sync with getopt32 call! */
#define OPT_DONT_FRAGMNT (1<<0) /* F */
#define OPT_USE_ICMP (1<<1) /* I */
struct globals {
- /* last inbound (icmp) packet */
- unsigned char packet[512];
+ struct ip *outip; /* last output (udp) packet */
+ struct udphdr *outudp; /* last output (udp) packet */
+ struct outdata *outdata; /* last output (udp) packet */
+
+#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
+ struct icmp *outicmp; /* last output (icmp) packet */
+#endif
+
+ int rcvsock; /* receive (icmp) socket file descriptor */
+ int sndsock; /* send (udp/icmp) socket file descriptor */
+
+ int packlen; /* total length of packet */
+ int minpacket; /* min ip packet size */
+ int maxpacket; // 32 * 1024; /* max ip packet size */
+ int pmtu; /* Path MTU Discovery (RFC1191) */
+
+ char *hostname;
+
+ uint16_t ident;
+ uint16_t port; // 32768 + 666; /* start udp dest port # for probe packets */
+
+ int waittime; // 5; /* time to wait for response (in seconds) */
+ int doipcksum; // 1; /* calculate ip checksums by default */
+
+#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
+ int optlen; /* length of ip options */
+#else
+#define optlen 0
+#endif
+
struct sockaddr_storage whereto; /* Who to try to reach */
struct sockaddr_storage wherefrom; /* Who we are */
+ /* last inbound (icmp) packet */
+ unsigned char packet[512];
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
/* Maximum number of gateways (include room for one noop) */
#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
};
#define G (*ptr_to_globals)
-
+#define outip (G.outip )
+#define outudp (G.outudp )
+#define outdata (G.outdata )
+#define outicmp (G.outicmp )
+#define rcvsock (G.rcvsock )
+#define sndsock (G.sndsock )
+#define packlen (G.packlen )
+#define minpacket (G.minpacket)
+#define maxpacket (G.maxpacket)
+#define pmtu (G.pmtu )
+#define hostname (G.hostname )
+#define ident (G.ident )
+#define port (G.port )
+#define waittime (G.waittime )
+#define doipcksum (G.doipcksum)
+#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
+#define optlen (G.optlen )
+#endif
#define packet (G.packet )
#define whereto (G.whereto )
#define wherefrom (G.wherefrom)
#define gwlist (G.gwlist )
+#define INIT_G() do { \
+ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+ maxpacket = 32 * 1024; \
+ port = 32768 + 666; \
+ waittime = 5; \
+ doipcksum = 1; \
+} while (0)
/*
static int
wait_for_reply(int sock, struct sockaddr_in *fromp)
{
- fd_set fds;
- struct timeval tvwait;
+ struct pollfd pfd[1];
int cc = 0;
socklen_t fromlen = sizeof(*fromp);
- FD_ZERO(&fds);
- FD_SET(sock, &fds);
-
- tvwait.tv_sec = waittime;
- tvwait.tv_usec = 0;
-
- if (select(sock + 1, &fds, NULL, NULL, &tvwait) > 0)
- cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
+ pfd[0].fd = sock;
+ pfd[0].events = POLLIN;
+ if (safe_poll(pfd, 1, waittime * 1000) > 0)
+ cc = recvfrom(sock, packet, sizeof(packet), 0,
(struct sockaddr *)fromp, &fromlen);
-
return cc;
}
static inline const char *
pr_type(unsigned char t)
{
- static const char * const ttab[] = {
+ static const char *const ttab[] = {
"Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
"Source Quench", "Redirect", "ICMP 6", "ICMP 7",
"Echo", "Router Advert", "Router Solicit", "Time Exceeded",
}
#endif
+#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
+#define packet_ok(buf, cc, from, seq) \
+ packet_ok(buf, cc, seq)
+#endif
static int
packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
{
else {
char *n = NULL;
if (from->sin_addr.s_addr != INADDR_ANY)
- n = xmalloc_sockaddr2host_noport((struct sockaddr*)from, sizeof(*from));
+ n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
printf(" %s (%s)", (n ? n : ina), ina);
free(n);
}
printf(" %u.%03u ms", tt/1000, tt%1000);
}
-int traceroute_main(int argc, char **argv);
+int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int traceroute_main(int argc, char **argv)
{
int code, n;
llist_t *source_route_list = NULL;
#endif
- PTR_TO_GLOBALS = xzalloc(sizeof(G));
+ INIT_G();
from = (struct sockaddr_in *)&wherefrom;
to = (struct sockaddr_in *)&whereto;
opt_complementary = "x-x";
#endif
- op = getopt32(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
+ op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
"g:"
#endif
/* Ensure the socket fds won't be 0, 1 or 2 */
bb_sanitize_stdio();
- s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ rcvsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
#if TRACEROUTE_SO_DEBUG
if (op & OPT_DEBUG)
- setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
&const_int_1, sizeof(const_int_1));
#endif
if (op & OPT_BYPASS_ROUTE)
- setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
+ setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
&const_int_1, sizeof(const_int_1));
sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
outicmp = (struct icmp *)outp;
outicmp->icmp_type = ICMP_ECHO;
outicmp->icmp_id = htons(ident);
- outdata = (struct outdata *)(outp + 8); /* XXX magic number */
+ outdata = (outdata_t *)(outp + 8); /* XXX magic number */
} else
#endif
{
outudp = (struct udphdr *)outp;
outudp->source = htons(ident);
outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen)));
- outdata = (struct outdata *)(outudp + 1);
+ outdata = (outdata_t *)(outudp + 1);
}
/* Get the interface address list */
t1 = monotonic_us();
send_probe(++seq, ttl);
++sentfirst;
- while ((cc = wait_for_reply(s, from)) != 0) {
+ while ((cc = wait_for_reply(rcvsock, from)) != 0) {
t2 = monotonic_us();
i = packet_ok(packet, cc, from, seq);
/* Skip short packet */
printf(" *");
(void)fflush(stdout);
}
- putchar('\n');
+ bb_putchar('\n');
if (got_there ||
(unreachable > 0 && unreachable >= nprobes - 1))
break;