traceroute: set IP_PKTINFO to see correct local IP of received pkt (fixes -v display)
Also, assorted code shrink: function old new delta traceroute_init 1210 1172 -38 common_traceroute_main 2141 2091 -50 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-88) Total: -88 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
cc55bbef75
commit
df5c5394b0
@ -413,7 +413,6 @@ struct globals {
|
|||||||
#define port (G.port )
|
#define port (G.port )
|
||||||
#define waittime (G.waittime )
|
#define waittime (G.waittime )
|
||||||
#define recv_pkt (G.recv_pkt )
|
#define recv_pkt (G.recv_pkt )
|
||||||
#define gwlist (G.gwlist )
|
|
||||||
#define INIT_G() do { \
|
#define INIT_G() do { \
|
||||||
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
|
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -683,12 +682,15 @@ packet4_ok(int read_len, int seq)
|
|||||||
int i;
|
int i;
|
||||||
uint32_t *lp = (uint32_t *)&icp->icmp_ip;
|
uint32_t *lp = (uint32_t *)&icp->icmp_ip;
|
||||||
|
|
||||||
printf("\n%d bytes from %s",
|
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));
|
read_len,
|
||||||
/* Two separate printf() because inet_ntoa() returns static string */
|
/* inet_ntoa(G.from_lsa->u.sin.sin_addr) - two calls of inet_ntoa()
|
||||||
printf(" to %s: icmp type %d (%s) code %d\n",
|
* are unsafe (use the same buffer), using this instead:
|
||||||
|
*/
|
||||||
|
auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
|
||||||
inet_ntoa(ip->ip_dst),
|
inet_ntoa(ip->ip_dst),
|
||||||
type, pr_type(type), icp->icmp_code);
|
type, pr_type(type), icp->icmp_code
|
||||||
|
);
|
||||||
for (i = 4; i < read_len; i += sizeof(*lp))
|
for (i = 4; i < read_len; i += sizeof(*lp))
|
||||||
printf("%2d: x%8.8x\n", i, *lp++);
|
printf("%2d: x%8.8x\n", i, *lp++);
|
||||||
}
|
}
|
||||||
@ -756,19 +758,16 @@ packet6_ok(int read_len, int seq)
|
|||||||
# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
char pa[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + 4];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
p = (unsigned char *) (icp + 1);
|
p = (unsigned char *) (icp + 1);
|
||||||
|
|
||||||
printf("\n%d bytes from %s",
|
printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",
|
||||||
read_len,
|
read_len,
|
||||||
inet_ntop(AF_INET6, &G.from_lsa->u.sin6.sin6_addr, pa, sizeof(pa)));
|
auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa)),
|
||||||
/* Two printf() instead of one - reuse string constants */
|
auto_string(xmalloc_sockaddr2dotted_noport(G.to)),
|
||||||
printf(" to %s: icmp type %d (%s) code %d\n",
|
type, pr_type(type), icp->icmp6_code
|
||||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)G.to)->sin6_addr, pa, sizeof(pa)),
|
);
|
||||||
type, pr_type(type), icp->icmp6_code);
|
|
||||||
|
|
||||||
read_len -= sizeof(struct icmp6_hdr);
|
read_len -= sizeof(struct icmp6_hdr);
|
||||||
for (i = 0; i < read_len; i++) {
|
for (i = 0; i < read_len; i++) {
|
||||||
if (i % 16 == 0)
|
if (i % 16 == 0)
|
||||||
@ -796,55 +795,36 @@ packet_ok(int read_len, int seq)
|
|||||||
|
|
||||||
#else /* !ENABLE_TRACEROUTE6 */
|
#else /* !ENABLE_TRACEROUTE6 */
|
||||||
|
|
||||||
static ALWAYS_INLINE int
|
# define packet_ok(read_len, seq) packet4_ok(read_len, seq)
|
||||||
packet_ok(int read_len, int seq)
|
|
||||||
{
|
|
||||||
return packet4_ok(read_len, seq);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Construct an Internet address representation.
|
|
||||||
* If the -n flag has been supplied, give
|
|
||||||
* numeric value, otherwise try for symbolic name.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
print_inetname(const struct sockaddr *from)
|
print(int read_len)
|
||||||
{
|
{
|
||||||
char *ina = xmalloc_sockaddr2dotted_noport(from);
|
char *ina = auto_string(xmalloc_sockaddr2dotted_noport(&G.from_lsa->u.sa));
|
||||||
|
|
||||||
if (option_mask32 & OPT_ADDR_NUM) {
|
if (option_mask32 & OPT_ADDR_NUM) {
|
||||||
printf(" %s", ina);
|
printf(" %s", ina);
|
||||||
} else {
|
} else {
|
||||||
char *n = NULL;
|
char *n = NULL;
|
||||||
|
if (G.from_lsa->u.sa.sa_family != AF_INET
|
||||||
if (from->sa_family != AF_INET
|
|| G.from_lsa->u.sin.sin_addr.s_addr != INADDR_ANY
|
||||||
|| ((struct sockaddr_in*)from)->sin_addr.s_addr != INADDR_ANY
|
|
||||||
) {
|
) {
|
||||||
/* Try to reverse resolve if it is not 0.0.0.0 */
|
/* Try to reverse resolve if it is not 0.0.0.0 */
|
||||||
n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
|
n = auto_string(xmalloc_sockaddr2host_noport(&G.from_lsa->u.sa));
|
||||||
}
|
}
|
||||||
printf(" %s (%s)", (n ? n : ina), ina);
|
printf(" %s (%s)", (n ? n : ina), ina);
|
||||||
free(n);
|
|
||||||
}
|
}
|
||||||
free(ina);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print(int read_len)
|
|
||||||
{
|
|
||||||
print_inetname(&G.from_lsa->u.sa);
|
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
char *ina = xmalloc_sockaddr2dotted_noport(G.to);
|
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
/* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
|
/* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
|
||||||
* return the entire IP packet (IOW: they do not strip IP header).
|
* return the entire IP packet (IOW: they do not strip IP header).
|
||||||
* Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6
|
* Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6
|
||||||
* header and return only ICMP6 packet. Weird.
|
* header and return only ICMP6 packet. Weird.
|
||||||
*/
|
*/
|
||||||
if (G.to->sa_family == AF_INET6) {
|
if (G.from_lsa->u.sa.sa_family == AF_INET6) {
|
||||||
/* read_len -= sizeof(struct ip6_hdr); - WRONG! */
|
/* read_len -= sizeof(struct ip6_hdr); - WRONG! */
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@ -852,8 +832,9 @@ print(int read_len)
|
|||||||
struct ip *ip4packet = (struct ip*)recv_pkt;
|
struct ip *ip4packet = (struct ip*)recv_pkt;
|
||||||
read_len -= ip4packet->ip_hl << 2;
|
read_len -= ip4packet->ip_hl << 2;
|
||||||
}
|
}
|
||||||
printf(" %d bytes to %s", read_len, ina);
|
printf(" %d bytes to %s", read_len,
|
||||||
free(ina);
|
auto_string(xmalloc_sockaddr2dotted_noport(G.to))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,10 +851,6 @@ print_delta_ms(unsigned t1p, unsigned t2p)
|
|||||||
static NOINLINE void
|
static NOINLINE void
|
||||||
traceroute_init(int op, char **argv)
|
traceroute_init(int op, char **argv)
|
||||||
{
|
{
|
||||||
int minpacket;
|
|
||||||
#ifdef IP_TOS
|
|
||||||
int tos = 0;
|
|
||||||
#endif
|
|
||||||
char *source;
|
char *source;
|
||||||
char *device;
|
char *device;
|
||||||
char *tos_str;
|
char *tos_str;
|
||||||
@ -911,10 +888,6 @@ traceroute_init(int op, char **argv)
|
|||||||
#if 0 /* IGNORED */
|
#if 0 /* IGNORED */
|
||||||
if (op & OPT_IP_CHKSUM)
|
if (op & OPT_IP_CHKSUM)
|
||||||
bb_error_msg("warning: ip checksums disabled");
|
bb_error_msg("warning: ip checksums disabled");
|
||||||
#endif
|
|
||||||
#ifdef IP_TOS
|
|
||||||
if (op & OPT_TOS)
|
|
||||||
tos = xatou_range(tos_str, 0, 255);
|
|
||||||
#endif
|
#endif
|
||||||
if (op & OPT_MAX_TTL)
|
if (op & OPT_MAX_TTL)
|
||||||
G.max_ttl = xatou_range(max_ttl_str, 1, 255);
|
G.max_ttl = xatou_range(max_ttl_str, 1, 255);
|
||||||
@ -930,11 +903,11 @@ traceroute_init(int op, char **argv)
|
|||||||
G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl);
|
G.first_ttl = xatou_range(first_ttl_str, 1, G.max_ttl);
|
||||||
|
|
||||||
/* Process destination and optional packet size */
|
/* Process destination and optional packet size */
|
||||||
minpacket = sizeof(struct ip)
|
packlen = sizeof(struct ip)
|
||||||
+ sizeof(struct udphdr)
|
+ sizeof(struct udphdr)
|
||||||
+ sizeof(struct outdata_t);
|
+ sizeof(struct outdata_t);
|
||||||
if (op & OPT_USE_ICMP) {
|
if (op & OPT_USE_ICMP) {
|
||||||
minpacket = 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 */
|
||||||
@ -948,11 +921,11 @@ traceroute_init(int op, char **argv)
|
|||||||
dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
|
dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
|
||||||
af = dest_lsa->u.sa.sa_family;
|
af = dest_lsa->u.sa.sa_family;
|
||||||
if (af == AF_INET6) {
|
if (af == AF_INET6) {
|
||||||
minpacket = sizeof(struct ip6_hdr)
|
packlen = sizeof(struct ip6_hdr)
|
||||||
+ sizeof(struct udphdr)
|
+ sizeof(struct udphdr)
|
||||||
+ sizeof(struct outdata6_t);
|
+ sizeof(struct outdata6_t);
|
||||||
if (op & OPT_USE_ICMP)
|
if (op & OPT_USE_ICMP)
|
||||||
minpacket = sizeof(struct ip6_hdr)
|
packlen = sizeof(struct ip6_hdr)
|
||||||
+ SIZEOF_ICMP_HDR
|
+ SIZEOF_ICMP_HDR
|
||||||
+ sizeof(struct outdata6_t);
|
+ sizeof(struct outdata6_t);
|
||||||
}
|
}
|
||||||
@ -961,19 +934,20 @@ traceroute_init(int op, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
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);
|
||||||
|
|
||||||
packlen = minpacket;
|
|
||||||
if (argv[1])
|
if (argv[1])
|
||||||
packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
|
packlen = xatoul_range(argv[1], packlen, 32 * 1024);
|
||||||
|
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (af == AF_INET6) {
|
if (af == AF_INET6) {
|
||||||
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
||||||
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why?
|
/* want recvmsg to report target local address (for -v) */
|
||||||
|
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
|
||||||
} else
|
} else
|
||||||
#endif
|
#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) */
|
||||||
|
setsockopt_1(rcvsock, IPPROTO_IP, IP_PKTINFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TRACEROUTE_SO_DEBUG
|
#if TRACEROUTE_SO_DEBUG
|
||||||
@ -1010,8 +984,10 @@ traceroute_init(int op, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef IP_TOS
|
#ifdef IP_TOS
|
||||||
if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) {
|
if (op & OPT_TOS) {
|
||||||
bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos);
|
int tos = xatou_range(tos_str, 0, 255);
|
||||||
|
if (setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0)
|
||||||
|
bb_perror_msg_and_die("setsockopt(%s,%d)", "TOS", tos);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef IP_DONTFRAG
|
#ifdef IP_DONTFRAG
|
||||||
@ -1070,7 +1046,8 @@ traceroute_init(int op, char **argv)
|
|||||||
//TODO: we can query source port we bound to,
|
//TODO: we can query source port we bound to,
|
||||||
// and check it in replies... if we care enough
|
// and check it in replies... if we care enough
|
||||||
xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
|
xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
|
||||||
free(source_lsa);
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
|
free(source_lsa);
|
||||||
}
|
}
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
else if (af == AF_INET6) {
|
else if (af == AF_INET6) {
|
||||||
@ -1087,7 +1064,8 @@ traceroute_init(int op, char **argv)
|
|||||||
/* bind our recv socket to this IP (but not port) */
|
/* bind our recv socket to this IP (but not port) */
|
||||||
set_nport(&source_lsa->u.sa, 0);
|
set_nport(&source_lsa->u.sa, 0);
|
||||||
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
||||||
free(source_lsa);
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
|
free(source_lsa);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1097,9 +1075,8 @@ traceroute_init(int op, char **argv)
|
|||||||
|
|
||||||
dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
|
dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
|
||||||
printf("traceroute to %s (%s)", argv[0], dest_str);
|
printf("traceroute to %s (%s)", argv[0], dest_str);
|
||||||
if (ENABLE_FEATURE_CLEAN_UP) {
|
if (ENABLE_FEATURE_CLEAN_UP)
|
||||||
free(dest_str);
|
free(dest_str);
|
||||||
}
|
|
||||||
|
|
||||||
if (op & OPT_SOURCE)
|
if (op & OPT_SOURCE)
|
||||||
printf(" from %s", source);
|
printf(" from %s", source);
|
||||||
|
Loading…
Reference in New Issue
Block a user