diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-02 16:17:30 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-02 16:17:30 +0000 |
commit | 2cbe6e6eb237a8f51139be4d450997a0317ec593 (patch) | |
tree | 30bc665ee14823b8a6d34e309a14655d24b6eb93 /networking/ping.c | |
parent | db7f2e5881b9ae40896d7660cd2f2446f514c72d (diff) | |
download | busybox-w32-2cbe6e6eb237a8f51139be4d450997a0317ec593.tar.gz busybox-w32-2cbe6e6eb237a8f51139be4d450997a0317ec593.tar.bz2 busybox-w32-2cbe6e6eb237a8f51139be4d450997a0317ec593.zip |
ping: implement -I option
Diffstat (limited to 'networking/ping.c')
-rw-r--r-- | networking/ping.c | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/networking/ping.c b/networking/ping.c index 967a3e378..18fb926ad 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -155,6 +155,7 @@ int ping_main(int argc, char **argv) | |||
155 | #else /* ! CONFIG_FEATURE_FANCY_PING */ | 155 | #else /* ! CONFIG_FEATURE_FANCY_PING */ |
156 | /* full(er) version */ | 156 | /* full(er) version */ |
157 | static struct sockaddr_in pingaddr; | 157 | static struct sockaddr_in pingaddr; |
158 | static struct sockaddr_in sourceaddr; | ||
158 | static int pingsock = -1; | 159 | static int pingsock = -1; |
159 | static int datalen; /* intentionally uninitialized to work around gcc bug */ | 160 | static int datalen; /* intentionally uninitialized to work around gcc bug */ |
160 | 161 | ||
@@ -264,16 +265,15 @@ static void unpack(char *buf, int sz, struct sockaddr_in *from) | |||
264 | 265 | ||
265 | gettimeofday(&tv, NULL); | 266 | gettimeofday(&tv, NULL); |
266 | 267 | ||
267 | /* check IP header */ | ||
268 | iphdr = (struct iphdr *) buf; | ||
269 | hlen = iphdr->ihl << 2; | ||
270 | /* discard if too short */ | 268 | /* discard if too short */ |
271 | if (sz < (datalen + ICMP_MINLEN)) | 269 | if (sz < (datalen + ICMP_MINLEN)) |
272 | return; | 270 | return; |
273 | 271 | ||
272 | /* check IP header */ | ||
273 | iphdr = (struct iphdr *) buf; | ||
274 | hlen = iphdr->ihl << 2; | ||
274 | sz -= hlen; | 275 | sz -= hlen; |
275 | icmppkt = (struct icmp *) (buf + hlen); | 276 | icmppkt = (struct icmp *) (buf + hlen); |
276 | |||
277 | if (icmppkt->icmp_id != myid) | 277 | if (icmppkt->icmp_id != myid) |
278 | return; /* not our ping */ | 278 | return; /* not our ping */ |
279 | 279 | ||
@@ -329,12 +329,17 @@ static void ping(const char *host) | |||
329 | 329 | ||
330 | pingsock = create_icmp_socket(); | 330 | pingsock = create_icmp_socket(); |
331 | 331 | ||
332 | if (sourceaddr.sin_addr.s_addr) { | ||
333 | if (bind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr)) == -1) | ||
334 | bb_error_msg_and_die("could not bind to address"); | ||
335 | } | ||
336 | |||
332 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); | 337 | memset(&pingaddr, 0, sizeof(struct sockaddr_in)); |
333 | 338 | ||
334 | pingaddr.sin_family = AF_INET; | 339 | pingaddr.sin_family = AF_INET; |
335 | hostent = xgethostbyname(host); | 340 | hostent = xgethostbyname(host); |
336 | if (hostent->h_addrtype != AF_INET) | 341 | if (hostent->h_addrtype != AF_INET) |
337 | bb_error_msg_and_die("unknown address type; only AF_INET is currently supported."); | 342 | bb_error_msg_and_die("unknown address type; only AF_INET is currently supported"); |
338 | 343 | ||
339 | memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr)); | 344 | memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr)); |
340 | 345 | ||
@@ -348,10 +353,14 @@ static void ping(const char *host) | |||
348 | setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt, | 353 | setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt, |
349 | sizeof(sockopt)); | 354 | sizeof(sockopt)); |
350 | 355 | ||
351 | printf("PING %s (%s): %d data bytes\n", | 356 | printf("PING %s (%s)", |
352 | hostent->h_name, | 357 | hostent->h_name, |
353 | inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr), | 358 | inet_ntoa(*(struct in_addr *) &pingaddr.sin_addr.s_addr)); |
354 | datalen); | 359 | if (sourceaddr.sin_addr.s_addr) { |
360 | printf(" from %s", | ||
361 | inet_ntoa(*(struct in_addr *) &sourceaddr.sin_addr.s_addr)); | ||
362 | } | ||
363 | printf(": %d data bytes\n", datalen); | ||
355 | 364 | ||
356 | signal(SIGINT, pingstats); | 365 | signal(SIGINT, pingstats); |
357 | 366 | ||
@@ -378,6 +387,27 @@ static void ping(const char *host) | |||
378 | pingstats(0); | 387 | pingstats(0); |
379 | } | 388 | } |
380 | 389 | ||
390 | /* TODO: consolidate ether-wake.c, dnsd.c, ifupdown.c, nslookup.c | ||
391 | * versions of below thing. BTW we have far too many "%u.%u.%u.%u" too... | ||
392 | */ | ||
393 | static int parse_nipquad(const char *str, struct sockaddr_in* addr) | ||
394 | { | ||
395 | char dummy; | ||
396 | unsigned i1, i2, i3, i4; | ||
397 | if (sscanf(str, "%u.%u.%u.%u%c", | ||
398 | &i1, &i2, &i3, &i4, &dummy) == 4 | ||
399 | && ( (i1|i2|i3|i4) <= 0xff ) | ||
400 | ) { | ||
401 | uint8_t* ptr = (uint8_t*)&addr->sin_addr; | ||
402 | ptr[0] = i1; | ||
403 | ptr[1] = i2; | ||
404 | ptr[2] = i3; | ||
405 | ptr[3] = i4; | ||
406 | return 0; | ||
407 | } | ||
408 | return 1; /* error */ | ||
409 | } | ||
410 | |||
381 | int ping_main(int argc, char **argv) | 411 | int ping_main(int argc, char **argv) |
382 | { | 412 | { |
383 | char *thisarg; | 413 | char *thisarg; |
@@ -386,7 +416,6 @@ int ping_main(int argc, char **argv) | |||
386 | 416 | ||
387 | argc--; | 417 | argc--; |
388 | argv++; | 418 | argv++; |
389 | options = 0; | ||
390 | /* Parse any options */ | 419 | /* Parse any options */ |
391 | while (argc >= 1 && **argv == '-') { | 420 | while (argc >= 1 && **argv == '-') { |
392 | thisarg = *argv; | 421 | thisarg = *argv; |
@@ -407,6 +436,18 @@ int ping_main(int argc, char **argv) | |||
407 | argv++; | 436 | argv++; |
408 | datalen = atoi(*argv); | 437 | datalen = atoi(*argv); |
409 | break; | 438 | break; |
439 | case 'I': | ||
440 | if (--argc <= 0) | ||
441 | bb_show_usage(); | ||
442 | argv++; | ||
443 | /* ping6 accepts iface too: | ||
444 | if_index = if_nametoindex(*argv); | ||
445 | if (!if_index) ... | ||
446 | make it true for ping too. TODO. | ||
447 | */ | ||
448 | if (parse_nipquad(*argv, &sourceaddr)) | ||
449 | bb_show_usage(); | ||
450 | break; | ||
410 | default: | 451 | default: |
411 | bb_show_usage(); | 452 | bb_show_usage(); |
412 | } | 453 | } |