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

@ -440,7 +440,7 @@ void FAST_FUNC xlisten(int s, int backlog)
/* Die with an error message if sendto failed. /* Die with an error message if sendto failed.
* Return bytes sent otherwise */ * Return bytes sent otherwise */
ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to,
socklen_t tolen) socklen_t tolen)
{ {
ssize_t ret = sendto(s, buf, len, 0, to, tolen); ssize_t ret = sendto(s, buf, len, 0, to, tolen);

View File

@ -223,11 +223,10 @@
#define IPVERSION 4 #define IPVERSION 4
#ifndef IPPROTO_ICMP #ifndef IPPROTO_ICMP
/* Grrrr.... */ # define IPPROTO_ICMP 1
#define IPPROTO_ICMP 1
#endif #endif
#ifndef IPPROTO_IP #ifndef IPPROTO_IP
#define IPPROTO_IP 0 # define IPPROTO_IP 0
#endif #endif
/* /*
@ -482,7 +481,6 @@ ifaddrlist(struct IFADDRLIST **ipaddrp)
return nipaddr; return nipaddr;
} }
static void static void
setsin(struct sockaddr_in *addr_sin, uint32_t addr) 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; addr_sin->sin_addr.s_addr = addr;
} }
/* /*
* Return the source address for the given destination address * 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); 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 static int
wait_for_reply(int sock, struct sockaddr_in *fromp) wait_for_reply(int sock, struct sockaddr_in *fromp)
{ {
@ -581,12 +571,12 @@ in_cksum(uint16_t *addr, int len)
int sum = 0; int sum = 0;
/* /*
* Our algorithm is simple, using a 32 bit accumulator (sum), * Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold * we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower * back all the carry bits from the top 16 bits into the lower
* 16 bits. * 16 bits.
*/ */
while (nleft > 1) { while (nleft > 1) {
sum += *w++; sum += *w++;
nleft -= 2; nleft -= 2;
} }
@ -595,16 +585,13 @@ in_cksum(uint16_t *addr, int len)
if (nleft == 1) if (nleft == 1)
sum += *(unsigned char *)w; 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) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */ sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */ answer = ~sum; /* truncate to 16 bits */
return answer; return answer;
} }
static void static void
send_probe(int seq, int ttl) 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. * In most cases, the kernel will recalculate the ip checksum.
* But we must do it anyway so that the udp checksum comes out * But we must do it anyway so that the udp checksum comes out right.
* right.
*/ */
if (doipcksum) { if (doipcksum) {
outip->ip_sum = outip->ip_sum = in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
if (outip->ip_sum == 0) if (outip->ip_sum == 0)
outip->ip_sum = 0xffff; outip->ip_sum = 0xffff;
} }
@ -645,7 +630,7 @@ send_probe(int seq, int ttl)
/* Always calculate checksum for icmp packets */ /* Always calculate checksum for icmp packets */
outicmp->icmp_cksum = 0; outicmp->icmp_cksum = 0;
outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp,
packlen - (sizeof(*outip) + optlen)); packlen - (sizeof(*outip) + optlen));
if (outicmp->icmp_cksum == 0) if (outicmp->icmp_cksum == 0)
outicmp->icmp_cksum = 0xffff; outicmp->icmp_cksum = 0xffff;
} else } else
@ -656,7 +641,7 @@ send_probe(int seq, int ttl)
ui = (struct udpiphdr *)outip; ui = (struct udpiphdr *)outip;
oui = (struct udpiphdr *)&tip; oui = (struct udpiphdr *)&tip;
/* Easier to zero and put back things that are ok */ /* 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_src = oui->ui_src;
ui->ui_dst = oui->ui_dst; ui->ui_dst = oui->ui_dst;
ui->ui_pr = oui->ui_pr; ui->ui_pr = oui->ui_pr;
@ -668,7 +653,8 @@ send_probe(int seq, int ttl)
*outip = tip; *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 */ /* XXX undocumented debugging hack */
if (verbose > 1) { if (verbose > 1) {
const uint16_t *sp; const uint16_t *sp;
@ -695,15 +681,15 @@ send_probe(int seq, int ttl)
#if !defined(IP_HDRINCL) && defined(IP_TTL) #if !defined(IP_HDRINCL) && defined(IP_TTL)
if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
(char *)&ttl, sizeof(ttl)) < 0) { (char *)&ttl, sizeof(ttl)) < 0) {
bb_perror_msg_and_die("setsockopt ttl %d", ttl); bb_perror_msg_and_die("setsockopt ttl %d", ttl);
} }
#endif #endif
cc = xsendto(sndsock, (char *)outip, cc = xsendto(sndsock, outip, packlen,
packlen, (struct sockaddr *)&whereto, sizeof(whereto)); (struct sockaddr *)&whereto, sizeof(whereto));
if (cc != packlen) { 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" "Info Reply", "Mask Request", "Mask Reply"
}; };
if (t > 18) if (t >= ARRAY_SIZE(ttab))
return "OUT-OF-RANGE"; return "OUT-OF-RANGE";
return ttab[t]; return ttab[t];
@ -734,12 +720,12 @@ pr_type(unsigned char t)
packet_ok(buf, cc, seq) packet_ok(buf, cc, seq)
#endif #endif
static int 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; unsigned char type, code;
int hlen; int hlen;
struct ip *ip; const struct ip *ip;
ip = (struct ip *) buf; ip = (struct ip *) buf;
hlen = ip->ip_hl << 2; 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; type = icp->icmp_type;
code = icp->icmp_code; code = icp->icmp_code;
/* Path MTU Discovery (RFC1191) */ /* Path MTU Discovery (RFC1191) */
if (code != ICMP_UNREACH_NEEDFRAG) pmtu = 0;
pmtu = 0; if (code == ICMP_UNREACH_NEEDFRAG)
else {
pmtu = ntohs(icp->icmp_nextmtu); pmtu = ntohs(icp->icmp_nextmtu);
}
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS)
type == ICMP_UNREACH || type == ICMP_ECHOREPLY) { || type == ICMP_UNREACH
struct ip *hip; || type == ICMP_ECHOREPLY
struct udphdr *up; ) {
const struct ip *hip;
const struct udphdr *up;
hip = &icp->icmp_ip; hip = &icp->icmp_ip;
hlen = hip->ip_hl << 2; hlen = hip->ip_hl << 2;
@ -804,8 +791,9 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
printf("\n%d bytes from %s to " printf("\n%d bytes from %s to "
"%s: icmp type %d (%s) code %d\n", "%s: icmp type %d (%s) code %d\n",
cc, inet_ntoa(from->sin_addr), 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)) for (i = 4; i < cc; i += sizeof(*lp))
printf("%2d: x%8.8x\n", i, *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; return 0;
} }
/* /*
* Construct an Internet address representation. * 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. * numeric value, otherwise try for symbolic name.
*/ */
static void static void
print_inetname(struct sockaddr_in *from) print_inetname(const struct sockaddr_in *from)
{ {
const char *ina; const char *ina;
@ -837,9 +824,9 @@ print_inetname(struct sockaddr_in *from)
} }
static void 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; int hlen;
ip = (struct ip *) buf; ip = (struct ip *) buf;
@ -853,7 +840,6 @@ print(unsigned char *buf, int cc, struct sockaddr_in *from)
#endif #endif
} }
static struct hostinfo * static struct hostinfo *
gethostinfo(const char *host) gethostinfo(const char *host)
{ {
@ -910,15 +896,19 @@ static void
print_delta_ms(unsigned t1p, unsigned t2p) print_delta_ms(unsigned t1p, unsigned t2p)
{ {
unsigned tt = t2p - t1p; 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) MAIN_EXTERNALLY_VISIBLE;
int traceroute_main(int argc, char **argv) int traceroute_main(int argc, char **argv)
{ {
int code, n;
unsigned char *outp; unsigned char *outp;
uint32_t *ap;
struct sockaddr_in *from; struct sockaddr_in *from;
struct sockaddr_in *to; struct sockaddr_in *to;
struct hostinfo *hi; struct hostinfo *hi;
@ -931,7 +921,6 @@ int traceroute_main(int argc, char **argv)
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
int lsrr = 0; int lsrr = 0;
#endif #endif
uint16_t off = 0;
struct IFADDRLIST *al; struct IFADDRLIST *al;
char *device; char *device;
int max_ttl = 30; int max_ttl = 30;
@ -952,7 +941,6 @@ int traceroute_main(int argc, char **argv)
from = (struct sockaddr_in *)&wherefrom; from = (struct sockaddr_in *)&wherefrom;
to = (struct sockaddr_in *)&whereto; to = (struct sockaddr_in *)&whereto;
//opterr = 0;
#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
opt_complementary = "x-x:g::"; opt_complementary = "x-x:g::";
#else #else
@ -970,8 +958,6 @@ int traceroute_main(int argc, char **argv)
#endif #endif
); );
if (op & OPT_DONT_FRAGMNT)
off = IP_DF;
if (op & OPT_IP_CHKSUM) { if (op & OPT_IP_CHKSUM) {
doipcksum = 0; doipcksum = 0;
bb_error_msg("warning: ip checksums disabled"); 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 * set the ip source address of the outbound
* probe (e.g., on a multi-homed host). * probe (e.g., on a multi-homed host).
*/ */
if (getuid()) if (getuid() != 0)
bb_error_msg_and_die("-s %s: permission denied", source); bb_error_msg_and_die("you must be root to use -s");
} }
if (op & OPT_WAITTIME) if (op & OPT_WAITTIME)
waittime = xatou_range(waittime_str, 2, 24 * 60 * 60); waittime = xatou_range(waittime_str, 2, 24 * 60 * 60);
if (op & OPT_PAUSE_MS) if (op & OPT_PAUSE_MS)
pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000); pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000);
if (op & OPT_FIRST_TTL) 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 ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
if (source_route_list) { if (source_route_list) {
@ -1011,12 +997,6 @@ int traceroute_main(int argc, char **argv)
} }
#endif #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; minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP #if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
@ -1028,14 +1008,14 @@ int traceroute_main(int argc, char **argv)
packlen = minpacket; /* minimum sized packet */ packlen = minpacket; /* minimum sized packet */
/* Process destination and optional packet size */ /* Process destination and optional packet size */
switch (argc - optind) { argv += optind;
argc -= optind;
switch (argc) {
case 2: case 2:
packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket); packlen = xatoul_range(argv[1], minpacket, maxpacket);
/* Fall through */ /* Fall through */
case 1: case 1:
hostname = argv[optind]; hostname = argv[0];
hi = gethostinfo(hostname); hi = gethostinfo(hostname);
setsin(to, hi->addrs[0]); setsin(to, hi->addrs[0]);
if (hi->n > 1) if (hi->n > 1)
@ -1045,7 +1025,6 @@ int traceroute_main(int argc, char **argv)
hi->name = NULL; hi->name = NULL;
freehostinfo(hi); freehostinfo(hi);
break; break;
default: default:
bb_show_usage(); bb_show_usage();
} }
@ -1081,12 +1060,12 @@ int traceroute_main(int argc, char **argv)
optlist[1] = IPOPT_LSRR; optlist[1] = IPOPT_LSRR;
i = lsrr * sizeof(gwlist[0]); i = lsrr * sizeof(gwlist[0]);
optlist[2] = i + 3; optlist[2] = i + 3;
/* Pointer to LSRR addresses */ /* pointer to LSRR addresses */
optlist[3] = IPOPT_MINOFF; optlist[3] = IPOPT_MINOFF;
memcpy(optlist + 4, gwlist, i); memcpy(optlist + 4, gwlist, i);
if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, if (setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
(char *)optlist, i + sizeof(gwlist[0]))) < 0) { (char *)optlist, i + sizeof(gwlist[0])) < 0) {
bb_perror_msg_and_die("IP_OPTIONS"); bb_perror_msg_and_die("IP_OPTIONS");
} }
} }
@ -1106,7 +1085,7 @@ int traceroute_main(int argc, char **argv)
} }
#else #else
#ifdef IP_TOS #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); bb_perror_msg_and_die("setsockopt tos %d", tos);
} }
#endif #endif
@ -1127,10 +1106,11 @@ int traceroute_main(int argc, char **argv)
outip = xzalloc(packlen); outip = xzalloc(packlen);
outip->ip_v = IPVERSION; outip->ip_v = IPVERSION;
if (tos_str) if (op & OPT_TOS)
outip->ip_tos = tos; outip->ip_tos = tos;
outip->ip_len = htons(packlen); 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); outp = (unsigned char *)(outip + 1);
outip->ip_dst = to->sin_addr; outip->ip_dst = to->sin_addr;
@ -1153,12 +1133,11 @@ int traceroute_main(int argc, char **argv)
outdata = (outdata_t *)(outudp + 1); outdata = (outdata_t *)(outudp + 1);
} }
/* Get the interface address list */
n = ifaddrlist(&al);
/* Look for a specific device */ /* Look for a specific device */
if (op & OPT_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) if (strcmp(device, al->device) == 0)
goto found_dev; goto found_dev;
bb_error_msg_and_die("can't find interface %s", device); 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). * there are more than one).
*/ */
if (op & OPT_DEVICE) { if (op & OPT_DEVICE) {
uint32_t *ap;
for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
if (*ap == al->addr) if (*ap == al->addr)
goto found_dev2; goto found_dev2;
@ -1197,7 +1177,7 @@ int traceroute_main(int argc, char **argv)
if (hi->n > 1) if (hi->n > 1)
bb_error_msg( bb_error_msg(
"warning: %s has multiple addresses; using %s", "warning: %s has multiple addresses; using %s",
source, inet_ntoa(from->sin_addr)); source, inet_ntoa(from->sin_addr));
} }
freehostinfo(hi); freehostinfo(hi);
} }
@ -1211,7 +1191,6 @@ int traceroute_main(int argc, char **argv)
if (op & OPT_SOURCE) if (op & OPT_SOURCE)
printf(" from %s", source); printf(" from %s", source);
printf(", %d hops max, %d byte packets\n", max_ttl, packlen); printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
fflush(stdout);
for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
uint32_t lastaddr = 0; uint32_t lastaddr = 0;
@ -1229,17 +1208,21 @@ int traceroute_main(int argc, char **argv)
if (sentfirst && pausemsecs > 0) if (sentfirst && pausemsecs > 0)
usleep(pausemsecs * 1000); usleep(pausemsecs * 1000);
fflush(stdout);
t1 = monotonic_us(); t1 = monotonic_us();
send_probe(++seq, ttl); send_probe(++seq, ttl);
++sentfirst; ++sentfirst;
while ((cc = wait_for_reply(rcvsock, from)) != 0) { while ((cc = wait_for_reply(rcvsock, from)) != 0) {
t2 = monotonic_us(); t2 = monotonic_us();
i = packet_ok(packet, cc, from, seq); i = packet_ok(packet, cc, from, seq);
/* Skip short packet */ /* Skip short packet */
if (i == 0) if (i == 0)
continue; continue;
if (!gotlastaddr || if (!gotlastaddr
from->sin_addr.s_addr != lastaddr) { || from->sin_addr.s_addr != lastaddr
) {
print(packet, cc, from); print(packet, cc, from);
lastaddr = from->sin_addr.s_addr; lastaddr = from->sin_addr.s_addr;
++gotlastaddr; ++gotlastaddr;
@ -1251,99 +1234,86 @@ int traceroute_main(int argc, char **argv)
if (i == -2) { if (i == -2) {
if (ip->ip_ttl <= 1) if (ip->ip_ttl <= 1)
printf(" !"); printf(" !");
++got_there; got_there = 1;
break; break;
} }
/* time exceeded in transit */ /* time exceeded in transit */
if (i == -1) if (i == -1)
break; break;
code = i - 1; i--;
switch (code) { switch (i) {
case ICMP_UNREACH_PORT: case ICMP_UNREACH_PORT:
if (ip->ip_ttl <= 1) if (ip->ip_ttl <= 1)
printf(" !"); printf(" !");
++got_there; got_there = 1;
break; break;
case ICMP_UNREACH_NET: case ICMP_UNREACH_NET:
++unreachable;
printf(" !N"); printf(" !N");
++unreachable;
break; break;
case ICMP_UNREACH_HOST: case ICMP_UNREACH_HOST:
++unreachable;
printf(" !H"); printf(" !H");
++unreachable;
break; break;
case ICMP_UNREACH_PROTOCOL: case ICMP_UNREACH_PROTOCOL:
++got_there;
printf(" !P"); printf(" !P");
got_there = 1;
break; break;
case ICMP_UNREACH_NEEDFRAG: case ICMP_UNREACH_NEEDFRAG:
++unreachable;
printf(" !F-%d", pmtu); printf(" !F-%d", pmtu);
break;
case ICMP_UNREACH_SRCFAIL:
++unreachable; ++unreachable;
printf(" !S");
break; break;
case ICMP_UNREACH_SRCFAIL:
printf(" !S");
++unreachable;
break;
case ICMP_UNREACH_FILTER_PROHIB: case ICMP_UNREACH_FILTER_PROHIB:
case ICMP_UNREACH_NET_PROHIB: /* misuse */ case ICMP_UNREACH_NET_PROHIB: /* misuse */
++unreachable;
printf(" !A"); printf(" !A");
++unreachable;
break; break;
case ICMP_UNREACH_HOST_PROHIB: case ICMP_UNREACH_HOST_PROHIB:
++unreachable;
printf(" !C"); printf(" !C");
++unreachable;
break; break;
case ICMP_UNREACH_HOST_PRECEDENCE: case ICMP_UNREACH_HOST_PRECEDENCE:
++unreachable;
printf(" !V"); printf(" !V");
break;
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
++unreachable; ++unreachable;
printf(" !C");
break; break;
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
printf(" !C");
++unreachable;
break;
case ICMP_UNREACH_NET_UNKNOWN: case ICMP_UNREACH_NET_UNKNOWN:
case ICMP_UNREACH_HOST_UNKNOWN: case ICMP_UNREACH_HOST_UNKNOWN:
++unreachable;
printf(" !U"); printf(" !U");
break;
case ICMP_UNREACH_ISOLATED:
++unreachable; ++unreachable;
printf(" !I");
break; break;
case ICMP_UNREACH_ISOLATED:
printf(" !I");
++unreachable;
break;
case ICMP_UNREACH_TOSNET: case ICMP_UNREACH_TOSNET:
case ICMP_UNREACH_TOSHOST: case ICMP_UNREACH_TOSHOST:
++unreachable;
printf(" !T"); printf(" !T");
break;
default:
++unreachable; ++unreachable;
printf(" !<%d>", code); break;
default:
printf(" !<%d>", i);
++unreachable;
break; break;
} }
break; break;
} }
if (cc == 0) if (cc == 0)
printf(" *"); printf(" *");
(void)fflush(stdout);
} }
bb_putchar('\n'); bb_putchar('\n');
if (got_there || if (got_there
(unreachable > 0 && unreachable >= nprobes - 1)) || (unreachable > 0 && unreachable >= nprobes - 1)
) {
break; break;
}
} }
return 0; return 0;
} }