aboutsummaryrefslogtreecommitdiff
path: root/networking/ping.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-09-02 16:17:30 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-09-02 16:17:30 +0000
commit2cbe6e6eb237a8f51139be4d450997a0317ec593 (patch)
tree30bc665ee14823b8a6d34e309a14655d24b6eb93 /networking/ping.c
parentdb7f2e5881b9ae40896d7660cd2f2446f514c72d (diff)
downloadbusybox-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.c61
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 */
157static struct sockaddr_in pingaddr; 157static struct sockaddr_in pingaddr;
158static struct sockaddr_in sourceaddr;
158static int pingsock = -1; 159static int pingsock = -1;
159static int datalen; /* intentionally uninitialized to work around gcc bug */ 160static 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*/
393static 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
381int ping_main(int argc, char **argv) 411int 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 }