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_IPV4 = (1 << 17), /* 4 */
|
||||||
OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
|
OPT_IPV6 = (1 << 18) * ENABLE_TRACEROUTE6, /* 6 */
|
||||||
};
|
};
|
||||||
|
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||||
# define verbose (option_mask32 & OPT_VERBOSE)
|
# define verbose (option_mask32 & OPT_VERBOSE)
|
||||||
|
#else
|
||||||
|
# define verbose 0
|
||||||
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIZEOF_ICMP_HDR = 8,
|
SIZEOF_ICMP_HDR = 8,
|
||||||
@ -559,9 +563,7 @@ send_probe(int seq, int ttl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
#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 *
|
static const char *
|
||||||
pr_type(unsigned char t)
|
pr_type(unsigned char t)
|
||||||
{
|
{
|
||||||
@ -594,12 +596,35 @@ pr_type(unsigned char t)
|
|||||||
|
|
||||||
return ttab[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
|
#endif
|
||||||
|
|
||||||
#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
|
||||||
#define packet4_ok(read_len, from, seq) \
|
|
||||||
packet4_ok(read_len, seq)
|
|
||||||
#endif
|
|
||||||
static int
|
static int
|
||||||
packet4_ok(int read_len, int seq)
|
packet4_ok(int read_len, int seq)
|
||||||
{
|
{
|
||||||
@ -616,11 +641,9 @@ packet4_ok(int read_len, int seq)
|
|||||||
|
|
||||||
hlen = ip->ip_hl << 2;
|
hlen = ip->ip_hl << 2;
|
||||||
if (read_len < hlen + ICMP_MINLEN) {
|
if (read_len < hlen + ICMP_MINLEN) {
|
||||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf("packet too short (%d bytes) from %s\n", read_len,
|
printf("packet too short (%d bytes) from %s\n", read_len,
|
||||||
inet_ntoa(G.from_lsa->u.sin.sin_addr));
|
inet_ntoa(G.from_lsa->u.sin.sin_addr));
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
read_len -= hlen;
|
read_len -= hlen;
|
||||||
@ -677,24 +700,8 @@ packet4_ok(int read_len, int seq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
if (verbose)
|
||||||
if (verbose) {
|
hexdump(icp, read_len);
|
||||||
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
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,34 +761,9 @@ packet6_ok(int read_len, int seq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (verbose)
|
||||||
# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
/* cast is safe since the beginning of icmp4 and icmp6 layouts match */
|
||||||
if (verbose) {
|
hexdump((const struct icmp *)icp, read_len);
|
||||||
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
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,7 +892,7 @@ traceroute_init(int op, char **argv)
|
|||||||
packlen = sizeof(struct ip)
|
packlen = sizeof(struct ip)
|
||||||
+ SIZEOF_ICMP_HDR
|
+ SIZEOF_ICMP_HDR
|
||||||
+ sizeof(struct outdata_t);
|
+ 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
|
#if ENABLE_TRACEROUTE6
|
||||||
af = AF_UNSPEC;
|
af = AF_UNSPEC;
|
||||||
@ -932,23 +914,24 @@ traceroute_init(int op, char **argv)
|
|||||||
#else
|
#else
|
||||||
dest_lsa = xhost2sockaddr(argv[0], port);
|
dest_lsa = xhost2sockaddr(argv[0], port);
|
||||||
#endif
|
#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.from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
|
||||||
G.to = xzalloc(dest_lsa->len);
|
G.to = xzalloc(dest_lsa->len);
|
||||||
if (argv[1])
|
if (argv[1])
|
||||||
packlen = xatoul_range(argv[1], packlen, 32 * 1024);
|
packlen = xatoul_range(argv[1], packlen, 32 * 1024);
|
||||||
|
|
||||||
#if ENABLE_TRACEROUTE6
|
if (af == AF_INET) {
|
||||||
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
|
|
||||||
{
|
|
||||||
xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
|
xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
|
||||||
/* want recvmsg to report target local address (for -v) */
|
/* want recvmsg to report target local address (for -v) */
|
||||||
setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO);
|
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 TRACEROUTE_SO_DEBUG
|
||||||
if (op & OPT_DEBUG)
|
if (op & OPT_DEBUG)
|
||||||
@ -959,22 +942,22 @@ traceroute_init(int op, char **argv)
|
|||||||
|
|
||||||
{
|
{
|
||||||
int snd;
|
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 ENABLE_TRACEROUTE6
|
||||||
if (af == AF_INET6) {
|
else {
|
||||||
if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
|
if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
|
||||||
bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
|
bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
|
||||||
if (op & OPT_USE_ICMP)
|
if (op & OPT_USE_ICMP)
|
||||||
snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||||
else
|
else
|
||||||
snd = xsocket(AF_INET6, SOCK_DGRAM, 0);
|
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);
|
xmove_fd(snd, sndsock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,7 +989,7 @@ traceroute_init(int op, char **argv)
|
|||||||
ident = getpid();
|
ident = getpid();
|
||||||
|
|
||||||
outdata = (void*)(outudp + 1);
|
outdata = (void*)(outudp + 1);
|
||||||
if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
|
if (af == AF_INET) {
|
||||||
if (op & OPT_USE_ICMP) {
|
if (op & OPT_USE_ICMP) {
|
||||||
outicmp->icmp_type = ICMP_ECHO;
|
outicmp->icmp_type = ICMP_ECHO;
|
||||||
/*outicmp->icmp_code = 0; - set by xzalloc */
|
/*outicmp->icmp_code = 0; - set by xzalloc */
|
||||||
@ -1015,7 +998,7 @@ traceroute_init(int op, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (af == AF_INET6) {
|
else {
|
||||||
outdata = (void*)(outudp6 + 1);
|
outdata = (void*)(outudp6 + 1);
|
||||||
if (op & OPT_USE_ICMP) {
|
if (op & OPT_USE_ICMP) {
|
||||||
outicmp6->icmp_type = ICMP6_ECHO_REQUEST;
|
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);
|
xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
|
||||||
if (ENABLE_FEATURE_CLEAN_UP)
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
free(source_lsa);
|
free(source_lsa);
|
||||||
}
|
} else {
|
||||||
#if ENABLE_TRACEROUTE6
|
|
||||||
else if (af == AF_INET6) {
|
|
||||||
//TODO: why we don't do it for IPv4?
|
|
||||||
len_and_sockaddr *source_lsa;
|
len_and_sockaddr *source_lsa;
|
||||||
|
|
||||||
set_nport(&dest_lsa->u.sa, htons(port));
|
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);
|
xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len);
|
||||||
/* Read IP and port */
|
/* Read IP and port */
|
||||||
source_lsa = get_sock_lsa(sndsock);
|
source_lsa = get_sock_lsa(sndsock);
|
||||||
if (source_lsa == NULL)
|
if (source_lsa == NULL)
|
||||||
bb_simple_error_msg_and_die("can't get probe addr");
|
bb_simple_perror_msg_and_die("getsockname");
|
||||||
/* bind our recv socket to this IP (but not port) */
|
/* bind our recv ICMP socket to this IP (but not port, ICMP has no ports) */
|
||||||
set_nport(&source_lsa->u.sa, 0);
|
//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);
|
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
||||||
if (ENABLE_FEATURE_CLEAN_UP)
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
free(source_lsa);
|
free(source_lsa);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Revert to non-privileged user after opening sockets */
|
/* Revert to non-privileged user after opening sockets */
|
||||||
xsetgid(getgid());
|
xsetgid(getgid());
|
||||||
|
Loading…
Reference in New Issue
Block a user