ping: support -I addr in family neutral manner; reuse a bit of common code
This commit is contained in:
parent
d244c5eaf8
commit
9ca26d38c5
@ -321,6 +321,7 @@ int xconnect_stream(const len_and_sockaddr *lsa);
|
|||||||
len_and_sockaddr* host2sockaddr(const char *host, int port);
|
len_and_sockaddr* host2sockaddr(const char *host, int port);
|
||||||
/* Version which dies on error */
|
/* Version which dies on error */
|
||||||
len_and_sockaddr* xhost2sockaddr(const char *host, int port);
|
len_and_sockaddr* xhost2sockaddr(const char *host, int port);
|
||||||
|
len_and_sockaddr* xdotted2sockaddr(const char *host, int port);
|
||||||
#if ENABLE_FEATURE_IPV6
|
#if ENABLE_FEATURE_IPV6
|
||||||
/* Same, useful if you want to force family (e.g. IPv6) */
|
/* Same, useful if you want to force family (e.g. IPv6) */
|
||||||
len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af);
|
len_and_sockaddr* host_and_af2sockaddr(const char *host, int port, sa_family_t af);
|
||||||
|
@ -2428,9 +2428,10 @@
|
|||||||
#define ping_full_usage \
|
#define ping_full_usage \
|
||||||
"Send ICMP ECHO_REQUEST packets to network hosts" \
|
"Send ICMP ECHO_REQUEST packets to network hosts" \
|
||||||
"\n\nOptions:\n" \
|
"\n\nOptions:\n" \
|
||||||
|
" -4, -6 Force IPv4 or IPv6 hostname resolution\n" \
|
||||||
" -c CNT Send only CNT pings\n" \
|
" -c CNT Send only CNT pings\n" \
|
||||||
" -s SIZE Send SIZE data bytes in packets (default=56)\n" \
|
" -s SIZE Send SIZE data bytes in packets (default=56)\n" \
|
||||||
" -I IP Use IP as source address\n" \
|
" -I iface/IP Use interface or IP address as source\n" \
|
||||||
" -q Quiet mode, only displays output at start\n" \
|
" -q Quiet mode, only displays output at start\n" \
|
||||||
" and when finished"
|
" and when finished"
|
||||||
#define ping6_trivial_usage \
|
#define ping6_trivial_usage \
|
||||||
@ -2440,6 +2441,7 @@
|
|||||||
"\n\nOptions:\n" \
|
"\n\nOptions:\n" \
|
||||||
" -c CNT Send only CNT pings\n" \
|
" -c CNT Send only CNT pings\n" \
|
||||||
" -s SIZE Send SIZE data bytes in packets (default=56)\n" \
|
" -s SIZE Send SIZE data bytes in packets (default=56)\n" \
|
||||||
|
" -I iface/IP Use interface or IP address as source\n" \
|
||||||
" -q Quiet mode, only displays output at start\n" \
|
" -q Quiet mode, only displays output at start\n" \
|
||||||
" and when finished"
|
" and when finished"
|
||||||
#endif
|
#endif
|
||||||
|
@ -203,7 +203,7 @@ len_and_sockaddr* xhost2sockaddr(const char *host, int port)
|
|||||||
return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR);
|
return str2sockaddr(host, port, AF_UNSPEC, DIE_ON_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static len_and_sockaddr* xdotted2sockaddr(const char *host, int port)
|
len_and_sockaddr* xdotted2sockaddr(const char *host, int port)
|
||||||
{
|
{
|
||||||
return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR);
|
return str2sockaddr(host, port, AF_UNSPEC, AI_NUMERICHOST | DIE_ON_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ static union {
|
|||||||
struct sockaddr_in6 sin6;
|
struct sockaddr_in6 sin6;
|
||||||
#endif
|
#endif
|
||||||
} pingaddr;
|
} pingaddr;
|
||||||
static struct sockaddr_in sourceaddr;
|
static len_and_sockaddr *source_lsa;
|
||||||
static int pingsock = -1;
|
static int pingsock = -1;
|
||||||
static unsigned datalen; /* intentionally uninitialized to work around gcc bug */
|
static unsigned datalen; /* intentionally uninitialized to work around gcc bug */
|
||||||
|
|
||||||
@ -561,9 +561,8 @@ static void ping4(len_and_sockaddr *lsa)
|
|||||||
|
|
||||||
pingsock = create_icmp_socket();
|
pingsock = create_icmp_socket();
|
||||||
pingaddr.sin = lsa->sin;
|
pingaddr.sin = lsa->sin;
|
||||||
if (sourceaddr.sin_addr.s_addr) {
|
if (source_lsa)
|
||||||
xbind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr));
|
xbind(pingsock, &lsa->sa, lsa->len);
|
||||||
}
|
|
||||||
|
|
||||||
/* enable broadcast pings */
|
/* enable broadcast pings */
|
||||||
setsockopt_broadcast(pingsock);
|
setsockopt_broadcast(pingsock);
|
||||||
@ -572,13 +571,6 @@ static void ping4(len_and_sockaddr *lsa)
|
|||||||
sockopt = 48 * 1024; /* explain why 48k? */
|
sockopt = 48 * 1024; /* explain why 48k? */
|
||||||
setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
|
setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
|
||||||
|
|
||||||
printf("PING %s (%s)", hostname, dotted);
|
|
||||||
if (sourceaddr.sin_addr.s_addr) {
|
|
||||||
printf(" from %s",
|
|
||||||
inet_ntoa(*(struct in_addr *) &sourceaddr.sin_addr.s_addr));
|
|
||||||
}
|
|
||||||
printf(": %d data bytes\n", datalen);
|
|
||||||
|
|
||||||
signal(SIGINT, pingstats);
|
signal(SIGINT, pingstats);
|
||||||
|
|
||||||
/* start the ping's going ... */
|
/* start the ping's going ... */
|
||||||
@ -615,9 +607,9 @@ static void ping6(len_and_sockaddr *lsa)
|
|||||||
|
|
||||||
pingsock = create_icmp6_socket();
|
pingsock = create_icmp6_socket();
|
||||||
pingaddr.sin6 = lsa->sin6;
|
pingaddr.sin6 = lsa->sin6;
|
||||||
//if (sourceaddr.sin_addr.s_addr) {
|
/* untested whether "-I addr" really works for IPv6: */
|
||||||
// xbind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr));
|
if (source_lsa)
|
||||||
//}
|
xbind(pingsock, &lsa->sa, lsa->len);
|
||||||
|
|
||||||
#ifdef ICMP6_FILTER
|
#ifdef ICMP6_FILTER
|
||||||
{
|
{
|
||||||
@ -652,8 +644,6 @@ static void ping6(len_and_sockaddr *lsa)
|
|||||||
if (if_index)
|
if (if_index)
|
||||||
pingaddr.sin6.sin6_scope_id = if_index;
|
pingaddr.sin6.sin6_scope_id = if_index;
|
||||||
|
|
||||||
printf("PING %s (%s): %d data bytes\n", hostname, dotted, datalen);
|
|
||||||
|
|
||||||
signal(SIGINT, pingstats);
|
signal(SIGINT, pingstats);
|
||||||
|
|
||||||
/* start the ping's going ... */
|
/* start the ping's going ... */
|
||||||
@ -695,25 +685,21 @@ static void ping6(len_and_sockaddr *lsa)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: consolidate ether-wake.c, dnsd.c, ifupdown.c, nslookup.c
|
static void ping(len_and_sockaddr *lsa)
|
||||||
* versions of below thing. BTW we have far too many "%u.%u.%u.%u" too...
|
|
||||||
*/
|
|
||||||
static int parse_nipquad(const char *str, struct sockaddr_in* addr)
|
|
||||||
{
|
{
|
||||||
char dummy;
|
printf("PING %s (%s)", hostname, dotted);
|
||||||
unsigned i1, i2, i3, i4;
|
if (source_lsa) {
|
||||||
if (sscanf(str, "%u.%u.%u.%u%c",
|
printf(" from %s",
|
||||||
&i1, &i2, &i3, &i4, &dummy) == 4
|
xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len));
|
||||||
&& ( (i1|i2|i3|i4) <= 0xff )
|
|
||||||
) {
|
|
||||||
uint8_t* ptr = (uint8_t*)&addr->sin_addr;
|
|
||||||
ptr[0] = i1;
|
|
||||||
ptr[1] = i2;
|
|
||||||
ptr[2] = i3;
|
|
||||||
ptr[3] = i4;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1; /* error */
|
printf(": %d data bytes\n", datalen);
|
||||||
|
|
||||||
|
#if ENABLE_PING6
|
||||||
|
if (lsa->sa.sa_family == AF_INET6)
|
||||||
|
ping6(lsa);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ping4(lsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ping_main(int argc, char **argv);
|
int ping_main(int argc, char **argv);
|
||||||
@ -732,9 +718,11 @@ int ping_main(int argc, char **argv)
|
|||||||
if (option_mask32 & OPT_s) datalen = xatou16(opt_s); // -s
|
if (option_mask32 & OPT_s) datalen = xatou16(opt_s); // -s
|
||||||
if (option_mask32 & OPT_I) { // -I
|
if (option_mask32 & OPT_I) { // -I
|
||||||
if_index = if_nametoindex(opt_I);
|
if_index = if_nametoindex(opt_I);
|
||||||
if (!if_index)
|
if (!if_index) {
|
||||||
if (parse_nipquad(opt_I, &sourceaddr))
|
/* TODO: I'm not sure it takes IPv6 unless in [XX:XX..] format */
|
||||||
bb_show_usage();
|
/* (ping doesn't support source IPv6 addresses yet anyway) */
|
||||||
|
source_lsa = xdotted2sockaddr(opt_I, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
myid = (int16_t) getpid();
|
myid = (int16_t) getpid();
|
||||||
hostname = argv[optind];
|
hostname = argv[optind];
|
||||||
@ -747,13 +735,13 @@ int ping_main(int argc, char **argv)
|
|||||||
#else
|
#else
|
||||||
lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
|
lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (source_lsa && source_lsa->sa.sa_family != lsa->sa.sa_family)
|
||||||
|
/* leaking it here... */
|
||||||
|
source_lsa = NULL;
|
||||||
|
|
||||||
dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len);
|
dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len);
|
||||||
#if ENABLE_PING6
|
ping(lsa);
|
||||||
if (lsa->sa.sa_family == AF_INET6)
|
|
||||||
ping6(lsa);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
ping4(lsa);
|
|
||||||
pingstats(0);
|
pingstats(0);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user