diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-03 00:36:35 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-03 00:36:35 +0000 |
commit | 19c238bc909d1e06a6bc70fe5f74124b64a4fa9d (patch) | |
tree | a696356bc1b8c002af41aa928bc6bf64d3832f17 /networking/ping.c | |
parent | 2110aa9ece6f30563068b2ea29bd75e6ea1787eb (diff) | |
download | busybox-w32-19c238bc909d1e06a6bc70fe5f74124b64a4fa9d.tar.gz busybox-w32-19c238bc909d1e06a6bc70fe5f74124b64a4fa9d.tar.bz2 busybox-w32-19c238bc909d1e06a6bc70fe5f74124b64a4fa9d.zip |
ping: don't measure times if ping payload is less than 8 bytes;
commonalize some ping code.
Diffstat (limited to 'networking/ping.c')
-rw-r--r-- | networking/ping.c | 180 |
1 files changed, 75 insertions, 105 deletions
diff --git a/networking/ping.c b/networking/ping.c index 4c1ec836e..bbe2c9f76 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -262,7 +262,8 @@ static int if_index; | |||
262 | 262 | ||
263 | static unsigned long ntransmitted, nreceived, nrepeats, pingcount; | 263 | static unsigned long ntransmitted, nreceived, nrepeats, pingcount; |
264 | static int myid; | 264 | static int myid; |
265 | static unsigned long tmin = ULONG_MAX, tmax, tsum; | 265 | static unsigned tmin = UINT_MAX, tmax; |
266 | static unsigned long tsum; | ||
266 | static char rcvd_tbl[MAX_DUP_CHK / 8]; | 267 | static char rcvd_tbl[MAX_DUP_CHK / 8]; |
267 | 268 | ||
268 | static const char *hostname; | 269 | static const char *hostname; |
@@ -278,8 +279,6 @@ static const char *dotted; | |||
278 | 279 | ||
279 | static void pingstats(int junk ATTRIBUTE_UNUSED) | 280 | static void pingstats(int junk ATTRIBUTE_UNUSED) |
280 | { | 281 | { |
281 | int status; | ||
282 | |||
283 | signal(SIGINT, SIG_IGN); | 282 | signal(SIGINT, SIG_IGN); |
284 | 283 | ||
285 | printf("\n--- %s ping statistics ---\n", hostname); | 284 | printf("\n--- %s ping statistics ---\n", hostname); |
@@ -290,16 +289,12 @@ static void pingstats(int junk ATTRIBUTE_UNUSED) | |||
290 | if (ntransmitted) | 289 | if (ntransmitted) |
291 | ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; | 290 | ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; |
292 | printf("%lu%% packet loss\n", ntransmitted); | 291 | printf("%lu%% packet loss\n", ntransmitted); |
293 | if (nreceived) | 292 | if (tmin != UINT_MAX) |
294 | printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n", | 293 | printf("round-trip min/avg/max = %u.%u/%lu.%lu/%u.%u ms\n", |
295 | tmin / 10, tmin % 10, | 294 | tmin / 10, tmin % 10, |
296 | (tsum / (nreceived + nrepeats)) / 10, | 295 | (tsum / (nreceived + nrepeats)) / 10, |
297 | (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10); | 296 | (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10); |
298 | if (nreceived != 0) | 297 | exit(nreceived == 0); /* (nreceived == 0) is true (1) -- 'failure' */ |
299 | status = EXIT_SUCCESS; | ||
300 | else | ||
301 | status = EXIT_FAILURE; | ||
302 | exit(status); | ||
303 | } | 298 | } |
304 | 299 | ||
305 | static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt) | 300 | static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt) |
@@ -406,15 +401,57 @@ static const char *icmp6_type_name(int id) | |||
406 | } | 401 | } |
407 | #endif | 402 | #endif |
408 | 403 | ||
404 | static void unpack_tail(int sz, struct timeval *tp, | ||
405 | const char *from_str, | ||
406 | uint16_t recv_seq, int ttl) | ||
407 | { | ||
408 | const char *dupmsg = " (DUP!)"; | ||
409 | unsigned triptime = triptime; /* for gcc */ | ||
410 | |||
411 | ++nreceived; | ||
412 | |||
413 | if (tp) { | ||
414 | struct timeval tv; | ||
415 | |||
416 | gettimeofday(&tv, NULL); | ||
417 | tv.tv_usec -= tp->tv_usec; | ||
418 | if (tv.tv_usec < 0) { | ||
419 | --tv.tv_sec; | ||
420 | tv.tv_usec += 1000000; | ||
421 | } | ||
422 | tv.tv_sec -= tp->tv_sec; | ||
423 | |||
424 | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); | ||
425 | tsum += triptime; | ||
426 | if (triptime < tmin) | ||
427 | tmin = triptime; | ||
428 | if (triptime > tmax) | ||
429 | tmax = triptime; | ||
430 | } | ||
431 | |||
432 | if (TST(recv_seq % MAX_DUP_CHK)) { | ||
433 | ++nrepeats; | ||
434 | --nreceived; | ||
435 | } else { | ||
436 | SET(recv_seq % MAX_DUP_CHK); | ||
437 | dupmsg += 7; | ||
438 | } | ||
439 | |||
440 | if (option_mask32 & OPT_QUIET) | ||
441 | return; | ||
442 | |||
443 | printf("%d bytes from %s: seq=%u ttl=%d", sz, | ||
444 | from_str, recv_seq, ttl); | ||
445 | if (tp) | ||
446 | printf(" time=%u.%u ms", triptime / 10, triptime % 10); | ||
447 | puts(dupmsg); | ||
448 | fflush(stdout); | ||
449 | } | ||
409 | static void unpack4(char *buf, int sz, struct sockaddr_in *from) | 450 | static void unpack4(char *buf, int sz, struct sockaddr_in *from) |
410 | { | 451 | { |
411 | struct icmp *icmppkt; | 452 | struct icmp *icmppkt; |
412 | struct iphdr *iphdr; | 453 | struct iphdr *iphdr; |
413 | struct timeval tv, *tp; | 454 | int hlen; |
414 | int hlen, dupflag; | ||
415 | unsigned long triptime; | ||
416 | |||
417 | gettimeofday(&tv, NULL); | ||
418 | 455 | ||
419 | /* discard if too short */ | 456 | /* discard if too short */ |
420 | if (sz < (datalen + ICMP_MINLEN)) | 457 | if (sz < (datalen + ICMP_MINLEN)) |
@@ -430,61 +467,25 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from) | |||
430 | 467 | ||
431 | if (icmppkt->icmp_type == ICMP_ECHOREPLY) { | 468 | if (icmppkt->icmp_type == ICMP_ECHOREPLY) { |
432 | uint16_t recv_seq = ntohs(icmppkt->icmp_seq); | 469 | uint16_t recv_seq = ntohs(icmppkt->icmp_seq); |
433 | ++nreceived; | 470 | struct timeval *tp = NULL; |
434 | tp = (struct timeval *) icmppkt->icmp_data; | 471 | |
435 | 472 | if (sz >= ICMP_MINLEN + sizeof(struct timeval)) | |
436 | if ((tv.tv_usec -= tp->tv_usec) < 0) { | 473 | tp = (struct timeval *) icmppkt->icmp_data; |
437 | --tv.tv_sec; | 474 | unpack_tail(sz, tp, |
438 | tv.tv_usec += 1000000; | 475 | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), |
439 | } | 476 | recv_seq, iphdr->ttl); |
440 | tv.tv_sec -= tp->tv_sec; | 477 | } else if (icmppkt->icmp_type != ICMP_ECHO) { |
441 | 478 | bb_error_msg("warning: got ICMP %d (%s)", | |
442 | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); | 479 | icmppkt->icmp_type, |
443 | tsum += triptime; | 480 | icmp_type_name(icmppkt->icmp_type)); |
444 | if (triptime < tmin) | ||
445 | tmin = triptime; | ||
446 | if (triptime > tmax) | ||
447 | tmax = triptime; | ||
448 | |||
449 | if (TST(recv_seq % MAX_DUP_CHK)) { | ||
450 | ++nrepeats; | ||
451 | --nreceived; | ||
452 | dupflag = 1; | ||
453 | } else { | ||
454 | SET(recv_seq % MAX_DUP_CHK); | ||
455 | dupflag = 0; | ||
456 | } | ||
457 | |||
458 | if (option_mask32 & OPT_QUIET) | ||
459 | return; | ||
460 | |||
461 | printf("%d bytes from %s: icmp_seq=%u", sz, | ||
462 | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), | ||
463 | recv_seq); | ||
464 | printf(" ttl=%d", iphdr->ttl); | ||
465 | printf(" time=%lu.%lu ms", triptime / 10, triptime % 10); | ||
466 | if (dupflag) | ||
467 | printf(" (DUP!)"); | ||
468 | puts(""); | ||
469 | } else { | ||
470 | if (icmppkt->icmp_type != ICMP_ECHO) | ||
471 | bb_error_msg("warning: got ICMP %d (%s)", | ||
472 | icmppkt->icmp_type, | ||
473 | icmp_type_name(icmppkt->icmp_type)); | ||
474 | } | 481 | } |
475 | fflush(stdout); | ||
476 | } | 482 | } |
477 | #if ENABLE_PING6 | 483 | #if ENABLE_PING6 |
478 | static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit) | 484 | static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimit) |
479 | { | 485 | { |
480 | struct icmp6_hdr *icmppkt; | 486 | struct icmp6_hdr *icmppkt; |
481 | struct timeval tv, *tp; | ||
482 | int dupflag; | ||
483 | unsigned long triptime; | ||
484 | char buf[INET6_ADDRSTRLEN]; | 487 | char buf[INET6_ADDRSTRLEN]; |
485 | 488 | ||
486 | gettimeofday(&tv, NULL); | ||
487 | |||
488 | /* discard if too short */ | 489 | /* discard if too short */ |
489 | if (sz < (datalen + sizeof(struct icmp6_hdr))) | 490 | if (sz < (datalen + sizeof(struct icmp6_hdr))) |
490 | return; | 491 | return; |
@@ -495,50 +496,19 @@ static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimi | |||
495 | 496 | ||
496 | if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { | 497 | if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { |
497 | uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); | 498 | uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); |
498 | ++nreceived; | 499 | struct timeval *tp = NULL; |
499 | tp = (struct timeval *) &icmppkt->icmp6_data8[4]; | 500 | |
500 | 501 | if (sz >= sizeof(struct icmp6_hdr) + sizeof(struct timeval)) | |
501 | if ((tv.tv_usec -= tp->tv_usec) < 0) { | 502 | tp = (struct timeval *) &icmppkt->icmp6_data8[4]; |
502 | --tv.tv_sec; | 503 | unpack_tail(sz, tp, |
503 | tv.tv_usec += 1000000; | 504 | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, |
504 | } | 505 | buf, sizeof(buf)), |
505 | tv.tv_sec -= tp->tv_sec; | 506 | recv_seq, hoplimit); |
506 | 507 | } else if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) { | |
507 | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); | 508 | bb_error_msg("warning: got ICMP %d (%s)", |
508 | tsum += triptime; | 509 | icmppkt->icmp6_type, |
509 | if (triptime < tmin) | 510 | icmp6_type_name(icmppkt->icmp6_type)); |
510 | tmin = triptime; | ||
511 | if (triptime > tmax) | ||
512 | tmax = triptime; | ||
513 | |||
514 | if (TST(recv_seq % MAX_DUP_CHK)) { | ||
515 | ++nrepeats; | ||
516 | --nreceived; | ||
517 | dupflag = 1; | ||
518 | } else { | ||
519 | SET(recv_seq % MAX_DUP_CHK); | ||
520 | dupflag = 0; | ||
521 | } | ||
522 | |||
523 | if (option_mask32 & OPT_QUIET) | ||
524 | return; | ||
525 | |||
526 | printf("%d bytes from %s: icmp6_seq=%u", sz, | ||
527 | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, | ||
528 | buf, sizeof(buf)), | ||
529 | recv_seq); | ||
530 | printf(" ttl=%d time=%lu.%lu ms", hoplimit, | ||
531 | triptime / 10, triptime % 10); | ||
532 | if (dupflag) | ||
533 | printf(" (DUP!)"); | ||
534 | puts(""); | ||
535 | } else { | ||
536 | if (icmppkt->icmp6_type != ICMP6_ECHO_REQUEST) | ||
537 | bb_error_msg("warning: got ICMP %d (%s)", | ||
538 | icmppkt->icmp6_type, | ||
539 | icmp6_type_name(icmppkt->icmp6_type)); | ||
540 | } | 511 | } |
541 | fflush(stdout); | ||
542 | } | 512 | } |
543 | #endif | 513 | #endif |
544 | 514 | ||