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.
*
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 */
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)
{
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;
}
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();
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();
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();
}
m.base.descriptor = &dnstap__message__descriptor;
+ Dnstap__Policy policy = DNSTAP__POLICY__INIT;
+
if (req->qsource.addr) {
set_address(req->qsource.addr,
&m.query_address,
} 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);