From: Vladimír Čunát Date: Tue, 8 Jul 2025 07:05:16 +0000 (+0200) Subject: dnstap: export some information about applied policy X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fdnstap-policy;p=thirdparty%2Fknot-resolver.git dnstap: export some information about applied policy --- diff --git a/daemon/lua/kres-gen-33.lua b/daemon/lua/kres-gen-33.lua index efe0d6856..21d1a27ee 100644 --- a/daemon/lua/kres-gen-33.lua +++ b/daemon/lua/kres-gen-33.lua @@ -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; diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index a5bc6f9a4..ec9f47694 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -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 diff --git a/lib/resolve.h b/lib/resolve.h index c463118a3..40feaa4e8 100644 --- a/lib/resolve.h +++ b/lib/resolve.h @@ -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 */ diff --git a/lib/rules/api.c b/lib/rules/api.c index 82e3ee769..e403ba6a4 100644 --- a/lib/rules/api.c +++ b/lib/rules/api.c @@ -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(); } diff --git a/modules/dnstap/dnstap.c b/modules/dnstap/dnstap.c index 6fcc192c6..4679cf207 100644 --- a/modules/dnstap/dnstap.c +++ b/modules/dnstap/dnstap.c @@ -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);