traceroute: preparatory trivial cleanups

function                                             old     new   delta
traceroute_main                                     3932    3713    -219
This commit is contained in:
Denis Vlasenko 2009-01-24 20:11:36 +00:00
parent 39b681343b
commit fa65a3d78f
2 changed files with 103 additions and 133 deletions

View File

@ -223,11 +223,10 @@
#define IPVERSION 4
#ifndef IPPROTO_ICMP
/* Grrrr.... */
#define IPPROTO_ICMP 1
# define IPPROTO_ICMP 1
#endif
#ifndef IPPROTO_IP
#define IPPROTO_IP 0
# define IPPROTO_IP 0
#endif
/*
@ -482,7 +481,6 @@ ifaddrlist(struct IFADDRLIST **ipaddrp)
return nipaddr;
}
static void
setsin(struct sockaddr_in *addr_sin, uint32_t addr)
{
@ -494,7 +492,6 @@ setsin(struct sockaddr_in *addr_sin, uint32_t addr)
addr_sin->sin_addr.s_addr = addr;
}
/*
* Return the source address for the given destination address
*/
@ -547,13 +544,6 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
setsin(from, al->addr);
}
/*
"Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
"\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
"\t[-w waittime] [-z pausemsecs] host [packetlen]"
*/
static int
wait_for_reply(int sock, struct sockaddr_in *fromp)
{
@ -595,16 +585,13 @@ in_cksum(uint16_t *addr, int len)
if (nleft == 1)
sum += *(unsigned char *)w;
/*
* add back carry outs from top 16 bits to low 16 bits
*/
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return answer;
}
static void
send_probe(int seq, int ttl)
{
@ -617,12 +604,10 @@ send_probe(int seq, int ttl)
/*
* In most cases, the kernel will recalculate the ip checksum.
* But we must do it anyway so that the udp checksum comes out
* right.
* But we must do it anyway so that the udp checksum comes out right.
*/
if (doipcksum) {
outip->ip_sum =
in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
outip->ip_sum = in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
if (outip->ip_sum == 0)
outip->ip_sum = 0xffff;
}
@ -656,7 +641,7 @@ send_probe(int seq, int ttl)
ui = (struct udpiphdr *)outip;
oui = (struct udpiphdr *)&tip;
/* Easier to zero and put back things that are ok */
memset((char *)ui, 0, sizeof(ui->ui_i));
memset(ui, 0, sizeof(ui->ui_i));
ui->ui_src = oui->ui_src;
ui->ui_dst = oui->ui_dst;
ui->ui_pr = oui->ui_pr;
@ -668,7 +653,8 @@ send_probe(int seq, int ttl)
*outip = tip;
}
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
//BUG! verbose is (x & OPT_VERBOSE), not a counter!
#if 0 //ENABLE_FEATURE_TRACEROUTE_VERBOSE
/* XXX undocumented debugging hack */
if (verbose > 1) {
const uint16_t *sp;
@ -700,10 +686,10 @@ send_probe(int seq, int ttl)
}
#endif
cc = xsendto(sndsock, (char *)outip,
packlen, (struct sockaddr *)&whereto, sizeof(whereto));
cc = xsendto(sndsock, outip, packlen,
(struct sockaddr *)&whereto, sizeof(whereto));
if (cc != packlen) {
bb_info_msg("wrote %s %d chars, ret=%d", hostname, packlen, cc);
bb_info_msg("sent %s %d octets, ret=%d", hostname, packlen, cc);
}
}
@ -722,7 +708,7 @@ pr_type(unsigned char t)
"Info Reply", "Mask Request", "Mask Reply"
};
if (t > 18)
if (t >= ARRAY_SIZE(ttab))
return "OUT-OF-RANGE";
return ttab[t];
@ -734,12 +720,12 @@ pr_type(unsigned char t)
packet_ok(buf, cc, seq)
#endif
static int
packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
packet_ok(const unsigned char *buf, int cc, const struct sockaddr_in *from, int seq)
{
struct icmp *icp;
const struct icmp *icp;
unsigned char type, code;
int hlen;
struct ip *ip;
const struct ip *ip;
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
@ -756,15 +742,16 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
type = icp->icmp_type;
code = icp->icmp_code;
/* Path MTU Discovery (RFC1191) */
if (code != ICMP_UNREACH_NEEDFRAG)
pmtu = 0;
else {
if (code == ICMP_UNREACH_NEEDFRAG)
pmtu = ntohs(icp->icmp_nextmtu);
}
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
struct ip *hip;
struct udphdr *up;
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS)
|| type == ICMP_UNREACH
|| type == ICMP_ECHOREPLY
) {
const struct ip *hip;
const struct udphdr *up;
hip = &icp->icmp_ip;
hlen = hip->ip_hl << 2;
@ -805,7 +792,8 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
printf("\n%d bytes from %s to "
"%s: icmp type %d (%s) code %d\n",
cc, inet_ntoa(from->sin_addr),
inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
inet_ntoa(ip->ip_dst),
type, pr_type(type), icp->icmp_code);
for (i = 4; i < cc; i += sizeof(*lp))
printf("%2d: x%8.8x\n", i, *lp++);
}
@ -813,14 +801,13 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
return 0;
}
/*
* Construct an Internet address representation.
* If the nflag has been supplied, give
* If the -n flag has been supplied, give
* numeric value, otherwise try for symbolic name.
*/
static void
print_inetname(struct sockaddr_in *from)
print_inetname(const struct sockaddr_in *from)
{
const char *ina;
@ -837,9 +824,9 @@ print_inetname(struct sockaddr_in *from)
}
static void
print(unsigned char *buf, int cc, struct sockaddr_in *from)
print(const unsigned char *buf, int cc, const struct sockaddr_in *from)
{
struct ip *ip;
const struct ip *ip;
int hlen;
ip = (struct ip *) buf;
@ -853,7 +840,6 @@ print(unsigned char *buf, int cc, struct sockaddr_in *from)
#endif
}
static struct hostinfo *
gethostinfo(const char *host)
{
@ -910,15 +896,19 @@ static void
print_delta_ms(unsigned t1p, unsigned t2p)
{
unsigned tt = t2p - t1p;
printf(" %u.%03u ms", tt/1000, tt%1000);
printf(" %u.%03u ms", tt / 1000, tt % 1000);
}
/*
"Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
"\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
"\t[-w waittime] [-z pausemsecs] host [packetlen]"
*/
int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int traceroute_main(int argc, char **argv)
{
int code, n;
unsigned char *outp;
uint32_t *ap;
struct sockaddr_in *from;
struct sockaddr_in *to;
struct hostinfo *hi;
@ -931,7 +921,6 @@ int traceroute_main(int argc, char **argv)
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
int lsrr = 0;
#endif
uint16_t off = 0;
struct IFADDRLIST *al;
char *device;
int max_ttl = 30;
@ -952,7 +941,6 @@ int traceroute_main(int argc, char **argv)
from = (struct sockaddr_in *)&wherefrom;
to = (struct sockaddr_in *)&whereto;
//opterr = 0;
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
opt_complementary = "x-x:g::";
#else
@ -970,8 +958,6 @@ int traceroute_main(int argc, char **argv)
#endif
);
if (op & OPT_DONT_FRAGMNT)
off = IP_DF;
if (op & OPT_IP_CHKSUM) {
doipcksum = 0;
bb_error_msg("warning: ip checksums disabled");
@ -989,15 +975,15 @@ int traceroute_main(int argc, char **argv)
* 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() != 0)
bb_error_msg_and_die("you must be root to use -s");
}
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);
first_ttl = xatou_range(first_ttl_str, 1, max_ttl);
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
if (source_route_list) {
@ -1011,12 +997,6 @@ int traceroute_main(int argc, char **argv)
}
#endif
if (first_ttl > max_ttl) {
bb_error_msg_and_die(
"first ttl (%d) may not be greater than max ttl (%d)",
first_ttl, max_ttl);
}
minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
@ -1028,14 +1008,14 @@ int traceroute_main(int argc, char **argv)
packlen = minpacket; /* minimum sized packet */
/* Process destination and optional packet size */
switch (argc - optind) {
argv += optind;
argc -= optind;
switch (argc) {
case 2:
packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket);
packlen = xatoul_range(argv[1], minpacket, maxpacket);
/* Fall through */
case 1:
hostname = argv[optind];
hostname = argv[0];
hi = gethostinfo(hostname);
setsin(to, hi->addrs[0]);
if (hi->n > 1)
@ -1045,7 +1025,6 @@ int traceroute_main(int argc, char **argv)
hi->name = NULL;
freehostinfo(hi);
break;
default:
bb_show_usage();
}
@ -1081,12 +1060,12 @@ int traceroute_main(int argc, char **argv)
optlist[1] = IPOPT_LSRR;
i = lsrr * sizeof(gwlist[0]);
optlist[2] = i + 3;
/* Pointer to LSRR addresses */
/* pointer to LSRR addresses */
optlist[3] = IPOPT_MINOFF;
memcpy(optlist + 4, gwlist, i);
if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
(char *)optlist, i + sizeof(gwlist[0]))) < 0) {
if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
(char *)optlist, i + sizeof(gwlist[0])) < 0) {
bb_perror_msg_and_die("IP_OPTIONS");
}
}
@ -1106,7 +1085,7 @@ int traceroute_main(int argc, char **argv)
}
#else
#ifdef IP_TOS
if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
bb_perror_msg_and_die("setsockopt tos %d", tos);
}
#endif
@ -1127,10 +1106,11 @@ int traceroute_main(int argc, char **argv)
outip = xzalloc(packlen);
outip->ip_v = IPVERSION;
if (tos_str)
if (op & OPT_TOS)
outip->ip_tos = tos;
outip->ip_len = htons(packlen);
outip->ip_off = htons(off);
if (op & OPT_DONT_FRAGMNT)
outip->ip_off = htons(IP_DF);
outp = (unsigned char *)(outip + 1);
outip->ip_dst = to->sin_addr;
@ -1153,12 +1133,11 @@ int traceroute_main(int argc, char **argv)
outdata = (outdata_t *)(outudp + 1);
}
/* Get the interface address list */
n = ifaddrlist(&al);
/* Look for a specific device */
if (op & OPT_DEVICE) {
for (i = n; i > 0; --i, ++al)
/* Get the interface address list */
int n = ifaddrlist(&al);
for (; n > 0; --n, ++al)
if (strcmp(device, al->device) == 0)
goto found_dev;
bb_error_msg_and_die("can't find interface %s", device);
@ -1185,6 +1164,7 @@ int traceroute_main(int argc, char **argv)
* there are more than one).
*/
if (op & OPT_DEVICE) {
uint32_t *ap;
for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
if (*ap == al->addr)
goto found_dev2;
@ -1211,7 +1191,6 @@ int traceroute_main(int argc, char **argv)
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;
@ -1229,17 +1208,21 @@ int traceroute_main(int argc, char **argv)
if (sentfirst && pausemsecs > 0)
usleep(pausemsecs * 1000);
fflush(stdout);
t1 = monotonic_us();
send_probe(++seq, ttl);
++sentfirst;
while ((cc = wait_for_reply(rcvsock, from)) != 0) {
t2 = monotonic_us();
i = packet_ok(packet, cc, from, seq);
/* Skip short packet */
if (i == 0)
continue;
if (!gotlastaddr ||
from->sin_addr.s_addr != lastaddr) {
if (!gotlastaddr
|| from->sin_addr.s_addr != lastaddr
) {
print(packet, cc, from);
lastaddr = from->sin_addr.s_addr;
++gotlastaddr;
@ -1251,99 +1234,86 @@ int traceroute_main(int argc, char **argv)
if (i == -2) {
if (ip->ip_ttl <= 1)
printf(" !");
++got_there;
got_there = 1;
break;
}
/* time exceeded in transit */
if (i == -1)
break;
code = i - 1;
switch (code) {
i--;
switch (i) {
case ICMP_UNREACH_PORT:
if (ip->ip_ttl <= 1)
printf(" !");
++got_there;
got_there = 1;
break;
case ICMP_UNREACH_NET:
++unreachable;
printf(" !N");
++unreachable;
break;
case ICMP_UNREACH_HOST:
++unreachable;
printf(" !H");
++unreachable;
break;
case ICMP_UNREACH_PROTOCOL:
++got_there;
printf(" !P");
got_there = 1;
break;
case ICMP_UNREACH_NEEDFRAG:
++unreachable;
printf(" !F-%d", pmtu);
break;
case ICMP_UNREACH_SRCFAIL:
++unreachable;
printf(" !S");
break;
case ICMP_UNREACH_SRCFAIL:
printf(" !S");
++unreachable;
break;
case ICMP_UNREACH_FILTER_PROHIB:
case ICMP_UNREACH_NET_PROHIB: /* misuse */
++unreachable;
printf(" !A");
++unreachable;
break;
case ICMP_UNREACH_HOST_PROHIB:
++unreachable;
printf(" !C");
++unreachable;
break;
case ICMP_UNREACH_HOST_PRECEDENCE:
++unreachable;
printf(" !V");
break;
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
++unreachable;
printf(" !C");
break;
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
printf(" !C");
++unreachable;
break;
case ICMP_UNREACH_NET_UNKNOWN:
case ICMP_UNREACH_HOST_UNKNOWN:
++unreachable;
printf(" !U");
break;
case ICMP_UNREACH_ISOLATED:
++unreachable;
printf(" !I");
break;
case ICMP_UNREACH_ISOLATED:
printf(" !I");
++unreachable;
break;
case ICMP_UNREACH_TOSNET:
case ICMP_UNREACH_TOSHOST:
++unreachable;
printf(" !T");
break;
default:
++unreachable;
printf(" !<%d>", code);
break;
default:
printf(" !<%d>", i);
++unreachable;
break;
}
break;
}
if (cc == 0)
printf(" *");
(void)fflush(stdout);
}
bb_putchar('\n');
if (got_there ||
(unreachable > 0 && unreachable >= nprobes - 1))
if (got_there
|| (unreachable > 0 && unreachable >= nprobes - 1)
) {
break;
}
}
return 0;
}