};
struct kr_request_rule {
int8_t action;
+ kr_rule_tags_t tags;
};
struct kr_request {
struct kr_context *ctx;
unsigned int count_no_nsaddr;
unsigned int count_fail_row;
alloc_wire_f alloc_wire_cb;
- kr_rule_tags_t rule_tags;
+ kr_rule_tags_t rule_tags_apply;
+ kr_rule_tags_t rule_tags_audit;
struct kr_extended_error extended_error;
};
enum kr_rank {KR_RANK_INITIAL, KR_RANK_OMIT, KR_RANK_TRY, KR_RANK_INDET = 4, KR_RANK_BOGUS, KR_RANK_MISMATCH, KR_RANK_MISSING, KR_RANK_INSECURE, KR_RANK_AUTH = 16, KR_RANK_SECURE = 32};
/** 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". */
+ * Though the meaning can't "match exactly".
+ * TODO: when multiple actions happen during one kr_request... */
struct kr_request_rule {
int8_t action;
+ kr_rule_tags_t tags; /// TagSet that caused the action
};
enum kr_request_rule_action {
// zero == unset
unsigned int count_no_nsaddr;
unsigned int count_fail_row;
alloc_wire_f alloc_wire_cb; /**< CB to allocate answer wire (can be NULL). */
- kr_rule_tags_t rule_tags; /**< TagSet applying to this request. */
+ kr_rule_tags_t rule_tags_apply; /**< TagSet applying to this request. */
+ kr_rule_tags_t rule_tags_audit; /**< TagSet audited by this request. */
struct kr_extended_error extended_error; /**< EDE info; don't modify directly, use kr_request_set_extended_error() */
};
return ruledb_op(commit, false, true);
}
-static bool kr_rule_consume_tags(knot_db_val_t *val, const struct kr_request *req)
+/** Eat and process tags from *val.
+ *
+ * Returning true means that the rule should apply,
+ * and it requires the caller to fill req->rule.action later.
+ */
+static bool kr_rule_consume_tags(knot_db_val_t *val, struct kr_request *req, bool allow_audit)
{
kr_rule_tags_t tags;
if (deserialize_fails_assert(val, &tags)) {
* will fail anyway due to zero remaining length. */
return false;
}
- return tags == KR_RULE_TAGS_ALL || (tags & req->rule_tags);
+ // _apply tags take precendence, and we store the last one
+ kr_rule_tags_t const tags_apply = tags & req->rule_tags_apply;
+ if (tags == KR_RULE_TAGS_ALL || tags_apply) {
+ req->rule.tags = tags_apply;
+ return true;
+ }
+ // _audit: we fill everything iff we're the very first action
+ kr_rule_tags_t const tags_audit = tags & req->rule_tags_audit;
+ if (allow_audit && tags_audit && !req->rule.action) {
+ req->rule.tags = tags_audit;
+ req->rule.action = KREQ_ACTION_AUDIT;
+ }
+ return false;
}
if (kr_request_unblocked(req))
goto shorten;
+ // Let's never audit _UNBLOCK actions.
+ const bool allow_audit = ztype != VAL_ZLAT_UNBLOCK;
// The other ztype possibilities are similar; check the tags now.
- if (!kr_rule_consume_tags(&val, req)) {
+ if (!kr_rule_consume_tags(&val, req, allow_audit)) {
kr_assert(key_leq.len >= lf_start_i);
shorten:
// Shorten key_leq by one label and retry.
for (ret = ruledb_op(it_first, &key, &val);
ret == 0;
ret = ruledb_op(it_next, &val)) {
- if (!kr_rule_consume_tags(&val, qry->request))
+ if (!kr_rule_consume_tags(&val, qry->request, true))
continue;
// We found a rule that applies to the dname+rrtype+req.
knot_db_val_t val;
// Multiple variants are possible, with different tags.
for (ret = ruledb_op(it_first, &key, &val); ret == 0; ret = ruledb_op(it_next, &val)) {
- if (kr_rule_consume_tags(&val, qry->request)) {
+ const bool allow_audit = false; // we just audited at _REDIRECT root
+ if (kr_rule_consume_tags(&val, qry->request, allow_audit)) {
int ret2 = answer_exact_match(qry, pkt, qry->stype, &val);
if (ret2 != RET_CONTINUE)
return ret2;