X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Ftraceroute.c;h=33023e74fd09909a3bab115c3360dad28bdc2b13;hb=2f7b923f5c46de0840d7a683b75b6e8561461135;hp=49007654360d93f86e58b19a64eac58fcc0a3efd;hpb=48237b0c88343154d58854020c3a9c8b07c61b10;p=oweals%2Fbusybox.git diff --git a/networking/traceroute.c b/networking/traceroute.c index 490076543..33023e74f 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -207,7 +207,6 @@ //#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP //#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP -#include "inet_common.h" #include #include @@ -217,6 +216,7 @@ #include #include "busybox.h" +#include "inet_common.h" /* @@ -247,7 +247,7 @@ struct ipovly { /* * UDP kernel structures and variables. */ -struct udpiphdr { +struct udpiphdr { struct ipovly ui_i; /* overlaid ip structure */ struct udphdr ui_u; /* udp header */ }; @@ -268,7 +268,7 @@ struct udpiphdr { struct hostinfo { char *name; int n; - u_int32_t *addrs; + uint32_t *addrs; }; /* Data section of the probe packet */ @@ -279,16 +279,11 @@ struct outdata { }; struct IFADDRLIST { - u_int32_t addr; + uint32_t addr; char device[sizeof(struct ifreq)]; }; -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(u_int32_t))) -/* loose source route gateway list (including room for final destination) */ -static u_int32_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 */ @@ -316,11 +302,10 @@ static int pmtu; /* Path MTU Discovery (RFC1191) */ static char *hostname; -static u_short ident; -static u_short port = 32768 + 666; /* start udp dest port # for probe packets */ +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 @@ -429,7 +458,7 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) static void -setsin(struct sockaddr_in *addr_sin, u_int32_t addr) +setsin(struct sockaddr_in *addr_sin, uint32_t addr) { memset(addr_sin, 0, sizeof(*addr_sin)); #ifdef HAVE_SOCKADDR_SA_LEN @@ -448,12 +477,12 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) { int i, n; FILE *f; - u_int32_t mask; - u_int32_t dest, tmask; + uint32_t mask; + uint32_t dest, tmask; 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; @@ -539,12 +568,12 @@ wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp) /* * Checksum routine for Internet Protocol family headers (C Version) */ -static u_short -in_cksum(u_short *addr, int len) +static uint16_t +in_cksum(uint16_t *addr, int len) { int nleft = len; - u_short *w = addr; - u_short answer; + uint16_t *w = addr; + uint16_t answer; int sum = 0; /* @@ -589,7 +618,7 @@ send_probe(int seq, int ttl, struct timeval *tp) */ if (doipcksum) { outip->ip_sum = - in_cksum((u_short *)outip, sizeof(*outip) + optlen); + in_cksum((uint16_t *)outip, sizeof(*outip) + optlen); if (outip->ip_sum == 0) outip->ip_sum = 0xffff; } @@ -610,7 +639,7 @@ send_probe(int seq, int ttl, struct timeval *tp) if (useicmp) { /* Always calculate checksum for icmp packets */ outicmp->icmp_cksum = 0; - outicmp->icmp_cksum = in_cksum((u_short *)outicmp, + outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, packlen - (sizeof(*outip) + optlen)); if (outicmp->icmp_cksum == 0) outicmp->icmp_cksum = 0xffff; @@ -628,7 +657,7 @@ send_probe(int seq, int ttl, struct timeval *tp) ui->ui_pr = oui->ui_pr; ui->ui_len = outudp->len; outudp->check = 0; - outudp->check = in_cksum((u_short *)ui, packlen); + outudp->check = in_cksum((uint16_t *)ui, packlen); if (outudp->check == 0) outudp->check = 0xffff; *outip = tip; @@ -637,11 +666,11 @@ send_probe(int seq, int ttl, struct timeval *tp) #if ENABLE_FEATURE_TRACEROUTE_VERBOSE /* XXX undocumented debugging hack */ if (verbose > 1) { - const u_short *sp; + const uint16_t *sp; int nshorts, i; - sp = (u_short *)outip; - nshorts = (u_int)packlen / sizeof(u_short); + sp = (uint16_t *)outip; + nshorts = (unsigned)packlen / sizeof(uint16_t); i = 0; printf("[ %d bytes", packlen); while (--nshorts >= 0) { @@ -776,7 +805,7 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) #if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) { int i; - u_int32_t *lp = (u_int32_t *)&icp->icmp_ip; + uint32_t *lp = (uint32_t *)&icp->icmp_ip; printf("\n%d bytes from %s to " "%s: icmp type %d (%s) code %d\n", @@ -803,7 +832,8 @@ inetname(struct sockaddr_in *from) char name[257]; if (!nflag && from->sin_addr.s_addr != INADDR_ANY) { - if (INET_rresolve(name, sizeof(name), from, 0x4000, 0xffffffff) >= 0) + if (INET_rresolve(name, sizeof(name), from, 0x4000, + 0xffffffff) >= 0) n = name; } ina = inet_ntoa(from->sin_addr); @@ -838,11 +868,11 @@ gethostinfo(const char *host) struct hostent *hp; struct hostinfo *hi; char **p; - u_int32_t addr, *ap; + uint32_t addr, *ap; hi = xzalloc(sizeof(*hi)); addr = inet_addr(host); - if ((int32_t)addr != -1) { + if (addr != 0xffffffff) { hi->name = xstrdup(host); hi->n = 1; hi->addrs = xzalloc(sizeof(hi->addrs[0])); @@ -874,7 +904,7 @@ freehostinfo(struct hostinfo *hi) #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE static void -getaddr(u_int32_t *ap, const char *host) +getaddr(uint32_t *ap, const char *host) { struct hostinfo *hi; @@ -885,45 +915,46 @@ getaddr(u_int32_t *ap, const char *host) #endif -int -traceroute_main(int argc, char *argv[]) +int traceroute_main(int argc, char **argv); +int traceroute_main(int argc, char **argv) { - static const int on = 1; - int code, n; unsigned char *outp; - u_int32_t *ap; - struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; - struct sockaddr_in *to = (struct sockaddr_in *)&whereto; + uint32_t *ap; + 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 - u_short off = 0; + 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; - u_int pausemsecs = 0; - char *pausemsecs_str = NULL; + char *nprobes_str; + char *waittime_str; + unsigned pausemsecs = 0; + 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 @@ -931,65 +962,51 @@ 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); @@ -1041,21 +1058,19 @@ traceroute_main(int argc, char *argv[]) bb_show_usage(); } - /* Insure the socket fds won't be 0, 1 or 2 */ - do n = xopen(bb_dev_null, O_RDONLY); while (n < 2); - if (n > 2) - close(n); + /* Ensure the socket fds won't be 0, 1 or 2 */ + bb_sanitize_stdio(); s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); #if TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) - (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)); + if (op & OPT_DEBUG) + setsockopt(s, SOL_SOCKET, SO_DEBUG, + &const_int_1, sizeof(const_int_1)); #endif - if (op & USAGE_OP_BYPASS_ROUTE) - (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on, - sizeof(on)); + if (op & OPT_BYPASS_ROUTE) + setsockopt(s, SOL_SOCKET, SO_DONTROUTE, + &const_int_1, sizeof(const_int_1)); sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); @@ -1087,38 +1102,37 @@ traceroute_main(int argc, char *argv[]) #endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */ #ifdef SO_SNDBUF - if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen, - sizeof(packlen)) < 0) { + if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { bb_perror_msg_and_die("SO_SNDBUF"); } #endif #ifdef IP_HDRINCL - if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, - sizeof(on)) < 0 && errno != ENOPROTOOPT) { + if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0 + && errno != ENOPROTOOPT + ) { bb_perror_msg_and_die("IP_HDRINCL"); } #else #ifdef IP_TOS - if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, - (char *)&tos, sizeof(tos)) < 0) { + if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { bb_perror_msg_and_die("setsockopt tos %d", tos); } #endif #endif #if TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) - (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)); + if (op & OPT_DEBUG) + setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, + &const_int_1, sizeof(const_int_1)); #endif - if (op & USAGE_OP_BYPASS_ROUTE) - (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on, - sizeof(on)); + if (op & OPT_BYPASS_ROUTE) + setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, + &const_int_1, sizeof(const_int_1)); /* Revert to non-privileged user after opening sockets */ xsetgid(getgid()); xsetuid(getuid()); - outip = (struct ip *)xzalloc(packlen); + outip = xzalloc(packlen); outip->ip_v = IPVERSION; if (tos_str) @@ -1133,21 +1147,17 @@ traceroute_main(int argc, char *argv[]) #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP if (useicmp) { outip->ip_p = IPPROTO_ICMP; - outicmp = (struct icmp *)outp; outicmp->icmp_type = ICMP_ECHO; outicmp->icmp_id = htons(ident); - outdata = (struct outdata *)(outp + 8); /* XXX magic number */ } else #endif - { + { outip->ip_p = IPPROTO_UDP; - outudp = (struct udphdr *)outp; outudp->source = htons(ident); - outudp->len = - htons((u_short)(packlen - (sizeof(*outip) + optlen))); + outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen))); outdata = (struct outdata *)(outudp + 1); } @@ -1155,22 +1165,21 @@ 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 { @@ -1183,21 +1192,19 @@ 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); @@ -1208,14 +1215,14 @@ 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) { - u_int32_t lastaddr = 0; + uint32_t lastaddr = 0; int gotlastaddr = 0; int got_there = 0; int unreachable = 0; @@ -1247,7 +1254,7 @@ 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)