Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/ping PR bin/36997 Zafer Aydogan: ping doesn't validate ...



details:   https://anonhg.NetBSD.org/src/rev/9910ac1b622b
branches:  trunk
changeset: 349660:9910ac1b622b
user:      dholland <dholland%NetBSD.org@localhost>
date:      Sun Dec 18 01:19:34 2016 +0000

description:
PR bin/36997 Zafer Aydogan: ping doesn't validate numeric inputs enough.

Reject packet intervals < 1 ns as they lead to infinite loops adding
zero timespecs.

Fix the behind-schedule behavior so it doesn't spend all its time in
that loop adding very small timespecs. Try ping -c 500 -i 0.000000001
to see this in action with the old ping.

diffstat:

 sbin/ping/ping.c |  39 +++++++++++++++++++++++++++++++++------
 1 files changed, 33 insertions(+), 6 deletions(-)

diffs (74 lines):

diff -r bfd20b098aee -r 9910ac1b622b sbin/ping/ping.c
--- a/sbin/ping/ping.c  Sun Dec 18 00:21:33 2016 +0000
+++ b/sbin/ping/ping.c  Sun Dec 18 01:19:34 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ping.c,v 1.113 2016/12/18 00:21:33 dholland Exp $      */
+/*     $NetBSD: ping.c,v 1.114 2016/12/18 01:19:34 dholland Exp $      */
 
 /*
  * Copyright (c) 1989, 1993
@@ -58,7 +58,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: ping.c,v 1.113 2016/12/18 00:21:33 dholland Exp $");
+__RCSID("$NetBSD: ping.c,v 1.114 2016/12/18 01:19:34 dholland Exp $");
 #endif
 
 #include <stdio.h>
@@ -461,6 +461,9 @@
                errx(EXIT_FAILURE, "Must be superuser to use -l");
 #endif
        sec_to_timespec(interval, &interval_tv);
+       if (interval_tv.tv_sec == 0 && interval_tv.tv_nsec == 0) {
+               errx(EXIT_FAILURE, "Packet interval must be at least 1 ns");
+       }
 
        if ((pingflags & (F_AUDIBLE|F_FLOOD)) == (F_AUDIBLE|F_FLOOD))
                warnx("Sorry, no audible output for flood pings");
@@ -893,6 +896,8 @@
 {
        struct tv32 tv32;
        int i, cc, sw;
+       double waittime;
+       long numskip;
 
        opack_icmp.icmp_code = 0;
        opack_icmp.icmp_seq = htons((u_int16_t)(ntransmitted));
@@ -976,10 +981,32 @@
         * If we are at most 100 ms behind, send extras to get caught up.
         * Otherwise, skip packets we were too slow to send.
         */
-       if (diffsec(&next_tx, &now) <= interval) {
-               do {
-                       timespecadd(&next_tx, &interval_tv, &next_tx);
-               } while (diffsec(&next_tx, &now) < -0.1);
+       waittime = diffsec(&next_tx, &now);
+       if (waittime < -1.0) {
+               /* very behind - forget about being precise */
+               next_tx.tv_sec += (int)(-waittime);
+       } else if (waittime < -0.1) {
+               /* behind - skip a few */
+               if (interval_tv.tv_sec == 0) {
+                       numskip = (long)(-waittime / interval_tv.tv_nsec);
+                       next_tx.tv_nsec += numskip * interval_tv.tv_nsec;
+                       /*
+                        * We can add at most one second's worth, but allow
+                        * for tv_nsec reaching 2 billion just in case FP
+                        * issues strike.
+                        */
+                       while (next_tx.tv_nsec >= 1000000000) {
+                               next_tx.tv_sec++;
+                               next_tx.tv_nsec -= 1000000000;
+                       }
+               } else {
+                       do {
+                               timespecadd(&next_tx, &interval_tv, &next_tx);
+                       } while (diffsec(&next_tx, &now) < -0.1);
+               }
+
+       } else if (waittime <= interval) {
+               timespecadd(&next_tx, &interval_tv, &next_tx);
        }
 
        if (pingflags & F_FLOOD)



Home | Main Index | Thread Index | Old Index