summaryrefslogtreecommitdiffstats
path: root/clientlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'clientlog.c')
-rw-r--r--clientlog.c42
1 files changed, 28 insertions, 14 deletions
diff --git a/clientlog.c b/clientlog.c
index c408e8d..903f190 100644
--- a/clientlog.c
+++ b/clientlog.c
@@ -3,7 +3,7 @@
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2003
- * Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021
+ * Copyright (C) Miroslav Lichvar 2009, 2015-2017, 2021, 2024
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -117,6 +117,14 @@ static int token_shift[MAX_SERVICES];
static int leak_rate[MAX_SERVICES];
+/* Rates at which responses requesting clients to reduce their rate
+ (e.g. NTP KoD RATE) are randomly allowed (in log2, but 0 means disabled) */
+
+#define MIN_KOD_RATE 0
+#define MAX_KOD_RATE 4
+
+static int kod_rate[MAX_SERVICES];
+
/* Limit intervals in log2 */
static int limit_interval[MAX_SERVICES];
@@ -354,18 +362,19 @@ set_bucket_params(int interval, int burst, uint16_t *max_tokens,
void
CLG_Initialise(void)
{
- int i, interval, burst, lrate, slots2;
+ int i, interval, burst, lrate, krate, slots2;
for (i = 0; i < MAX_SERVICES; i++) {
max_tokens[i] = 0;
tokens_per_hit[i] = 0;
token_shift[i] = 0;
leak_rate[i] = 0;
+ kod_rate[i] = 0;
limit_interval[i] = MIN_LIMIT_INTERVAL;
switch (i) {
case CLG_NTP:
- if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate))
+ if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate, &krate))
continue;
break;
case CLG_NTSKE:
@@ -382,6 +391,7 @@ CLG_Initialise(void)
set_bucket_params(interval, burst, &max_tokens[i], &tokens_per_hit[i], &token_shift[i]);
leak_rate[i] = CLAMP(MIN_LEAK_RATE, lrate, MAX_LEAK_RATE);
+ kod_rate[i] = CLAMP(MIN_KOD_RATE, krate, MAX_KOD_RATE);
limit_interval[i] = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
}
@@ -579,28 +589,28 @@ CLG_LogServiceAccess(CLG_Service service, IPAddr *client, struct timespec *now)
/* ================================================== */
static int
-limit_response_random(int leak_rate)
+limit_response_random(int rate)
{
static uint32_t rnd;
static int bits_left = 0;
int r;
- if (bits_left < leak_rate) {
+ if (bits_left < rate) {
UTI_GetRandomBytes(&rnd, sizeof (rnd));
bits_left = 8 * sizeof (rnd);
}
- /* Return zero on average once per 2^leak_rate */
- r = rnd % (1U << leak_rate) ? 1 : 0;
- rnd >>= leak_rate;
- bits_left -= leak_rate;
+ /* Return zero on average once per 2^rate */
+ r = rnd % (1U << rate) ? 1 : 0;
+ rnd >>= rate;
+ bits_left -= rate;
return r;
}
/* ================================================== */
-int
+CLG_Limit
CLG_LimitServiceRate(CLG_Service service, int index)
{
Record *record;
@@ -609,14 +619,14 @@ CLG_LimitServiceRate(CLG_Service service, int index)
check_service_number(service);
if (tokens_per_hit[service] == 0)
- return 0;
+ return CLG_PASS;
record = ARR_GetElement(records, index);
record->drop_flags &= ~(1U << service);
if (record->tokens[service] >= tokens_per_hit[service]) {
record->tokens[service] -= tokens_per_hit[service];
- return 0;
+ return CLG_PASS;
}
drop = limit_response_random(leak_rate[service]);
@@ -632,14 +642,18 @@ CLG_LimitServiceRate(CLG_Service service, int index)
if (!drop) {
record->tokens[service] = 0;
- return 0;
+ return CLG_PASS;
+ }
+
+ if (kod_rate[service] > 0 && !limit_response_random(kod_rate[service])) {
+ return CLG_KOD;
}
record->drop_flags |= 1U << service;
record->drops[service]++;
total_drops[service]++;
- return 1;
+ return CLG_DROP;
}
/* ================================================== */