traceroute: commonalize verbose printing
function old new delta hexdump - 274 +274 traceroute_init 1172 1147 -25 pr_type 79 - -79 common_traceroute_main 2091 1785 -306 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 0/2 up/down: 274/-410) Total: -136 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
df5c5394b0
commit
e76f03b267
@ -358,7 +358,11 @@ enum {
|
||||
OPT_IPV4 = (1 << 17), /* 4 */
|
||||
OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
|
||||
};
|
||||
#define verbose (option_mask32 & OPT_VERBOSE)
|
||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
# define verbose (option_mask32 & OPT_VERBOSE)
|
||||
#else
|
||||
# define verbose 0
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SIZEOF_ICMP_HDR = 8,
|
||||
@ -559,9 +563,7 @@ send_probe(int seq, int ttl)
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
/*
|
||||
* Convert an ICMP "type" field to a printable string.
|
||||
*/
|
||||
/* Convert an ICMP "type" field to a printable string */
|
||||
static const char *
|
||||
pr_type(unsigned char t)
|
||||
{
|
||||
@ -594,12 +596,35 @@ pr_type(unsigned char t)
|
||||
|
||||
return ttab[t];
|
||||
}
|
||||
static void
|
||||
hexdump(const struct icmp *icp, int len)
|
||||
{
|
||||
const unsigned char *p;
|
||||
int i;
|
||||
|
||||
printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
|
||||
len,
|
||||
auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
|
||||
auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
|
||||
icp->icmp_type, pr_type(icp->icmp_type),
|
||||
icp->icmp_code
|
||||
);
|
||||
p = (const void *)icp;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 16 == 0)
|
||||
printf("%04x:", i);
|
||||
if (i % 4 == 0)
|
||||
bb_putchar(' ');
|
||||
printf("%02x", p[i]);
|
||||
if ((i % 16 == 15) && (i + 1 < len))
|
||||
bb_putchar('\n');
|
||||
}
|
||||
bb_putchar('\n');
|
||||
}
|
||||
#else
|
||||
# define hexdump(...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
#define packet4_ok(read_len, from, seq) \
|
||||
packet4_ok(read_len, seq)
|
||||
#endif
|
||||
static int
|
||||
packet4_ok(int read_len, int seq)
|
||||
{
|
||||
@ -616,11 +641,9 @@ packet4_ok(int read_len, int seq)
|
||||
|
||||
hlen = ip->ip_hl << 2;
|
||||
if (read_len < hlen + ICMP_MINLEN) {
|
||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
if (verbose)
|
||||
printf("packet too short (%d bytes) from %s\n", read_len,
|
||||
inet_ntoa(G.from_lsa->u.sin.sin_addr));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
read_len -= hlen;
|
||||
@ -677,24 +700,8 @@ packet4_ok(int read_len, int seq)
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
if (verbose) {
|
||||
int i;
|
||||
uint32_t *lp = (uint32_t *)&icp->icmp_ip;
|
||||
|
||||
printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
|
||||
read_len,
|
||||
/* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa()
|
||||
* are unsafe (use the same buffer), using this instead:
|
||||
*/
|
||||
auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
|
||||
inet_ntoa(ip->ip_dst),
|
||||
type, pr_type(type), icp->icmp_code
|
||||
);
|
||||
for (i = 4; i < read_len; i += sizeof(*lp))
|
||||
printf("%2d: x%8.8x\n", i, *lp++);
|
||||
}
|
||||
#endif
|
||||
if (verbose)
|
||||
hexdump(icp, read_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -754,34 +761,9 @@ packet6_ok(int read_len, int seq)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||
if (verbose) {
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
p = (unsigned char *) (icp + 1);
|
||||
|
||||
printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
|
||||
read_len,
|
||||
auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
|
||||
auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
|
||||
type, pr_type(type), icp->icmp6_code
|
||||
);
|
||||
read_len -= sizeof(struct icmp6_hdr);
|
||||
for (i = 0; i < read_len; i++) {
|
||||
if (i % 16 == 0)
|
||||
printf("%04x:", i);
|
||||
if (i % 4 == 0)
|
||||
bb_putchar(' ');
|
||||
printf("%02x", p[i]);
|
||||
if ((i % 16 == 15) && (i + 1 < read_len))
|
||||
bb_putchar('\n');
|
||||
}
|
||||
bb_putchar('\n');
|
||||
}
|
||||
# endif
|
||||
|
||||
if (verbose)
|
||||
/* cast is safe since the beginning of icmp4 and icmp6 layouts match */
|
||||
hexdump((const struct icmp *)icp, read_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -910,7 +892,7 @@ traceroute_init(int op, char **argv)
|
||||
packlen = sizeof(struct ip)
|
||||
+ SIZEOF_ICMP_HDR
|
||||
+ sizeof(struct outdata_t);
|
||||
port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */
|
||||
port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL! */
|
||||
}
|
||||
#if ENABLE_TRACEROUTE6
|
||||
af = AF_UNSPEC;
|
||||
@ -932,23 +914,24 @@ traceroute_init(int op, char **argv)
|
||||
#else
|
||||
dest_lsa = xhost2sockaddr(argv[0], port);
|
||||
#endif
|
||||
//TODO: make sure af == AF_INET[6]? (FEATURE_UNIX_LOCAL=y allows "local:/PATH" to be translated to AF_UNIX)
|
||||
G.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
|
||||
G.to = xzalloc(dest_lsa->len);
|
||||
if (argv[1])
|
||||
packlen = xatoul_range(argv[1], packlen, 32 * 1024);
|
||||
|
||||
#if ENABLE_TRACEROUTE6
|
||||
if (af == AF_INET6) {
|
||||
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
||||
/* want recvmsg to report target local address (for -v) */
|
||||
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (af == AF_INET) {
|
||||
xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
|
||||
/* want recvmsg to report target local address (for -v) */
|
||||
setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO);
|
||||
}
|
||||
#if ENABLE_TRACEROUTE6
|
||||
else {
|
||||
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
||||
/* want recvmsg to report target local address (for -v) */
|
||||
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TRACEROUTE_SO_DEBUG
|
||||
if (op & OPT_DEBUG)
|
||||
@ -959,22 +942,22 @@ traceroute_init(int op, char **argv)
|
||||
|
||||
{
|
||||
int snd;
|
||||
if (af == AF_INET) {
|
||||
if (op & OPT_USE_ICMP)
|
||||
snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
else
|
||||
snd = xsocket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
#if ENABLE_TRACEROUTE6
|
||||
if (af == AF_INET6) {
|
||||
else {
|
||||
if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
|
||||
bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
|
||||
if (op & OPT_USE_ICMP)
|
||||
snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
else
|
||||
snd = xsocket(AF_INET6, SOCK_DGRAM, 0);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (op & OPT_USE_ICMP)
|
||||
snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
else
|
||||
snd = xsocket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
#endif
|
||||
xmove_fd(snd, sndsock);
|
||||
}
|
||||
|
||||
@ -1006,7 +989,7 @@ traceroute_init(int op, char **argv)
|
||||
ident = getpid();
|
||||
|
||||
outdata = (void*)(outudp + 1);
|
||||
if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
|
||||
if (af == AF_INET) {
|
||||
if (op & OPT_USE_ICMP) {
|
||||
outicmp->icmp_type = ICMP_ECHO;
|
||||
/*outicmp->icmp_code = 0; - set by xzalloc */
|
||||
@ -1015,7 +998,7 @@ traceroute_init(int op, char **argv)
|
||||
}
|
||||
}
|
||||
#if ENABLE_TRACEROUTE6
|
||||
if (af == AF_INET6) {
|
||||
else {
|
||||
outdata = (void*)(outudp6 + 1);
|
||||
if (op & OPT_USE_ICMP) {
|
||||
outicmp6->icmp_type = ICMP6_ECHO_REQUEST;
|
||||
@ -1048,26 +1031,22 @@ traceroute_init(int op, char **argv)
|
||||
xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
free(source_lsa);
|
||||
}
|
||||
#if ENABLE_TRACEROUTE6
|
||||
else if (af == AF_INET6) {
|
||||
//TODO: why we don't do it for IPv4?
|
||||
} else {
|
||||
len_and_sockaddr *source_lsa;
|
||||
|
||||
set_nport(&dest_lsa->u.sa, htons(port));
|
||||
/* Connect makes kernel pick source IP and port */
|
||||
/* Connect makes kernel pick source IP (and port if UDP) */
|
||||
xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len);
|
||||
/* Read IP and port */
|
||||
source_lsa = get_sock_lsa(sndsock);
|
||||
if (source_lsa == NULL)
|
||||
bb_simple_error_msg_and_die("can't get probe addr");
|
||||
/* bind our recv socket to this IP (but not port) */
|
||||
set_nport(&source_lsa->u.sa, 0);
|
||||
bb_simple_perror_msg_and_die("getsockname");
|
||||
/* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */
|
||||
//set_nport(&source_lsa->u.sa, 0); - paranoia, seems to work without this for both ipv4 and ipv6
|
||||
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
free(source_lsa);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Revert to non-privileged user after opening sockets */
|
||||
xsetgid(getgid());
|
||||
|
Loading…
Reference in New Issue
Block a user