diff --git a/clientlog.c b/clientlog.c index 43cba67..4297fe2 100644 --- a/clientlog.c +++ b/clientlog.c @@ -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 8849bdc..7426e61 100644 --- 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 4c0a787..4479c9c 100644 --- 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); diff --git a/doc/chrony.conf.adoc b/doc/chrony.conf.adoc index bd296bc..b6cd421 100644 --- a/doc/chrony.conf.adoc +++ b/doc/chrony.conf.adoc @@ -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 <> 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 <> 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: + diff --git a/ntp_core.c b/ntp_core.c index 6aa8e18..149e32a 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -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; diff --git a/test/simulation/135-ratelimit b/test/simulation/135-ratelimit index 86c435d..0756f19 100755 --- a/test/simulation/135-ratelimit +++ b/test/simulation/135-ratelimit @@ -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