]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
dnstap: export some information about applied policy docs-dnstap-polic-ly80ii/deployments/7159 dnstap-policy
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 8 Jul 2025 07:05:16 +0000 (09:05 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 8 Jul 2025 10:27:32 +0000 (12:27 +0200)
daemon/lua/kres-gen-33.lua
daemon/lua/kres-gen.sh
lib/resolve.h
lib/rules/api.c
modules/dnstap/dnstap.c

index efe0d68564fb0ecece2cc7231b7deced696f55b6..21d1a27eed7dd3f74266a1e2c268dc49b0323a20 100644 (file)
@@ -233,6 +233,9 @@ struct kr_extended_error {
        int32_t info_code;
        const char *extra_text;
 };
+struct kr_request_rule {
+       int8_t action;
+};
 struct kr_request {
        struct kr_context *ctx;
        knot_pkt_t *answer;
@@ -265,6 +268,7 @@ struct kr_request {
        uint8_t rank;
        uint8_t rule_score_apply;
        uint8_t rule_score_log;
+       struct kr_request_rule rule;
        struct kr_rplan rplan;
        trace_log_f trace_log;
        trace_callback_f trace_finish;
index a5bc6f9a4d18cd4c23b960a28600c4e885a2ea9d..ec9f47694a32e5a7e2911e3c64f4d5f24fc3f668 100755 (executable)
@@ -143,6 +143,7 @@ ${CDEFS} ${LIBKRES} types <<-EOF
        struct kr_rule_fwd_flags
        typedef kr_rule_fwd_flags_t
        struct kr_extended_error
+       struct kr_request_rule
        struct kr_request
        enum kr_rank
        typedef kr_cdb_pt
index c463118a343c14093e697142e0073c560a312e2a..40feaa4e8acc8448747707f46d7ed93b38e807c5 100644 (file)
@@ -208,6 +208,21 @@ typedef bool (*addr_info_f)(struct sockaddr*);
 typedef void (*async_resolution_f)(knot_dname_t*, enum knot_rr_type);
 typedef array_t(union kr_sockaddr) kr_sockaddr_array_t;
 
+/** Information about rules/policies applied to a kr_request.
+ *
+ * Let's keep this compatible with dnstap, including the number values.
+ * Though the meaning can't "match exactly". */
+struct kr_request_rule {
+       int8_t action;
+};
+enum kr_request_rule_action {
+       // zero == unset
+       KREQ_ACTION_NXDOMAIN = 1,
+       KREQ_ACTION_NODATA = 2,
+       KREQ_ACTION_PASS = 3,
+       KREQ_ACTION_LOCAL_DATA = 6,
+};
+
 /**
  * Name resolution request.
  *
@@ -282,6 +297,8 @@ struct kr_request {
        uint8_t rule_score_apply;
        uint8_t rule_score_log;
 
+       struct kr_request_rule rule;
+
        struct kr_rplan rplan;
        trace_log_f trace_log; /**< Logging tracepoint */
        trace_callback_f trace_finish; /**< Request finish tracepoint */
index 82e3ee769b65c183b7b68405cb93e04ee436470e..e403ba6a41e92d94af1080602f65ab560a85138c 100644 (file)
@@ -65,6 +65,18 @@ static int rule_local_subtree(const knot_dname_t *apex, enum kr_rule_sub_t type,
                                const knot_dname_t *target, uint32_t ttl,
                                kr_rule_tags_t tags, kr_rule_opts_t opts);
 
+static void qry_set_action(struct kr_query *qry, enum kr_request_rule_action action)
+{
+       // We only set the action if applying on the original QNAME
+       // or the CNAME chain leading from it, not on any other sub-queries.
+       const struct kr_query *q = qry;
+       while (q->cname_parent)
+               q = q->cname_parent;
+       if (q->parent)
+               return;
+       qry->request->rule.action = action;
+}
+
 // LATER: doing tag_names_default() and kr_rule_tag_add() inside a RW transaction would be better.
 static int tag_names_default(void)
 {
@@ -586,6 +598,7 @@ static int answer_exact_match(struct kr_query *qry, knot_pkt_t *pkt, uint16_t ty
        qry->flags.EXPIRING = false;
        qry->flags.CACHED = true;
        qry->flags.NO_MINIMIZE = true;
+       qry_set_action(qry, is_nodata ? KREQ_ACTION_NODATA : KREQ_ACTION_LOCAL_DATA);
        return RET_ANSWERED;
 }
 
@@ -774,6 +787,14 @@ static int answer_zla_empty(val_zla_type_t type, struct kr_query *qry, knot_pkt_
        qry->flags.CACHED = true;
        qry->flags.NO_MINIMIZE = true;
 
+       if (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NXDOMAIN) {
+               qry_set_action(qry, KREQ_ACTION_NXDOMAIN);
+       } else if (pkt->current == KNOT_ANSWER) {
+               qry_set_action(qry, KREQ_ACTION_LOCAL_DATA);
+       } else {
+               qry_set_action(qry, KREQ_ACTION_NODATA);
+       }
+
        VERBOSE_MSG(qry, "=> satisfied by local data (%s zone)\n",
                     type == KR_RULE_SUB_EMPTY ? "empty" : "nxdomain");
        return kr_ok();
@@ -846,6 +867,7 @@ static int answer_zla_dname(val_zla_type_t type, struct kr_query *qry, knot_pkt_
        qry->flags.EXPIRING = false;
        qry->flags.CACHED = true;
        qry->flags.NO_MINIMIZE = true;
+       qry_set_action(qry, KREQ_ACTION_LOCAL_DATA);
 
        VERBOSE_MSG(qry, "=> satisfied by local data (DNAME)\n");
        return kr_ok();
@@ -912,6 +934,12 @@ nodata: // Want NODATA answer (or NOERROR if it hits apex SOA).
        qry->flags.CACHED = true;
        qry->flags.NO_MINIMIZE = true;
 
+       if (sec == KNOT_ANSWER) {
+               qry_set_action(qry, KREQ_ACTION_LOCAL_DATA);
+       } else {
+               qry_set_action(qry, KREQ_ACTION_NODATA);
+       }
+
        VERBOSE_MSG(qry, "=> satisfied by local data (no data)\n");
        return kr_ok();
 }
index 6fcc192c62425253c3b4d7605040261da1d4233b..4679cf20723c9e85f64e05d87ca0c10088bfea5e 100644 (file)
@@ -159,6 +159,8 @@ static int dnstap_log(kr_layer_t *ctx, enum dnstap_log_phase phase) {
 
        m.base.descriptor = &dnstap__message__descriptor;
 
+       Dnstap__Policy policy = DNSTAP__POLICY__INIT;
+
        if (req->qsource.addr) {
                set_address(req->qsource.addr,
                                &m.query_address,
@@ -236,6 +238,12 @@ static int dnstap_log(kr_layer_t *ctx, enum dnstap_log_phase phase) {
        } else if (phase == CLIENT_RESPONSE_PHASE) {
                m.type = DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE;
 
+               if (req->rule.action) {
+                       policy.action = req->rule.action;
+                       policy.has_action = true;
+                       m.policy = &policy;
+               }
+
                /* current time */
                struct timeval now;
                gettimeofday(&now, NULL);