diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-09 20:32:16 +0300 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-02-09 20:32:16 +0300 |
commit | 9ca26d38c513c918cf88db8fef057b7ae5c133f0 (patch) | |
tree | 59a8c81de0d3631aca6303adc506363e2807f270 /networking | |
parent | d244c5eaf80677bc785ada68d4bb805cdf2d4505 (diff) |
ping: support -I addr in family neutral manner; reuse a bit of common code
Diffstat (limited to 'networking')
-rw-r--r-- | networking/ping.c | 72 |
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; } |