X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Ftraceroute.c;h=33023e74fd09909a3bab115c3360dad28bdc2b13;hb=2f7b923f5c46de0840d7a683b75b6e8561461135;hp=15d55e79bc0c6806f282903956efbe5f74c0b8d6;hpb=45a8ed89c69f95fa35f139a7c9ddb3874b13de46;p=oweals%2Fbusybox.git diff --git a/networking/traceroute.c b/networking/traceroute.c index 15d55e79b..33023e74f 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */ /* * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000 * The Regents of the University of California. All rights reserved. @@ -195,56 +196,49 @@ * Tue Dec 20 03:50:13 PST 1988 */ -#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#define TRACEROUTE_SO_DEBUG 0 + +/* TODO: undefs were uncommented - ??! we have config system for that! */ +/* probably ok to remove altogether */ +//#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE //#define CONFIG_FEATURE_TRACEROUTE_VERBOSE -#undef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG /* not in documentation man */ -#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE +//#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE //#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE -#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +//#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP //#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include /* concession to AIX */ -#include -#include "inet_common.h" #include -#include #include +#include #include #include #include #include "busybox.h" +#include "inet_common.h" /* * Definitions for internet protocol version 4. * Per RFC 791, September 1981. */ -#define IPVERSION 4 +#define IPVERSION 4 + +#ifndef IPPROTO_ICMP +/* Grrrr.... */ +#define IPPROTO_ICMP 1 +#endif +#ifndef IPPROTO_IP +#define IPPROTO_IP 0 +#endif /* * Overlay for ip header used by other protocols (tcp, udp). */ struct ipovly { - u_char ih_x1[9]; /* (unused) */ - u_char ih_pr; /* protocol */ + unsigned char ih_x1[9]; /* (unused) */ + unsigned char ih_pr; /* protocol */ short ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ @@ -253,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 */ }; @@ -274,74 +268,102 @@ struct udpiphdr { struct hostinfo { char *name; int n; - u_int32_t *addrs; + uint32_t *addrs; }; /* Data section of the probe packet */ struct outdata { - u_char seq; /* sequence number of this packet */ - u_char ttl; /* ttl packet left with */ - struct timeval tv __attribute__((packed)); /* time packet left */ + unsigned char seq; /* sequence number of this packet */ + unsigned char ttl; /* ttl packet left with */ + struct timeval tv ATTRIBUTE_PACKED; /* time packet left */ }; 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 u_char packet[512] __attribute__((align (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 */ -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP static struct icmp *outicmp; /* last output (icmp) packet */ #endif -#ifdef CONFIG_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 */ static int pmtu; /* Path MTU Discovery (RFC1191) */ static char *hostname; -static const char devnull[] = "/dev/null"; -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 */ -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE +#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE static int optlen; /* length of ip options */ #else #define optlen 0 #endif -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP -static int useicmp; /* use icmp echo instead of udp packets */ + +/* 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 +/* use icmp echo instead of udp packets */ +#define useicmp (option_mask32 & OPT_USE_ICMP) #endif -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE -static int verbose; +#if ENABLE_FEATURE_TRACEROUTE_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 @@ -360,9 +382,7 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; struct IFADDRLIST *st_ifaddrlist; - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) - bb_perror_msg_and_die("socket"); + fd = xsocket(AF_INET, SOCK_DGRAM, 0); ifc.ifc_len = sizeof(ibuf); ifc.ifc_buf = (caddr_t)ibuf; @@ -372,7 +392,7 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) if (errno == EINVAL) bb_error_msg_and_die( "SIOCGIFCONF: ifreq struct too small (%d bytes)", - sizeof(ibuf)); + (int)sizeof(ibuf)); else bb_perror_msg_and_die("SIOCGIFCONF"); } @@ -380,7 +400,7 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq)); - st_ifaddrlist = xcalloc(nipaddr, sizeof(struct IFADDRLIST)); + st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST)); al = st_ifaddrlist; nipaddr = 0; @@ -428,8 +448,8 @@ ifaddrlist(struct IFADDRLIST **ipaddrp) ++al; ++nipaddr; } - if(nipaddr == 0) - bb_error_msg_and_die ("Can't find any network interfaces"); + if (nipaddr == 0) + bb_error_msg_and_die ("can't find any network interfaces"); (void)close(fd); *ipaddrp = st_ifaddrlist; @@ -438,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 @@ -457,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 = bb_xfopen(route, "r"); + f = xfopen("/proc/net/route", "r"); /* Find the appropriate interface */ n = 0; @@ -484,7 +504,7 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) fclose(f); if (device[0] == '\0') - bb_error_msg_and_die ("Can't find interface"); + bb_error_msg_and_die ("can't find interface"); /* Get the interface address list */ n = ifaddrlist(&al); @@ -494,7 +514,7 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) if (strcmp(device, al->device) == 0) break; if (i <= 0) - bb_error_msg_and_die("Can't find interface %s", device); + bb_error_msg_and_die("can't find interface %s", device); setsin(from, al->addr); } @@ -506,34 +526,6 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from) */ -/* String to value with optional min and max. Handles decimal and hex. */ -static int -str2val(const char *str, const char *what, int mi, int ma) -{ - const char *cp; - int val; - char *ep; - - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - cp = str + 2; - val = (int)strtol(cp, &ep, 16); - } else - val = (int)strtol(str, &ep, 10); - if (*ep != '\0') { - bb_error_msg_and_die("\"%s\" bad value for %s \n", str, what); - } - if (val < mi && mi >= 0) { - if (mi == 0) - bb_error_msg_and_die("%s must be >= %d\n", what, mi); - else - bb_error_msg_and_die("%s must be > %d\n", what, mi - 1); - } - if (val > ma && ma >= 0) - bb_error_msg_and_die("%s must be <= %d\n", what, ma); - return val; -} - - /* * Subtract 2 timeval structs: out = out - in. * Out is assumed to be >= in. @@ -553,7 +545,7 @@ static int wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp) { fd_set fds; - struct timeval now, wait; + struct timeval now, tvwait; struct timezone tz; int cc = 0; socklen_t fromlen = sizeof(*fromp); @@ -561,12 +553,12 @@ wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp) FD_ZERO(&fds); FD_SET(sock, &fds); - wait.tv_sec = tp->tv_sec + waittime; - wait.tv_usec = tp->tv_usec; + tvwait.tv_sec = tp->tv_sec + waittime; + tvwait.tv_usec = tp->tv_usec; (void)gettimeofday(&now, &tz); - tvsub(&wait, &now); + tvsub(&tvwait, &now); - if (select(sock + 1, &fds, NULL, NULL, &wait) > 0) + if (select(sock + 1, &fds, NULL, NULL, &tvwait) > 0) cc = recvfrom(sock, (char *)packet, sizeof(packet), 0, (struct sockaddr *)fromp, &fromlen); @@ -576,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; /* @@ -597,7 +589,7 @@ in_cksum(u_short *addr, int len) /* mop up an odd byte, if necessary */ if (nleft == 1) - sum += *(u_char *)w; + sum += *(unsigned char *)w; /* * add back carry outs from top 16 bits to low 16 bits @@ -626,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; } @@ -636,24 +628,24 @@ send_probe(int seq, int ttl, struct timeval *tp) outdata->ttl = ttl; memcpy(&outdata->tv, tp, sizeof(outdata->tv)); -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP if (useicmp) outicmp->icmp_seq = htons(seq); else #endif outudp->dest = htons(port + seq); -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 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; } else #endif - if (doipcksum) { + if (doipcksum) { /* Checksum (we must save and restore ip header) */ tip = *outip; ui = (struct udpiphdr *)outip; @@ -665,20 +657,20 @@ 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; } -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#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) { @@ -690,7 +682,7 @@ send_probe(int seq, int ttl, struct timeval *tp) if (packlen & 1) { if ((i % 8) == 0) printf("\n\t"); - printf(" %02x", *(u_char *)sp); + printf(" %02x", *(unsigned char *)sp); } printf("]\n"); } @@ -709,7 +701,7 @@ send_probe(int seq, int ttl, struct timeval *tp) if (cc < 0) bb_perror_msg_and_die("sendto"); printf("%s: wrote %s %d chars, ret=%d\n", - bb_applet_name, hostname, packlen, cc); + applet_name, hostname, packlen, cc); (void)fflush(stdout); } } @@ -724,12 +716,12 @@ deltaT(struct timeval *t1p, struct timeval *t2p) return dt; } -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#if ENABLE_FEATURE_TRACEROUTE_VERBOSE /* * Convert an ICMP "type" field to a printable string. */ static inline const char * -pr_type(u_char t) +pr_type(unsigned char t) { static const char * const ttab[] = { "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", @@ -747,17 +739,17 @@ pr_type(u_char t) #endif static int -packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) +packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq) { struct icmp *icp; - u_char type, code; + unsigned char type, code; int hlen; struct ip *ip; ip = (struct ip *) buf; hlen = ip->ip_hl << 2; if (cc < hlen + ICMP_MINLEN) { -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf("packet too short (%d bytes) from %s\n", cc, inet_ntoa(from->sin_addr)); @@ -781,7 +773,7 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) hip = &icp->icmp_ip; hlen = hip->ip_hl << 2; -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP if (useicmp) { struct icmp *hicmp; @@ -791,7 +783,7 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) icp->icmp_seq == htons(seq)) return -2; - hicmp = (struct icmp *)((u_char *)hip + hlen); + hicmp = (struct icmp *)((unsigned char *)hip + hlen); /* XXX 8 is a magic number */ if (hlen + 8 <= cc && hip->ip_p == IPPROTO_ICMP && @@ -800,8 +792,8 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) return (type == ICMP_TIMXCEED ? -1 : code + 1); } else #endif - { - up = (struct udphdr *)((u_char *)hip + hlen); + { + up = (struct udphdr *)((unsigned char *)hip + hlen); /* XXX 8 is a magic number */ if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP && @@ -810,10 +802,10 @@ packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq) return (type == ICMP_TIMXCEED ? -1 : code + 1); } } -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#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", @@ -840,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); @@ -851,7 +844,7 @@ inetname(struct sockaddr_in *from) } static inline void -print(u_char *buf, int cc, struct sockaddr_in *from) +print(unsigned char *buf, int cc, struct sockaddr_in *from) { struct ip *ip; int hlen; @@ -861,7 +854,7 @@ print(u_char *buf, int cc, struct sockaddr_in *from) cc -= hlen; inetname(from); -#ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE +#if ENABLE_FEATURE_TRACEROUTE_VERBOSE if (verbose) printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); #endif @@ -875,14 +868,14 @@ gethostinfo(const char *host) struct hostent *hp; struct hostinfo *hi; char **p; - u_int32_t addr, *ap; + uint32_t addr, *ap; - hi = xcalloc(1, sizeof(*hi)); + hi = xzalloc(sizeof(*hi)); addr = inet_addr(host); - if ((int32_t)addr != -1) { - hi->name = bb_xstrdup(host); + if (addr != 0xffffffff) { + hi->name = xstrdup(host); hi->n = 1; - hi->addrs = xcalloc(1, sizeof(hi->addrs[0])); + hi->addrs = xzalloc(sizeof(hi->addrs[0])); hi->addrs[0] = addr; return hi; } @@ -890,11 +883,11 @@ gethostinfo(const char *host) hp = xgethostbyname(host); if (hp->h_addrtype != AF_INET || hp->h_length != 4) bb_perror_msg_and_die("bad host %s", host); - hi->name = bb_xstrdup(hp->h_name); + hi->name = xstrdup(hp->h_name); for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p) continue; hi->n = n; - hi->addrs = xcalloc(n, sizeof(hi->addrs[0])); + hi->addrs = xzalloc(n * sizeof(hi->addrs[0])); for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p) memcpy(ap, *p, sizeof(*ap)); return hi; @@ -903,17 +896,15 @@ gethostinfo(const char *host) static void freehostinfo(struct hostinfo *hi) { - if (hi->name != NULL) { - free(hi->name); - hi->name = NULL; - } + free(hi->name); + hi->name = NULL; free((char *)hi->addrs); free((char *)hi); } -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE +#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; @@ -924,116 +915,100 @@ 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) { int code, n; - char *cp; - u_char *outp; - u_int32_t *ap; - struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom; - struct sockaddr_in *to = (struct sockaddr_in *)&whereto; + unsigned char *outp; + uint32_t *ap; + struct sockaddr_in *from; + struct sockaddr_in *to; struct hostinfo *hi; - int on = 1; - struct protoent *pe; int ttl, probe, i; int seq = 0; int tos = 0; - char *tos_str = NULL; - char *source = NULL; - unsigned long op; - -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE + 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; - int uid = getuid(); - 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; -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE + char *first_ttl_str; +#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE llist_t *sourse_route_list = NULL; #endif - opterr = 0; -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE - bb_opt_complementally = "x-x:g*"; + 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 - bb_opt_complementally = "x-x"; + opt_complementary = "x-x"; #endif - op = bb_getopt_ulflags(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 */ - -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE + op = getopt32(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:" +#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 -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE - , &sourse_route_list + , &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 #endif ); - if(op & USAGE_OP_DONT_FRAGMNT) + if (op & OPT_DONT_FRAGMNT) off = IP_DF; -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP - useicmp = op & USAGE_OP_USE_ICMP; -#endif - nflag = op & USAGE_OP_ADDR_NUM; -#ifdef CONFIG_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"); + bb_error_msg("warning: ip checksums disabled"); } - if (tos_str) - tos = str2val(tos_str, "tos", 0, 255); - if(max_ttl_str) - max_ttl = str2val(max_ttl_str, "max ttl", 1, 255); - if(port_str) - port = (u_short)str2val(port_str, "port", 1, (1 << 16) - 1); - if(nprobes_str) - nprobes = str2val(optarg, "nprobes", 1, -1); - if(source) { - /* - * set the ip source address of the outbound - * probe (e.g., on a multi-homed host). - */ - if (uid) - bb_error_msg_and_die("-s %s: Permission denied", source); + 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 (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(waittime_str) - waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60); - if(pausemsecs_str) - pausemsecs = str2val(pausemsecs_str, "pause msecs", 0, 60 * 60 * 1000); - if(first_ttl_str) - first_ttl = str2val(first_ttl_str, "first ttl", 1, 255); - -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE - if(sourse_route_list) { + 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); + bb_error_msg_and_die("no more than %d gateways", NGATEWAYS); getaddr(gwlist + lsrr, l_sr->data); ++lsrr; l_sr = l_sr->link; @@ -1052,7 +1027,7 @@ traceroute_main(int argc, char *argv[]) minpacket = sizeof(*outip) + sizeof(*outdata) + optlen; -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP if (useicmp) minpacket += 8; /* XXX magic number */ else @@ -1064,8 +1039,7 @@ traceroute_main(int argc, char *argv[]) switch (argc - optind) { case 2: - packlen = str2val(argv[optind + 1], - "packet length", minpacket, maxpacket); + packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket); /* Fall through */ case 1: @@ -1073,8 +1047,7 @@ traceroute_main(int argc, char *argv[]) hi = gethostinfo(hostname); setsin(to, hi->addrs[0]); if (hi->n > 1) - bb_error_msg( - "Warning: %s has multiple addresses; using %s", + bb_error_msg("warning: %s has multiple addresses; using %s", hostname, inet_ntoa(to->sin_addr)); hostname = hi->name; hi->name = NULL; @@ -1085,39 +1058,26 @@ traceroute_main(int argc, char *argv[]) bb_show_usage(); } - cp = "icmp"; - if ((pe = getprotobyname(cp)) == NULL) - bb_perror_msg_and_die("unknown protocol %s", cp); - - /* Insure the socket fds won't be 0, 1 or 2 */ - do n = bb_xopen(devnull, O_RDONLY); while (n < 2); - if (n > 2) - close(n); + /* Ensure the socket fds won't be 0, 1 or 2 */ + bb_sanitize_stdio(); - if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) - bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); + s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); -#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) - (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)); +#if TRACEROUTE_SO_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) - (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 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); - if (sndsock < 0) - bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket); + sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); -#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE +#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE #if defined(IP_OPTIONS) if (lsrr > 0) { - u_char optlist[MAX_IPOPTLEN]; - - cp = "ip"; - if ((pe = getprotobyname(cp)) == NULL) - bb_perror_msg_and_die("unknown protocol"); + unsigned char optlist[MAX_IPOPTLEN]; /* final hop */ gwlist[lsrr] = to->sin_addr.s_addr; @@ -1133,76 +1093,71 @@ traceroute_main(int argc, char *argv[]) optlist[3] = IPOPT_MINOFF; memcpy(optlist + 4, gwlist, i); - if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, + if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, (char *)optlist, i + sizeof(gwlist[0]))) < 0) { bb_perror_msg_and_die("IP_OPTIONS"); - } + } } #endif /* IP_OPTIONS */ #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 -#ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG - if (op & USAGE_OP_DEBUG) - (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on, - sizeof(on)); +#if TRACEROUTE_SO_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) - (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 */ - setgid(getgid()); - setuid(uid); + xsetgid(getgid()); + xsetuid(getuid()); - outip = (struct ip *)xcalloc(1, (unsigned)packlen); + outip = xzalloc(packlen); outip->ip_v = IPVERSION; if (tos_str) outip->ip_tos = tos; outip->ip_len = htons(packlen); outip->ip_off = htons(off); - outp = (u_char *)(outip + 1); + outp = (unsigned char *)(outip + 1); outip->ip_dst = to->sin_addr; - outip->ip_hl = (outp - (u_char *)outip) >> 2; + outip->ip_hl = (outp - (unsigned char *)outip) >> 2; ident = (getpid() & 0xffff) | 0x8000; -#ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP +#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); } @@ -1210,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 { @@ -1238,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); @@ -1260,19 +1212,17 @@ traceroute_main(int argc, char *argv[]) outip->ip_src = from->sin_addr; #ifndef IP_HDRINCL - if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) { - bb_perror_msg_and_die("bind"); - } + 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; @@ -1304,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)