diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-18 08:55:57 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-18 08:55:57 +0000 |
commit | 7679145cfa61e41099645bdeecb6a8c2743c6772 (patch) | |
tree | f130799bb1bd2f0721cb832c2dcee92b8d80c2ce /networking/ping.c | |
parent | ebd27aabaab98bef2f2d0fe0d7bf4261e5c3ffcd (diff) | |
download | busybox-w32-7679145cfa61e41099645bdeecb6a8c2743c6772.tar.gz busybox-w32-7679145cfa61e41099645bdeecb6a8c2743c6772.tar.bz2 busybox-w32-7679145cfa61e41099645bdeecb6a8c2743c6772.zip |
ping: fix write-after-allocated-mem bug
ping: use monotonic_us instead of gettimeofday: smaller code and
needs only 4 bytes in the packet
ping: display roundtrip times with 1/1000th of ms, not 1/10 ms precision.
wget: small optimization
function old new delta
pingstats 243 259 +16
sendping6 98 93 -5
sendping4 183 178 -5
.rodata 129715 129707 -8
progressmeter 867 855 -12
unpack_tail 320 272 -48
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/5 up/down: 16/-78) Total: -62 bytes
Diffstat (limited to 'networking/ping.c')
-rw-r--r-- | networking/ping.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/networking/ping.c b/networking/ping.c index e94b7914f..c4a498cd8 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -242,8 +242,8 @@ struct globals { | |||
242 | int if_index; | 242 | int if_index; |
243 | unsigned long ntransmitted, nreceived, nrepeats, pingcount; | 243 | unsigned long ntransmitted, nreceived, nrepeats, pingcount; |
244 | uint16_t myid; | 244 | uint16_t myid; |
245 | unsigned tmin, tmax; | 245 | unsigned tmin, tmax; /* in us */ |
246 | unsigned long tsum; | 246 | unsigned long long tsum; /* in us, sum of all times */ |
247 | const char *hostname; | 247 | const char *hostname; |
248 | const char *dotted; | 248 | const char *dotted; |
249 | union { | 249 | union { |
@@ -301,11 +301,13 @@ static void pingstats(int junk ATTRIBUTE_UNUSED) | |||
301 | if (ntransmitted) | 301 | if (ntransmitted) |
302 | ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; | 302 | ntransmitted = (ntransmitted - nreceived) * 100 / ntransmitted; |
303 | printf("%lu%% packet loss\n", ntransmitted); | 303 | printf("%lu%% packet loss\n", ntransmitted); |
304 | if (tmin != UINT_MAX) | 304 | if (tmin != UINT_MAX) { |
305 | printf("round-trip min/avg/max = %u.%u/%lu.%lu/%u.%u ms\n", | 305 | unsigned tavg = tsum / (nreceived + nrepeats); |
306 | tmin / 10, tmin % 10, | 306 | printf("round-trip min/avg/max = %u.%03u/%u.%03u/%u.%03u ms\n", |
307 | (tsum / (nreceived + nrepeats)) / 10, | 307 | tmin / 1000, tmin % 1000, |
308 | (tsum / (nreceived + nrepeats)) % 10, tmax / 10, tmax % 10); | 308 | tavg / 1000, tavg % 1000, |
309 | tmax / 1000, tmax % 1000); | ||
310 | } | ||
309 | exit(nreceived == 0); /* (nreceived == 0) is true (1) -- 'failure' */ | 311 | exit(nreceived == 0); /* (nreceived == 0) is true (1) -- 'failure' */ |
310 | } | 312 | } |
311 | 313 | ||
@@ -334,7 +336,9 @@ static void sendping_tail(void (*sp)(int), const void *pkt, int size_pkt) | |||
334 | 336 | ||
335 | static void sendping4(int junk ATTRIBUTE_UNUSED) | 337 | static void sendping4(int junk ATTRIBUTE_UNUSED) |
336 | { | 338 | { |
337 | struct icmp *pkt = alloca(datalen + ICMP_MINLEN); | 339 | /* +4 reserves a place for timestamp, which may end up sitting |
340 | * *after* packet. Saves one if() */ | ||
341 | struct icmp *pkt = alloca(datalen + ICMP_MINLEN + 4); | ||
338 | 342 | ||
339 | pkt->icmp_type = ICMP_ECHO; | 343 | pkt->icmp_type = ICMP_ECHO; |
340 | pkt->icmp_code = 0; | 344 | pkt->icmp_code = 0; |
@@ -342,10 +346,9 @@ static void sendping4(int junk ATTRIBUTE_UNUSED) | |||
342 | pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ | 346 | pkt->icmp_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ |
343 | pkt->icmp_id = myid; | 347 | pkt->icmp_id = myid; |
344 | 348 | ||
345 | // I can't fucking believe someone thought it's okay to do it like this... | 349 | /* We don't do hton, because we will read it back on the same machine */ |
346 | // where's hton? Where is a provision for different word size, structure padding, etc?? | 350 | /*if (datalen >= 4)*/ |
347 | // FIXME! | 351 | *(uint32_t*)&pkt->icmp_dun = monotonic_us(); |
348 | gettimeofday((struct timeval *) &pkt->icmp_dun, NULL); | ||
349 | 352 | ||
350 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); | 353 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); |
351 | 354 | ||
@@ -354,7 +357,7 @@ static void sendping4(int junk ATTRIBUTE_UNUSED) | |||
354 | #if ENABLE_PING6 | 357 | #if ENABLE_PING6 |
355 | static void sendping6(int junk ATTRIBUTE_UNUSED) | 358 | static void sendping6(int junk ATTRIBUTE_UNUSED) |
356 | { | 359 | { |
357 | struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr)); | 360 | struct icmp6_hdr *pkt = alloca(datalen + sizeof(struct icmp6_hdr) + 4); |
358 | 361 | ||
359 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; | 362 | pkt->icmp6_type = ICMP6_ECHO_REQUEST; |
360 | pkt->icmp6_code = 0; | 363 | pkt->icmp6_code = 0; |
@@ -362,8 +365,8 @@ static void sendping6(int junk ATTRIBUTE_UNUSED) | |||
362 | pkt->icmp6_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ | 365 | pkt->icmp6_seq = htons(ntransmitted); /* don't ++ here, it can be a macro */ |
363 | pkt->icmp6_id = myid; | 366 | pkt->icmp6_id = myid; |
364 | 367 | ||
365 | // FIXME! | 368 | /*if (datalen >= 4)*/ |
366 | gettimeofday((struct timeval *) &pkt->icmp6_data8[4], NULL); | 369 | *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); |
367 | 370 | ||
368 | sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr)); | 371 | sendping_tail(sendping6, pkt, datalen + sizeof(struct icmp6_hdr)); |
369 | } | 372 | } |
@@ -417,7 +420,7 @@ static const char *icmp6_type_name(int id) | |||
417 | } | 420 | } |
418 | #endif | 421 | #endif |
419 | 422 | ||
420 | static void unpack_tail(int sz, struct timeval *tp, | 423 | static void unpack_tail(int sz, uint32_t *tp, |
421 | const char *from_str, | 424 | const char *from_str, |
422 | uint16_t recv_seq, int ttl) | 425 | uint16_t recv_seq, int ttl) |
423 | { | 426 | { |
@@ -427,17 +430,9 @@ static void unpack_tail(int sz, struct timeval *tp, | |||
427 | ++nreceived; | 430 | ++nreceived; |
428 | 431 | ||
429 | if (tp) { | 432 | if (tp) { |
430 | struct timeval tv; | 433 | /* (int32_t) cast is for hypothetical 64-bit unsigned */ |
431 | 434 | /* (doesn't hurt 32-bit real-world anyway) */ | |
432 | gettimeofday(&tv, NULL); | 435 | triptime = (int32_t) ((uint32_t)monotonic_us() - *tp); |
433 | tv.tv_usec -= tp->tv_usec; | ||
434 | if (tv.tv_usec < 0) { | ||
435 | --tv.tv_sec; | ||
436 | tv.tv_usec += 1000000; | ||
437 | } | ||
438 | tv.tv_sec -= tp->tv_sec; | ||
439 | |||
440 | triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); | ||
441 | tsum += triptime; | 436 | tsum += triptime; |
442 | if (triptime < tmin) | 437 | if (triptime < tmin) |
443 | tmin = triptime; | 438 | tmin = triptime; |
@@ -459,7 +454,7 @@ static void unpack_tail(int sz, struct timeval *tp, | |||
459 | printf("%d bytes from %s: seq=%u ttl=%d", sz, | 454 | printf("%d bytes from %s: seq=%u ttl=%d", sz, |
460 | from_str, recv_seq, ttl); | 455 | from_str, recv_seq, ttl); |
461 | if (tp) | 456 | if (tp) |
462 | printf(" time=%u.%u ms", triptime / 10, triptime % 10); | 457 | printf(" time=%u.%03u ms", triptime / 1000, triptime % 1000); |
463 | puts(dupmsg); | 458 | puts(dupmsg); |
464 | fflush(stdout); | 459 | fflush(stdout); |
465 | } | 460 | } |
@@ -483,10 +478,10 @@ static void unpack4(char *buf, int sz, struct sockaddr_in *from) | |||
483 | 478 | ||
484 | if (icmppkt->icmp_type == ICMP_ECHOREPLY) { | 479 | if (icmppkt->icmp_type == ICMP_ECHOREPLY) { |
485 | uint16_t recv_seq = ntohs(icmppkt->icmp_seq); | 480 | uint16_t recv_seq = ntohs(icmppkt->icmp_seq); |
486 | struct timeval *tp = NULL; | 481 | uint32_t *tp = NULL; |
487 | 482 | ||
488 | if (sz >= ICMP_MINLEN + sizeof(struct timeval)) | 483 | if (sz >= ICMP_MINLEN + sizeof(uint32_t)) |
489 | tp = (struct timeval *) icmppkt->icmp_data; | 484 | tp = (uint32_t *) icmppkt->icmp_data; |
490 | unpack_tail(sz, tp, | 485 | unpack_tail(sz, tp, |
491 | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), | 486 | inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), |
492 | recv_seq, iphdr->ttl); | 487 | recv_seq, iphdr->ttl); |
@@ -512,10 +507,10 @@ static void unpack6(char *packet, int sz, struct sockaddr_in6 *from, int hoplimi | |||
512 | 507 | ||
513 | if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { | 508 | if (icmppkt->icmp6_type == ICMP6_ECHO_REPLY) { |
514 | uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); | 509 | uint16_t recv_seq = ntohs(icmppkt->icmp6_seq); |
515 | struct timeval *tp = NULL; | 510 | uint32_t *tp = NULL; |
516 | 511 | ||
517 | if (sz >= sizeof(struct icmp6_hdr) + sizeof(struct timeval)) | 512 | if (sz >= sizeof(struct icmp6_hdr) + sizeof(uint32_t)) |
518 | tp = (struct timeval *) &icmppkt->icmp6_data8[4]; | 513 | tp = (uint32_t *) &icmppkt->icmp6_data8[4]; |
519 | unpack_tail(sz, tp, | 514 | unpack_tail(sz, tp, |
520 | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, | 515 | inet_ntop(AF_INET6, &pingaddr.sin6.sin6_addr, |
521 | buf, sizeof(buf)), | 516 | buf, sizeof(buf)), |