]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: add server support for KoD RATE
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 2 Apr 2024 13:25:51 +0000 (15:25 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 2 Apr 2024 13:39:12 +0000 (15:39 +0200)
Add "kod" option to the ratelimit directive to respond with the KoD
RATE code to randomly selected requests exceeding the configured limit.
This complements the client support of KoD RATE. It's disabled by
default.

There can be only one KoD code in one response. If both NTS NAK and RATE
codes are triggered, drop the response. The KoD RATE code can be set in
an NTS-authenticated response.

clientlog.c
conf.c
conf.h
doc/chrony.conf.adoc
ntp_core.c
test/simulation/135-ratelimit

index 43cba6775d557018e3e97919d770d02cf5f97d74..4297fe2c5d743ae1e110c6120538816828431e8d 100644 (file)
@@ -374,7 +374,7 @@ CLG_Initialise(void)
 
     switch (i) {
       case CLG_NTP:
-        if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate))
+        if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate, &krate))
           continue;
         break;
       case CLG_NTSKE:
diff --git a/conf.c b/conf.c
index 8849bdced87bc4fcba4c4ed52f627bf91b8bef4f..7426e619360f83906911f77b92b604cd64f8ada6 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -79,7 +79,7 @@ static void parse_maxchange(char *);
 static void parse_ntsserver(char *, ARR_Instance files);
 static void parse_ntstrustedcerts(char *);
 static void parse_ratelimit(char *line, int *enabled, int *interval,
-                            int *burst, int *leak);
+                            int *burst, int *leak, int *kod);
 static void parse_refclock(char *);
 static void parse_smoothtime(char *);
 static void parse_source(char *line, char *type, int fatal);
@@ -220,6 +220,7 @@ static int ntp_ratelimit_enabled = 0;
 static int ntp_ratelimit_interval = 3;
 static int ntp_ratelimit_burst = 8;
 static int ntp_ratelimit_leak = 2;
+static int ntp_ratelimit_kod = 0;
 static int nts_ratelimit_enabled = 0;
 static int nts_ratelimit_interval = 6;
 static int nts_ratelimit_burst = 8;
@@ -591,7 +592,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
     parse_int(p, &cmd_port);
   } else if (!strcasecmp(command, "cmdratelimit")) {
     parse_ratelimit(p, &cmd_ratelimit_enabled, &cmd_ratelimit_interval,
-                    &cmd_ratelimit_burst, &cmd_ratelimit_leak);
+                    &cmd_ratelimit_burst, &cmd_ratelimit_leak, NULL);
   } else if (!strcasecmp(command, "combinelimit")) {
     parse_double(p, &combine_limit);
   } else if (!strcasecmp(command, "confdir")) {
@@ -678,7 +679,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
     parse_string(p, &ntp_signd_socket);
   } else if (!strcasecmp(command, "ntsratelimit")) {
     parse_ratelimit(p, &nts_ratelimit_enabled, &nts_ratelimit_interval,
-                    &nts_ratelimit_burst, &nts_ratelimit_leak);
+                    &nts_ratelimit_burst, &nts_ratelimit_leak, NULL);
   } else if (!strcasecmp(command, "ntscachedir") ||
              !strcasecmp(command, "ntsdumpdir")) {
     parse_string(p, &nts_dump_dir);
@@ -710,7 +711,7 @@ CNF_ParseLine(const char *filename, int number, char *line)
     parse_int(p, &ptp_port);
   } else if (!strcasecmp(command, "ratelimit")) {
     parse_ratelimit(p, &ntp_ratelimit_enabled, &ntp_ratelimit_interval,
-                    &ntp_ratelimit_burst, &ntp_ratelimit_leak);
+                    &ntp_ratelimit_burst, &ntp_ratelimit_leak, &ntp_ratelimit_kod);
   } else if (!strcasecmp(command, "refclock")) {
     parse_refclock(p);
   } else if (!strcasecmp(command, "refresh")) {
@@ -848,7 +849,7 @@ parse_sourcedir(char *line)
 /* ================================================== */
 
 static void
-parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
+parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak, int *kod)
 {
   int n, val;
   char *opt;
@@ -869,6 +870,8 @@ parse_ratelimit(char *line, int *enabled, int *interval, int *burst, int *leak)
       *burst = val;
     else if (!strcasecmp(opt, "leak"))
       *leak = val;
+    else if (!strcasecmp(opt, "kod") && kod)
+      *kod = val;
     else
       command_parse_error();
   }
@@ -2428,11 +2431,12 @@ CNF_GetLockMemory(void)
 
 /* ================================================== */
 
-int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak)
+int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod)
 {
   *interval = ntp_ratelimit_interval;
   *burst = ntp_ratelimit_burst;
   *leak = ntp_ratelimit_leak;
+  *kod = ntp_ratelimit_kod;
   return ntp_ratelimit_enabled;
 }
 
diff --git a/conf.h b/conf.h
index 4c0a7879a83ce85cba9addbcd019914ed350387a..4479c9c6bb3e2c639722f2b936b044119a644d3b 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -115,7 +115,7 @@ extern void CNF_SetupAccessRestrictions(void);
 extern int CNF_GetSchedPriority(void);
 extern int CNF_GetLockMemory(void);
 
-extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak);
+extern int CNF_GetNTPRateLimit(int *interval, int *burst, int *leak, int *kod);
 extern int CNF_GetNtsRateLimit(int *interval, int *burst, int *leak);
 extern int CNF_GetCommandRateLimit(int *interval, int *burst, int *leak);
 extern void CNF_GetSmooth(double *max_freq, double *max_wander, int *leap_only);
index bd296bc6ee46187bb1928bb88801b40fc2b5b3e6..b6cd421a5708f58781792da99d6e9506789f316e 100644 (file)
@@ -1861,6 +1861,14 @@ source address from completely blocking responses to that address. The leak
 rate is defined as a power of 1/2 and it is 2 by default, i.e. on average at
 least every fourth request has a response. The minimum value is 1 and the
 maximum value is 4.
+*kod* _rate_:::
+This option sets the rate at which Kiss-o'-Death (KoD) RATE responses are
+randomly sent when the limits specified by the *interval* and *burst* options
+are exceeded. It is an additional stream of responses to the *leak* option. A
+KoD RATE response is a request for the client to reduce its polling rate. Few
+implementations actually support it. The rate is defined as a power of 1/2. The
+default value is 0, which means disabled. The minimum value is 0 and the maximu
+value is 4.
 {blank}::
 +
 An example use of the directive is:
@@ -1876,7 +1884,7 @@ packets, by up to 75% (with default *leak* of 2).
 [[ntsratelimit]]*ntsratelimit* [_option_]...::
 This directive enables rate limiting of NTS-KE requests. It is similar to the
 <<ratelimit,*ratelimit*>> directive, except the default interval is 6
-(1 connection per 64 seconds).
+(1 connection per 64 seconds) and the *kod* option is not supported.
 +
 An example of the use of the directive is:
 +
@@ -2024,8 +2032,8 @@ need to be run with the *-p 257* option to inter-operate correctly.)
 [[cmdratelimit]]*cmdratelimit* [_option_]...::
 This directive enables response rate limiting for command packets. It is
 similar to the <<ratelimit,*ratelimit*>> directive, except responses to
-localhost are never limited and the default interval is -4 (16 packets per
-second).
+localhost are never limited, the default interval is -4 (16 packets per
+second), and the *kod* option is not supported.
 +
 An example of the use of the directive is:
 +
index 6aa8e18eb4166018ae2da74a0d156aaf9c89b659..149e32aff4d87ec25745f60ee6c592669d0e644e 100644 (file)
@@ -2717,6 +2717,13 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
       return;
   }
 
+  if (limit == CLG_KOD) {
+    /* Don't respond if there is a conflict with the NTS NAK */
+    if (kod != 0)
+      return;
+    kod = KOD_RATE;
+  }
+
   local_ntp_rx = NULL;
   tx_ts = NULL;
   interleaved = 0;
index 86c435dfadb0feb966e3eb9b2d17795573492b35..0756f19d4afd9eb070f5461ffaec0c1bcc063029 100755 (executable)
@@ -15,4 +15,15 @@ check_sync || test_fail
 check_file_messages "  2       1       " 1200 1300 log.packets || test_fail
 check_file_messages "  1       2       " 180 220 log.packets || test_fail
 
+server_conf="ratelimit interval 6 burst 2 leak 4 kod 2"
+
+run_test || test_fail
+check_chronyd_exit || test_fail
+check_packet_interval || test_fail
+check_sync || test_fail
+
+check_file_messages "  2       1       " 700 850 log.packets || test_fail
+check_file_messages "  1       2       " 350 450 log.packets || test_fail
+check_log_messages "Received KoD RATE.*\.123.1" 100 140 || test_fail
+
 test_pass