]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
WIP unblock: add the actual unblocking mechanics
authorVladimír Čunát <vladimir.cunat@nic.cz>
Sun, 31 Aug 2025 08:48:49 +0000 (10:48 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 9 Oct 2025 09:04:31 +0000 (11:04 +0200)
daemon/lua/kres-gen-33.lua
lib/resolve.h
lib/rules/api.c
lib/rules/api.h
lib/rules/impl.h

index e7b5b94b2267fcf28c36a44eb06fb5b00079abd8..62d93e66993f7885969ae28131617502f084f15b 100644 (file)
@@ -370,7 +370,7 @@ struct kr_query_data_src {
        kr_rule_fwd_flags_t flags;
        knot_db_val_t targets_ptr;
 };
-enum kr_rule_sub_t {KR_RULE_SUB_EMPTY = 1, KR_RULE_SUB_NXDOMAIN, KR_RULE_SUB_NODATA, KR_RULE_SUB_REDIRECT, KR_RULE_SUB_DNAME};
+enum kr_rule_sub_t {KR_RULE_SUB_EMPTY = 16, KR_RULE_SUB_NXDOMAIN, KR_RULE_SUB_NODATA, KR_RULE_SUB_REDIRECT, KR_RULE_SUB_DNAME};
 enum kr_proto {KR_PROTO_INTERNAL, KR_PROTO_UDP53, KR_PROTO_TCP53, KR_PROTO_DOT, KR_PROTO_DOH, KR_PROTO_DOQ, KR_PROTO_COUNT};
 typedef unsigned char kr_proto_set;
 kr_layer_t kr_layer_t_static;
index 991ef0506c1b8a723a94009a741accbc13981625..d1d2ac376d1892c2e3a8712c216b28306e52683b 100644 (file)
@@ -467,3 +467,14 @@ static inline void kr_query_inform_timeout(struct kr_request *req, const struct
 
        kr_log_req(req, qid, ind, WORKER, "internal timeout for resolving the request has expired\n");
 }
+
+/* Let's represent unblocked (allow-listed) requests in this way. */
+static inline void kr_request_unblock(struct kr_request *req)
+{
+       req->rule.action = KREQ_ACTION_PASS;
+}
+static inline bool kr_request_unblocked(const struct kr_request *req)
+{
+       return req->rule.action == KREQ_ACTION_PASS;
+}
+
index 1f39e23e38b8a58a75f6f2f5fb62f30a5bccffcd..9d31fe3da69d0c7f0a988fb4cd91ff9206514796 100644 (file)
@@ -356,6 +356,7 @@ static int subtree_search(const size_t lf_start_i, const knot_db_val_t key,
                                const char * const ruleset_name,
                                struct kr_query *qry, knot_pkt_t *pkt)
 {
+       struct kr_request * const req = qry->request;
        kr_require(lf_start_i < KEY_MAXLEN);
        knot_db_val_t key_leq = key;
        knot_db_val_t val;
@@ -381,7 +382,7 @@ static int subtree_search(const size_t lf_start_i, const knot_db_val_t key,
                        .len  = key_leq.len  - lf_start_i,
                };
                // Found some good key, now check tags.
-               if (!kr_rule_consume_tags(&val, qry->request)) {
+               if (!kr_rule_consume_tags(&val, req)) {
                        kr_assert(key_leq.len >= lf_start_i);
                shorten:
                        // Shorten key_leq by one label and retry.
@@ -410,12 +411,25 @@ static int subtree_search(const size_t lf_start_i, const knot_db_val_t key,
                        return RET_CONT_CACHE;
                }
 
+               // Only forward rules apply to unblocked requests.
+               // LATER(optim.): we might cache the state of having no forward rules
+               if (kr_request_unblocked(req))
+                       goto shorten;
+               // Unblock rules also don't have opts+ttl.
+               if (ztype == VAL_ZLAT_UNBLOCK) {
+                       kr_request_unblock(req);
+                       VERBOSE_MSG(qry, "=> unblocked\n");
+                       if (kr_fails_assert(val.len == 0))
+                               kr_log_error(RULES, "ERROR: unused bytes: %zu\n", val.len);
+                       goto shorten; // the same situation as kr_request_unblocked()
+               }
+
                // Process opts.
                kr_rule_opts_t opts;
                if (deserialize_fails_assert(&val, &opts))
                        return kr_error(EILSEQ);
                log_rule(opts, qry);
-               if (opts.score < qry->request->rule_score_apply)
+               if (opts.score < req->rule_score_apply)
                        goto shorten; // continue looking for rules
 
                // The non-forward types optionally specify TTL.
@@ -503,6 +517,8 @@ int rule_local_data_answer(struct kr_query *qry, knot_pkt_t *pkt)
                                goto skip_exact;
                        }
                }
+               if (kr_request_unblocked(qry->request))
+                       goto skip_exact;
 
                // Probe for exact and CNAME rule.
                memcpy(key_data_ruleset_end, &KEY_EXACT_MATCH, sizeof(KEY_EXACT_MATCH));
index 7e972dde3f0ce7446de01f33e4add5a985f6d4d1..6fba0f8274eb940ab4099a65f423d26575bc546d 100644 (file)
@@ -193,7 +193,7 @@ int kr_rule_local_data_del(const knot_rrset_t *rrs, kr_rule_tags_t tags);
 
 enum kr_rule_sub_t {
        /// Empty zone, i.e. with SOA and NS
-       KR_RULE_SUB_EMPTY = 1,
+       KR_RULE_SUB_EMPTY = 16,
        /// NXDOMAIN for everything; TODO: SOA owner is hard.
        KR_RULE_SUB_NXDOMAIN,
        /// NODATA answers but not on exact name (e.g. it's similar to DNAME)
index bf82b581a947f2d60da985478e4658705eb878b0..23df7caed9c7d4799b960046e6f23bb6229af101 100644 (file)
@@ -46,6 +46,8 @@ int rule_local_data_answer(struct kr_query *qry, knot_pkt_t *pkt);
 typedef uint8_t val_zla_type_t;
 /** This effectively contains enum kr_rule_sub_t */
 enum {
+       /** Unblock (i.e. allow-list) this subtree. */
+       VAL_ZLAT_UNBLOCK = 8,
        /** Forward, i.e. override upstream for this subtree (resolver or auth). */
        VAL_ZLAT_FORWARD = 128,
 };