]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/rules: add NXDOMAIN (pseudo-)zones
authorVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 9 Feb 2023 09:58:13 +0000 (10:58 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 12 Jun 2023 08:32:28 +0000 (10:32 +0200)
It's questionable which SOA owner to use, but some users will surely
prefer NXDOMAINs to empty zones.

daemon/lua/kres-gen-30.lua
daemon/lua/kres-gen-31.lua
daemon/lua/kres-gen-32.lua
daemon/lua/kres-gen.sh
lib/rules/api.c
lib/rules/api.h

index dd671d15083db54016342de7fc7c2b32199adb54..17057283997494ba22e90b5289f286b9796fc27f 100644 (file)
@@ -469,6 +469,7 @@ int kr_view_insert_action(const char *, const char *);
 int kr_view_select_action(const struct kr_request *, knot_db_val_t *);
 int kr_rule_tag_add(const char *, kr_rule_tags_t *);
 int kr_rule_local_data_emptyzone(const knot_dname_t *, kr_rule_tags_t);
+int kr_rule_local_data_nxdomain(const knot_dname_t *, kr_rule_tags_t);
 typedef struct {
        int sock_type;
        _Bool tls;
index 370de14310163581844adfc20b2102c21d13a83f..05b9e2cf91ceb156fea28249d70cec44c9823295 100644 (file)
@@ -469,6 +469,7 @@ int kr_view_insert_action(const char *, const char *);
 int kr_view_select_action(const struct kr_request *, knot_db_val_t *);
 int kr_rule_tag_add(const char *, kr_rule_tags_t *);
 int kr_rule_local_data_emptyzone(const knot_dname_t *, kr_rule_tags_t);
+int kr_rule_local_data_nxdomain(const knot_dname_t *, kr_rule_tags_t);
 typedef struct {
        int sock_type;
        _Bool tls;
index 899c05cf04c4a5796fa347a4cd9b31fde427170f..2521a6b4c5d84e82d0142f815707e7eeac588059 100644 (file)
@@ -480,6 +480,7 @@ int kr_view_insert_action(const char *, const char *);
 int kr_view_select_action(const struct kr_request *, knot_db_val_t *);
 int kr_rule_tag_add(const char *, kr_rule_tags_t *);
 int kr_rule_local_data_emptyzone(const knot_dname_t *, kr_rule_tags_t);
+int kr_rule_local_data_nxdomain(const knot_dname_t *, kr_rule_tags_t);
 typedef struct {
        int sock_type;
        _Bool tls;
index 5af527ae4ef0815f3722c0c4f29729b23e67f58c..fe7af5e9c00098597d8450bd2b8333e1ce3a919d 100755 (executable)
@@ -289,6 +289,7 @@ ${CDEFS} ${LIBKRES} functions <<-EOF
        kr_view_select_action
        kr_rule_tag_add
        kr_rule_local_data_emptyzone
+       kr_rule_local_data_nxdomain
 EOF
 
 
index e37efdd81669eb3aecce39c0a1df3fc8c7d7a35b..bb3325c278fce3cc9c819a13d08847ffc60ad978 100644 (file)
@@ -54,6 +54,8 @@ typedef uint8_t val_zla_type_t;
 enum {
        /** Empty zone. No data in DB value after this byte. */
        VAL_ZLAT_EMPTY = 1,
+       /** Forced NXDOMAIN. */
+       VAL_ZLAT_NXDOMAIN,
        /** Redirect: anything beneath has the same data as apex (except NS+SOA). */
        VAL_ZLAT_REDIRECT,
 };
@@ -61,7 +63,7 @@ enum {
 
 static int answer_exact_match(struct kr_query *qry, knot_pkt_t *pkt, uint16_t type,
                const uint8_t *data, const uint8_t *data_bound);
-static int answer_zla_empty(struct kr_query *qry, knot_pkt_t *pkt,
+static int answer_zla_empty(val_zla_type_t type, struct kr_query *qry, knot_pkt_t *pkt,
                knot_db_val_t zla_lf, knot_db_val_t val);
 static int answer_zla_redirect(struct kr_query *qry, knot_pkt_t *pkt, const char *ruleset_name,
                                knot_db_val_t zla_lf, knot_db_val_t val);
@@ -399,7 +401,8 @@ int kr_rule_local_data_answer(struct kr_query *qry, knot_pkt_t *pkt)
                        ++val.data; --val.len;
                        switch (ztype) {
                        case VAL_ZLAT_EMPTY:
-                               return answer_zla_empty(qry, pkt, zla_lf, val);
+                       case VAL_ZLAT_NXDOMAIN:
+                               return answer_zla_empty(ztype, qry, pkt, zla_lf, val);
                        case VAL_ZLAT_REDIRECT:
                                return answer_zla_redirect(qry, pkt, ruleset_name, zla_lf, val);
                        default:
@@ -547,9 +550,12 @@ int kr_rule_local_data_del(const knot_rrset_t *rrs, kr_rule_tags_t tags)
        return ret == 0 ? 1 : ret;
 }
 
-static int answer_zla_empty(struct kr_query *qry, knot_pkt_t *pkt,
+/** Empty or NXDOMAIN */
+static int answer_zla_empty(val_zla_type_t type, struct kr_query *qry, knot_pkt_t *pkt,
                                const knot_db_val_t zla_lf, const knot_db_val_t val)
 {
+       if (kr_fails_assert(type == VAL_ZLAT_EMPTY || type == VAL_ZLAT_NXDOMAIN))
+               return kr_error(EINVAL);
        if (kr_fails_assert(val.len == 0)) {
                kr_log_error(RULES, "ERROR: unused bytes: %zu\n", val.len);
                return kr_error(EILSEQ);
@@ -566,7 +572,7 @@ static int answer_zla_empty(struct kr_query *qry, knot_pkt_t *pkt,
        memset(&arrset, 0, sizeof(arrset));
 
        /* Construct SOA or NS data (hardcoded content). */
-       const bool name_matches = knot_dname_is_equal(qry->sname, apex_name);
+       const bool name_matches = type != VAL_ZLAT_NXDOMAIN && knot_dname_is_equal(qry->sname, apex_name);
        const bool want_NS = name_matches && qry->stype == KNOT_RRTYPE_NS;
        arrset.set.rr = knot_rrset_new(apex_name, want_NS ? KNOT_RRTYPE_NS : KNOT_RRTYPE_SOA,
                                        KNOT_CLASS_IN, RULE_TTL_DEFAULT, &pkt->mm);
@@ -574,6 +580,7 @@ static int answer_zla_empty(struct kr_query *qry, knot_pkt_t *pkt,
                return kr_error(ENOMEM);
        if (want_NS) {
                kr_require(zla_lf.len + 2 == knot_dname_size(apex_name));
+               // TODO: maybe it's weird to use this NS name, but what else?
                ret = knot_rrset_add_rdata(arrset.set.rr, apex_name, zla_lf.len + 2, &pkt->mm);
        } else {
                ret = knot_rrset_add_rdata(arrset.set.rr, soa_rdata,
@@ -605,7 +612,8 @@ static int answer_zla_empty(struct kr_query *qry, knot_pkt_t *pkt,
        qry->flags.CACHED = true;
        qry->flags.NO_MINIMIZE = true;
 
-       VERBOSE_MSG(qry, "=> satisfied by local data (empty zone)\n");
+       VERBOSE_MSG(qry, "=> satisfied by local data (%s zone)\n",
+                    type == VAL_ZLAT_EMPTY ? "empty" : "nxdomain");
        return kr_ok();
 }
 
@@ -710,6 +718,10 @@ int kr_rule_local_data_emptyzone(const knot_dname_t *apex, kr_rule_tags_t tags)
 {
        return insert_trivial_zone(VAL_ZLAT_EMPTY, apex, tags);
 }
+int kr_rule_local_data_nxdomain(const knot_dname_t *apex, kr_rule_tags_t tags)
+{
+       return insert_trivial_zone(VAL_ZLAT_NXDOMAIN, apex, tags);
+}
 int kr_rule_local_data_redirect(const knot_dname_t *apex, kr_rule_tags_t tags)
 {
        return insert_trivial_zone(VAL_ZLAT_REDIRECT, apex, tags);
index 6ccbde89cad6192a53adedb5b99e64f496f1d4bd..8ef48a2bb78640c2ec9959a6957cb6d21f73ecf4 100644 (file)
@@ -63,13 +63,19 @@ int kr_rule_local_data_ins(const knot_rrset_t *rrs, const knot_rdataset_t *sig_r
 KR_EXPORT
 int kr_rule_local_data_del(const knot_rrset_t *rrs, kr_rule_tags_t tags);
 
+// TODO: perhaps expose an enum to unify these simple subtree rules?
+
 /** Insert an empty zone.
- * Into the default rule-set ATM.  SOA for generated NODATA isn't overridable. */
+ * Into the default rule-set ATM.  SOA and NS for generated answers aren't overridable. */
 KR_EXPORT
 int kr_rule_local_data_emptyzone(const knot_dname_t *apex, kr_rule_tags_t tags);
 
+/** Insert an "NXDOMAIN zone".  TODO: SOA owner is hard. */
+KR_EXPORT
+int kr_rule_local_data_nxdomain(const knot_dname_t *apex, kr_rule_tags_t tags);
+
 /** Insert a redirect zone.
- * Into the default rule-set ATM.  SOA for generated NODATA isn't overridable. */
+ * Into the default rule-set ATM.  SOA for generated NODATA answers isn't overridable. */
 KR_EXPORT
 int kr_rule_local_data_redirect(const knot_dname_t *apex, kr_rule_tags_t tags);