]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
rate limit ntpdate packets to 2s interval per server to stay
authorDave Hart <hart@ntp.org>
Sun, 7 Mar 2010 20:01:29 +0000 (20:01 +0000)
committerDave Hart <hart@ntp.org>
Sun, 7 Mar 2010 20:01:29 +0000 (20:01 +0000)
  within the "restrict ... limited" default limit set by
  "discard minimum 1", plus 1s of enforcement slop.
Respect KoD rate-limiting responses from ntpd.

bk: 4b940619s_-nhP0lOxdfHzVzJKOvXg

ntpdate/ntpdate.c
ntpdate/ntpdate.h

index 082c5b089a972249855b063d7e4bcfa5609d930f..a906ae283d94e61bfdb61272b98d747df2f6c498 100644 (file)
@@ -58,7 +58,7 @@ struct timeval timeout = {0,0};
 #elif defined(SYS_WINNT)
 /*
  * Windows does not abort a select select call if SIGALRM goes off
- * so a 200 ms timeout is needed
+ * so a 200 ms timeout is needed (TIMER_HZ is 5).
  */
 struct sock_timeval timeout = {0,1000000/TIMER_HZ};
 #else
@@ -419,8 +419,18 @@ ntpdatemain (
                        } else {
                                sys_timeout = ((LFPTOFP(&tmp) * TIMER_HZ)
                                           + 0x8000) >> 16;
-                               if (sys_timeout == 0)
-                               sys_timeout = 1;
+                               /*
+                                * No less than 1s between requests to
+                                * a server to stay within ntpd's
+                                * default "discard minimum 1" (and 1s
+                                * enforcement slop).  That is enforced
+                                * only if the nondefault limited
+                                * restriction is in place, such as with
+                                * "restrict ... limited" and "restrict
+                                * ... kod limited".
+                                */
+                               if (MINTIMEOUT < sys_timeout)
+                                       sys_timeout = MINTIMEOUT;
                        }
                        break;
                case 'v':
@@ -828,6 +838,19 @@ receive(
        if (!is_authentic)
                server->trust |= 1;
 
+       /*
+        * Check for a KoD (rate limiting) response, cease and decist.
+        */
+       if (LEAP_NOTINSYNC == PKT_LEAP(rpkt->li_vn_mode) &&
+           STRATUM_PKT_UNSPEC == rpkt->stratum &&
+           !memcmp("RATE", &rpkt->refid, 4)) {
+               msyslog(LOG_ERR, "%s rate limit response from server.\n",
+                       stoa(&rbufp->recv_srcadr));
+               server->event_time = 0;
+               complete_servers++;
+               return;
+       }
+
        /*
         * Looks good.  Record info from the packet.
         */
@@ -845,8 +868,9 @@ receive(
         * Make sure the server is at least somewhat sane.      If not, try
         * again.
         */
-       if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)) {
-               transmit(server);
+       if (L_ISZERO(&rec) || !L_ISHIS(&server->org, &rec)
+           || L_ISEQU(&rec, &server->org)) {
+               server->event_time = current_time + sys_timeout;
                return;
        }
 
@@ -895,10 +919,10 @@ receive(
        }
 
        /*
-        * Shift this data in, then transmit again.
+        * Shift this data in, then schedule another transmit.
         */
        server_data(server, (s_fp) di, &ci, 0);
-       transmit(server);
+       server->event_time = current_time + sys_timeout;
 }
 
 
@@ -1346,12 +1370,16 @@ addserver(
                        /* Name server is unusable. Exit after failing on the
                           first server, in order to shorten the timeout caused
                           by waiting for resolution of several servers */
-                       fprintf(stderr, "Name server cannot be used, exiting");
-                       msyslog(LOG_ERR, "name server cannot be used, reason: %s\n", gai_strerror(error));
+                       fprintf(stderr, "Exiting, name server cannot be used: %s (%d)",
+                               gai_strerror(error), error);
+                       msyslog(LOG_ERR, "name server cannot be used: %s (%d)\n",
+                               gai_strerror(error), error);
                        exit(1);
                }
-               fprintf(stderr, "Error : %s\n", gai_strerror(error));
-               msyslog(LOG_ERR, "can't find host %s\n", serv);
+               fprintf(stderr, "Error resolving %s: %s (%d)\n", serv,
+                       gai_strerror(error), error);
+               msyslog(LOG_ERR, "Can't find host %s: %s (%d)\n", serv,
+                       gai_strerror(error), error);
                return;
        }
 #ifdef DEBUG
index 00bc3ff061d43eda082fb55d988a6cb6f717f061..75fba42910656ed693be3aabbeb131fb4a882a63 100644 (file)
@@ -91,7 +91,8 @@ struct server {
 /*
  * Some defaults
  */
-#define        DEFTIMEOUT      5               /* 5 timer increments */
+#define        MINTIMEOUT      (2 * TIMER_HZ)  /* 2s min. between packets */
+#define        DEFTIMEOUT      MINTIMEOUT      /*   (to the same server) */
 #define        DEFSAMPLES      4               /* get 4 samples per server */
 #define        DEFPRECISION    (-5)            /* the precision we claim */
 #define        DEFMAXPERIOD    60              /* maximum time to wait */