summaryrefslogtreecommitdiffhomepage
path: root/networking/ping.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-02-09 17:32:16 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-02-09 17:32:16 +0000
commit9ca26d38c513c918cf88db8fef057b7ae5c133f0 (patch)
tree59a8c81de0d3631aca6303adc506363e2807f270 /networking/ping.c
parentd244c5eaf80677bc785ada68d4bb805cdf2d4505 (diff)
ping: support -I addr in family neutral manner; reuse a bit of common code
Diffstat (limited to 'networking/ping.c')
-rw-r--r--networking/ping.c72
1 files changed, 30 insertions, 42 deletions
diff --git a/networking/ping.c b/networking/ping.c
index e76584341..9bf38130e 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -254,7 +254,7 @@ static union {
struct sockaddr_in6 sin6;
#endif
} pingaddr;
-static struct sockaddr_in sourceaddr;
+static len_and_sockaddr *source_lsa;
static int pingsock = -1;
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();
pingaddr.sin = lsa->sin;
- if (sourceaddr.sin_addr.s_addr) {
- xbind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr));
- }
+ if (source_lsa)
+ xbind(pingsock, &lsa->sa, lsa->len);
/* enable broadcast pings */
setsockopt_broadcast(pingsock);
@@ -572,13 +571,6 @@ static void ping4(len_and_sockaddr *lsa)
sockopt = 48 * 1024; /* explain why 48k? */
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);
/* start the ping's going ... */
@@ -615,9 +607,9 @@ static void ping6(len_and_sockaddr *lsa)
pingsock = create_icmp6_socket();
pingaddr.sin6 = lsa->sin6;
- //if (sourceaddr.sin_addr.s_addr) {
- // xbind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr));
- //}
+ /* untested whether "-I addr" really works for IPv6: */
+ if (source_lsa)
+ xbind(pingsock, &lsa->sa, lsa->len);
#ifdef ICMP6_FILTER
{
@@ -652,8 +644,6 @@ static void ping6(len_and_sockaddr *lsa)
if (if_index)
pingaddr.sin6.sin6_scope_id = if_index;
- printf("PING %s (%s): %d data bytes\n", hostname, dotted, datalen);
-
signal(SIGINT, pingstats);
/* start the ping's going ... */
@@ -695,25 +685,21 @@ static void ping6(len_and_sockaddr *lsa)
}
#endif
-/* TODO: consolidate ether-wake.c, dnsd.c, ifupdown.c, nslookup.c
- * 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)
+static void ping(len_and_sockaddr *lsa)
{
- char dummy;
- unsigned i1, i2, i3, i4;
- if (sscanf(str, "%u.%u.%u.%u%c",
- &i1, &i2, &i3, &i4, &dummy) == 4
- && ( (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;
+ printf("PING %s (%s)", hostname, dotted);
+ if (source_lsa) {
+ printf(" from %s",
+ xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len));
}
- 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);
@@ -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_I) { // -I
if_index = if_nametoindex(opt_I);
- if (!if_index)
- if (parse_nipquad(opt_I, &sourceaddr))
- bb_show_usage();
+ if (!if_index) {
+ /* TODO: I'm not sure it takes IPv6 unless in [XX:XX..] format */
+ /* (ping doesn't support source IPv6 addresses yet anyway) */
+ source_lsa = xdotted2sockaddr(opt_I, 0);
+ }
}
myid = (int16_t) getpid();
hostname = argv[optind];
@@ -747,13 +735,13 @@ int ping_main(int argc, char **argv)
#else
lsa = xhost_and_af2sockaddr(hostname, 0, AF_INET);
#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);
-#if ENABLE_PING6
- if (lsa->sa.sa_family == AF_INET6)
- ping6(lsa);
- else
-#endif
- ping4(lsa);
+ ping(lsa);
pingstats(0);
return EXIT_SUCCESS;
}