From 8c7c88ab274d0cd0076ad18995731f499390c7d4 Mon Sep 17 00:00:00 2001
From: Daniel Salzman <daniel.salzman@nic.cz>
Date: Mon, 2 Dec 2024 15:26:25 +0100
Subject: [PATCH] mod-rrl: add QNAME, if possible, and PROTO to log messages

---
 src/knot/modules/rrl/functions.c | 29 +++++++++++++++++++++++------
 src/knot/modules/rrl/functions.h | 10 ++++++++--
 src/knot/modules/rrl/rrl.c       |  6 ++++--
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/src/knot/modules/rrl/functions.c b/src/knot/modules/rrl/functions.c
index 01d89cb669..5534b44377 100644
--- a/src/knot/modules/rrl/functions.c
+++ b/src/knot/modules/rrl/functions.c
@@ -68,18 +68,35 @@ static void addr_tostr(char *dst, size_t maxlen, const struct sockaddr_storage *
 	}
 }
 
-static void rrl_log_limited(knotd_mod_t *mod, const struct sockaddr_storage *ss,
+static void rrl_log_limited(rrl_log_params_t *params, const struct sockaddr_storage *ss,
                             const uint8_t prefix, bool rate)
 {
-	if (mod == NULL) {
+	if (params == NULL) {
 		return;
 	}
 
 	char addr_str[SOCKADDR_STRLEN];
 	addr_tostr(addr_str, sizeof(addr_str), ss);
 
-	knotd_mod_log(mod, LOG_NOTICE, "address %s limited on /%d by %s",
-	              addr_str, prefix, rate ? "rate" : "time");
+	const char *proto_str = "UDP";
+	const char *qname_str = NULL;
+	knot_dname_txt_storage_t buf;
+	if (params->qdata != NULL) {
+		qname_str = knot_dname_to_str(buf, knot_pkt_qname(params->qdata->query),
+		                              sizeof(buf));
+	} else {
+		switch (params->proto) {
+		case KNOTD_QUERY_PROTO_TCP:  proto_str = "TCP"; break;
+		case KNOTD_QUERY_PROTO_QUIC: proto_str = "QUIC"; break;
+		case KNOTD_QUERY_PROTO_TLS:  proto_str = "TLS"; break;
+		default:                     break;
+		}
+	}
+
+	knotd_mod_log(params->mod, LOG_NOTICE, "address %s %s limited on /%d by %s%s%s",
+	              addr_str, proto_str, prefix, rate ? "rate" : "time",
+	              (qname_str != NULL ? ", qname " : ""),
+	              (qname_str != NULL ? qname_str : ""));
 }
 
 rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit,
@@ -131,7 +148,7 @@ rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit
 	return rrl;
 }
 
-int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod)
+int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, rrl_log_params_t *log)
 {
 	assert(rrl);
 	assert(remote);
@@ -186,7 +203,7 @@ int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod
 		do {
 			if (atomic_compare_exchange_weak_explicit(&rrl->log_time, &log_time_orig, now,
 			                                          memory_order_relaxed, memory_order_relaxed)) {
-				rrl_log_limited(mod, remote, prefix, rrl->rw_mode);
+				rrl_log_limited(log, remote, prefix, rrl->rw_mode);
 				break;
 			}
 		} while (now - log_time_orig + 1024 >= rrl->log_period + 1024);
diff --git a/src/knot/modules/rrl/functions.h b/src/knot/modules/rrl/functions.h
index 0941c8378f..8fe1383c5f 100644
--- a/src/knot/modules/rrl/functions.h
+++ b/src/knot/modules/rrl/functions.h
@@ -37,6 +37,12 @@ typedef struct rrl_table rrl_table_t;
 rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit,
                         bool rw_mode, uint32_t log_period);
 
+typedef struct {
+	knotd_mod_t *mod;
+	knotd_qdata_t *qdata;      // For rate limiting.
+	knotd_query_proto_t proto; // For time limiting.
+} rrl_log_params_t;
+
 /*!
  * \brief Query the RRL table for accept or deny, when the rate limit is reached.
  *
@@ -44,12 +50,12 @@ rrl_table_t *rrl_create(size_t size, uint32_t instant_limit, uint32_t rate_limit
  *
  * \param rrl RRL table.
  * \param remote Source address.
- * \param mod Query module (needed for logging).
+ * \param log Logging parameters (can be NULL).
  *
  * \retval KNOT_EOK if passed.
  * \retval KNOT_ELIMIT when the limit is reached.
  */
-int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, knotd_mod_t *mod);
+int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *remote, rrl_log_params_t *log);
 
 /*!
  * \brief Update the RRL table.
diff --git a/src/knot/modules/rrl/rrl.c b/src/knot/modules/rrl/rrl.c
index 72c1d33e9b..9fcb8724dc 100644
--- a/src/knot/modules/rrl/rrl.c
+++ b/src/knot/modules/rrl/rrl.c
@@ -104,7 +104,8 @@ static knotd_proto_state_t protolimit_start(knotd_proto_state_t state,
 	}
 
 	// Check if the packet is limited.
-	if (rrl_query(ctx->time_table, params->remote, mod) != KNOT_EOK) {
+	rrl_log_params_t log = { .mod = mod, .proto = params->proto };
+	if (rrl_query(ctx->time_table, params->remote, &log) != KNOT_EOK) {
 		thrd->skip = true;
 		knotd_mod_stats_incr(mod, params->thread_id, 2, 0, 1);
 		return ctx->dry_run ? state : KNOTD_PROTO_STATE_BLOCK;
@@ -168,7 +169,8 @@ static knotd_state_t ratelimit_apply(knotd_state_t state, knot_pkt_t *pkt,
 		return state;
 	}
 
-	if (rrl_query(ctx->rate_table, knotd_qdata_remote_addr(qdata), mod) == KNOT_EOK) {
+	rrl_log_params_t log = { .mod = mod, .qdata = qdata };
+	if (rrl_query(ctx->rate_table, knotd_qdata_remote_addr(qdata), &log) == KNOT_EOK) {
 		// Rate limiting not applied.
 		return state;
 	}
-- 
GitLab