diff --git a/networking/traceroute.c b/networking/traceroute.c index fd4c20e6d..552903655 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -284,11 +284,6 @@ struct IFADDRLIST { }; -static const char route[] = "/proc/net/route"; - -/* last inbound (icmp) packet */ -static unsigned char packet[512] ATTRIBUTE_ALIGNED(32); - static struct ip *outip; /* last output (udp) packet */ static struct udphdr *outudp; /* last output (udp) packet */ static struct outdata *outdata; /* last output (udp) packet */ @@ -297,18 +292,9 @@ static struct outdata *outdata; /* last output (udp) packet */ static struct icmp *outicmp; /* last output (icmp) packet */ #endif -#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))) -/* loose source route gateway list (including room for final destination) */ -static uint32_t gwlist[NGATEWAYS + 1]; -#endif - static int s; /* receive (icmp) socket file descriptor */ static int sndsock; /* send (udp/icmp) socket file descriptor */ -static struct sockaddr_storage whereto; /* Who to try to reach */ -static struct sockaddr_storage wherefrom; /* Who we are */ static int packlen; /* total length of packet */ static int minpacket; /* min ip packet size */ static int maxpacket = 32 * 1024; /* max ip packet size */ @@ -320,7 +306,6 @@ 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 nflag; /* print addresses numerically */ static int doipcksum = 1; /* calculate ip checksums by default */ #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE @@ -329,12 +314,56 @@ static int optlen; /* length of ip options */ #define optlen 0 #endif + +/* Keep in sync with getopt32 call! */ +#define OPT_DONT_FRAGMNT (1<<0) /* F */ +#define OPT_USE_ICMP (1<<1) /* I */ +#define OPT_TTL_FLAG (1<<2) /* l */ +#define OPT_ADDR_NUM (1<<3) /* n */ +#define OPT_BYPASS_ROUTE (1<<4) /* r */ +#define OPT_DEBUG (1<<5) /* d */ +#define OPT_VERBOSE (1<<6) /* v */ +#define OPT_IP_CHKSUM (1<<7) /* x */ +#define OPT_TOS (1<<8) /* t */ +#define OPT_DEVICE (1<<9) /* i */ +#define OPT_MAX_TTL (1<<10) /* m */ +#define OPT_PORT (1<<11) /* p */ +#define OPT_NPROBES (1<<12) /* q */ +#define OPT_SOURCE (1<<13) /* s */ +#define OPT_WAITTIME (1<<14) /* w */ +#define OPT_PAUSE_MS (1<<15) /* z */ +#define OPT_FIRST_TTL (1<<16) /* f */ + #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP -static int useicmp; /* use icmp echo instead of udp packets */ +/* use icmp echo instead of udp packets */ +#define useicmp (option_mask32 & OPT_USE_ICMP) #endif #if ENABLE_FEATURE_TRACEROUTE_VERBOSE -static int verbose; +#define verbose (option_mask32 & OPT_VERBOSE) #endif +#define nflag (option_mask32 & OPT_ADDR_NUM) + + +struct globals { + /* last inbound (icmp) packet */ + unsigned char packet[512]; + struct sockaddr_storage whereto; /* Who to try to reach */ + struct sockaddr_storage wherefrom; /* Who we are */ +#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))) + /* loose source route gateway list (including room for final destination) */ + uint32_t gwlist[NGATEWAYS + 1]; +#endif +}; + +#define G (*ptr_to_globals) + +#define packet (G.packet ) +#define whereto (G.whereto ) +#define wherefrom (G.wherefrom) +#define gwlist (G.gwlist ) + /* * Return the interface list @@ -453,7 +482,7 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) struct IFADDRLIST *al; char buf[256], tdevice[256], device[256]; - f = xfopen(route, "r"); + f = xfopen("/proc/net/route", "r"); /* Find the appropriate interface */ n = 0; @@ -892,37 +921,40 @@ int traceroute_main(int argc, char *argv[]) int code, n; unsigned char *outp; uint32_t *ap; - struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; - struct sockaddr_in *to = (struct sockaddr_in *)&whereto; + struct sockaddr_in *from; + struct sockaddr_in *to; struct hostinfo *hi; int ttl, probe, i; int seq = 0; int tos = 0; - char *tos_str = NULL; - char *source = NULL; - unsigned long op; - + char *tos_str; + char *source; + unsigned op; #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE int lsrr = 0; #endif uint16_t off = 0; struct IFADDRLIST *al; - char *device = NULL; + char *device; int max_ttl = 30; - char *max_ttl_str = NULL; - char *port_str = NULL; + char *max_ttl_str; + char *port_str; int nprobes = 3; - char *nprobes_str = NULL; - char *waittime_str = NULL; + char *nprobes_str; + char *waittime_str; unsigned pausemsecs = 0; - char *pausemsecs_str = NULL; + char *pausemsecs_str; int first_ttl = 1; - char *first_ttl_str = NULL; + char *first_ttl_str; #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE llist_t *sourse_route_list = NULL; #endif - opterr = 0; + PTR_TO_GLOBALS = xzalloc(sizeof(G)); + from = (struct sockaddr_in *)&wherefrom; + to = (struct sockaddr_in *)&whereto; + + //opterr = 0; #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE opt_complementary = "x-x:g::"; #else @@ -930,65 +962,51 @@ int traceroute_main(int argc, char *argv[]) #endif op = getopt32(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:" -#define USAGE_OP_DONT_FRAGMNT (1<<0) /* F */ -#define USAGE_OP_USE_ICMP (1<<1) /* I */ -#define USAGE_OP_TTL_FLAG (1<<2) /* l */ -#define USAGE_OP_ADDR_NUM (1<<3) /* n */ -#define USAGE_OP_BYPASS_ROUTE (1<<4) /* r */ -#define USAGE_OP_DEBUG (1<<5) /* d */ -#define USAGE_OP_VERBOSE (1<<6) /* v */ -#define USAGE_OP_IP_CHKSUM (1<<7) /* x */ - #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE "g:" #endif - , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str, - &source, &waittime_str, &pausemsecs_str, &first_ttl_str + , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str + , &source, &waittime_str, &pausemsecs_str, &first_ttl_str #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE - , &sourse_route_list + , &sourse_route_list #endif ); - if (op & USAGE_OP_DONT_FRAGMNT) + if (op & OPT_DONT_FRAGMNT) off = IP_DF; -#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP - useicmp = op & USAGE_OP_USE_ICMP; -#endif - nflag = op & USAGE_OP_ADDR_NUM; -#if ENABLE_FEATURE_TRACEROUTE_VERBOSE - verbose = op & USAGE_OP_VERBOSE; -#endif - if (op & USAGE_OP_IP_CHKSUM) { + if (op & OPT_IP_CHKSUM) { doipcksum = 0; bb_error_msg("warning: ip checksums disabled"); } - if (tos_str) - tos = xatoul_range(tos_str, 0, 255); - if (max_ttl_str) - max_ttl = xatoul_range(max_ttl_str, 1, 255); - if (port_str) + if (op & OPT_TOS) + tos = xatou_range(tos_str, 0, 255); + if (op & OPT_MAX_TTL) + max_ttl = xatou_range(max_ttl_str, 1, 255); + if (op & OPT_PORT) port = xatou16(port_str); - if (nprobes_str) - nprobes = xatoul_range(nprobes_str, 1, INT_MAX); - if (source) { + if (op & OPT_NPROBES) + nprobes = xatou_range(nprobes_str, 1, INT_MAX); + if (op & OPT_SOURCE) { /* * set the ip source address of the outbound * probe (e.g., on a multi-homed host). */ - if (getuid()) bb_error_msg_and_die("-s %s: permission denied", source); + if (getuid()) + bb_error_msg_and_die("-s %s: permission denied", source); } - if (waittime_str) - waittime = xatoul_range(waittime_str, 2, 24 * 60 * 60); - if (pausemsecs_str) - pausemsecs = xatoul_range(pausemsecs_str, 0, 60 * 60 * 1000); - if (first_ttl_str) - first_ttl = xatoul_range(first_ttl_str, 1, 255); + if (op & OPT_WAITTIME) + waittime = xatou_range(waittime_str, 2, 24 * 60 * 60); + if (op & OPT_PAUSE_MS) + pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); + if (op & OPT_FIRST_TTL) + first_ttl = xatou_range(first_ttl_str, 1, 255); #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE if (sourse_route_list) { llist_t *l_sr; - for (l_sr = sourse_route_list; l_sr; ) { + l_sr = sourse_route_list; + while (l_sr) { if (lsrr >= NGATEWAYS) bb_error_msg_and_die("no more than %d gateways", NGATEWAYS); getaddr(gwlist + lsrr, l_sr->data); @@ -1046,11 +1064,11 @@ int traceroute_main(int argc, char *argv[]) s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); #if TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) + if (op & OPT_DEBUG) setsockopt(s, SOL_SOCKET, SO_DEBUG, &const_int_1, sizeof(const_int_1)); #endif - if (op & USAGE_OP_BYPASS_ROUTE) + if (op & OPT_BYPASS_ROUTE) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)); @@ -1102,11 +1120,11 @@ int traceroute_main(int argc, char *argv[]) #endif #endif #if TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) + if (op & OPT_DEBUG) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, &const_int_1, sizeof(const_int_1)); #endif - if (op & USAGE_OP_BYPASS_ROUTE) + if (op & OPT_BYPASS_ROUTE) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)); @@ -1147,22 +1165,21 @@ int traceroute_main(int argc, char *argv[]) n = ifaddrlist(&al); /* Look for a specific device */ - if (device != NULL) { + if (op & OPT_DEVICE) { for (i = n; i > 0; --i, ++al) if (strcmp(device, al->device) == 0) - break; - if (i <= 0) { - bb_error_msg_and_die("can't find interface %s", device); - } + goto found_dev; + bb_error_msg_and_die("can't find interface %s", device); } + found_dev: /* Determine our source address */ - if (source == NULL) { + if (!(op & OPT_SOURCE)) { /* * If a device was specified, use the interface address. * Otherwise, try to determine our source address. */ - if (device != NULL) + if (op & OPT_DEVICE) setsin(from, al->addr); findsaddr(to, from); } else { @@ -1175,21 +1192,19 @@ int traceroute_main(int argc, char *argv[]) * Otherwise, use the first address (and warn if * there are more than one). */ - if (device != NULL) { + if (op & OPT_DEVICE) { for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) if (*ap == al->addr) - break; - if (i <= 0) { - bb_error_msg_and_die( - "%s is not on interface %s", - source, device); - } + goto found_dev2; + bb_error_msg_and_die("%s is not on interface %s", + source, device); + found_dev2: setsin(from, *ap); } else { setsin(from, hi->addrs[0]); if (hi->n > 1) bb_error_msg( - "Warning: %s has multiple addresses; using %s", + "warning: %s has multiple addresses; using %s", source, inet_ntoa(from->sin_addr)); } freehostinfo(hi); @@ -1200,11 +1215,11 @@ int traceroute_main(int argc, char *argv[]) xbind(sndsock, (struct sockaddr *)from, sizeof(*from)); #endif - fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); - if (source) - fprintf(stderr, " from %s", source); - fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen); - (void)fflush(stderr); + printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); + if (op & OPT_SOURCE) + printf(" from %s", source); + printf(", %d hops max, %d byte packets\n", max_ttl, packlen); + fflush(stdout); for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { uint32_t lastaddr = 0; @@ -1239,7 +1254,7 @@ int traceroute_main(int argc, char *argv[]) } printf(" %.3f ms", deltaT(&t1, &t2)); ip = (struct ip *)packet; - if (op & USAGE_OP_TTL_FLAG) + if (op & OPT_TTL_FLAG) printf(" (%d)", ip->ip_ttl); if (i == -2) { if (ip->ip_ttl <= 1)