Also refactor the C APIs, causing most of the diffs.
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_layer_t kr_layer_t_static;
_Bool kr_dbg_assertion_abort;
int kr_dbg_assertion_fork;
+const uint32_t KR_RULE_TTL_DEFAULT;
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
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);
+int kr_rule_local_subtree(const knot_dname_t *, enum kr_rule_sub_t, uint32_t, kr_rule_tags_t);
int kr_rule_zonefile(const struct kr_rule_zonefile_config *);
int kr_rule_forward(const knot_dname_t *, kr_rule_fwd_flags_t, const struct sockaddr **);
int kr_rule_local_address(const char *, const char *, _Bool, uint32_t, kr_rule_tags_t);
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_layer_t kr_layer_t_static;
_Bool kr_dbg_assertion_abort;
int kr_dbg_assertion_fork;
+const uint32_t KR_RULE_TTL_DEFAULT;
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
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);
+int kr_rule_local_subtree(const knot_dname_t *, enum kr_rule_sub_t, uint32_t, kr_rule_tags_t);
int kr_rule_zonefile(const struct kr_rule_zonefile_config *);
int kr_rule_forward(const knot_dname_t *, kr_rule_fwd_flags_t, const struct sockaddr **);
int kr_rule_local_address(const char *, const char *, _Bool, uint32_t, kr_rule_tags_t);
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_layer_t kr_layer_t_static;
_Bool kr_dbg_assertion_abort;
int kr_dbg_assertion_fork;
+const uint32_t KR_RULE_TTL_DEFAULT;
typedef int32_t (*kr_stale_cb)(int32_t ttl, const knot_dname_t *owner, uint16_t type,
const struct kr_query *qry);
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);
+int kr_rule_local_subtree(const knot_dname_t *, enum kr_rule_sub_t, uint32_t, kr_rule_tags_t);
int kr_rule_zonefile(const struct kr_rule_zonefile_config *);
int kr_rule_forward(const knot_dname_t *, kr_rule_fwd_flags_t, const struct sockaddr **);
int kr_rule_local_address(const char *, const char *, _Bool, uint32_t, kr_rule_tags_t);
kr_log_level_t
enum kr_log_group
struct kr_query_data_src
+ enum kr_rule_sub_t
EOF
-${CDEFS} ${LIBKRES} variables <<-EOF
+${CDEFS} ${KRESD} variables <<-EOF
kr_layer_t_static
+EOF
+${CDEFS} ${LIBKRES} variables <<-EOF
kr_dbg_assertion_abort
kr_dbg_assertion_fork
+ KR_RULE_TTL_DEFAULT
EOF
printf "
kr_view_insert_action
kr_view_select_action
kr_rule_tag_add
- kr_rule_local_data_emptyzone
- kr_rule_local_data_nxdomain
+ kr_rule_local_subtree
kr_rule_zonefile
kr_rule_forward
kr_rule_local_address
.. option:: type: empty|nxdomain|redirect
- Type of a subtree.
+ Type of this subtree:
+
+ - ``empty`` is an empty zone with just SOA and NS at the top
+ - ``nxdomain`` replies ``NXDOMAIN`` everywhere, though in some cases that looks slightly weird
+ - ``redirect`` answers with local-data records from the top of the zone, inside the whole virtual subtree
.. option:: tags: <list of tags>
Optional, tags to link with other policy rules, e.g. :ref:`views <config-views>`.
+ .. option:: ttl: <time s|m|h|d>
+
+ Optional, TTL of answers from this rule. Uses ``/local-data/ttl`` if unspecified.
+
.. future
.. option:: addresses: <list of addresses>
struct kr_rules *the_rules = NULL;
+const uint32_t KR_RULE_TTL_DEFAULT = RULE_TTL_DEFAULT;
+
/* DB key-space summary
- "\0" starts special keys like "\0rulesets" or "\0stamp"
}
// Finally execute the rule.
switch (ztype) {
- case VAL_ZLAT_EMPTY:
- case VAL_ZLAT_NXDOMAIN:
- case VAL_ZLAT_NODATA:
+ case KR_RULE_SUB_EMPTY:
+ case KR_RULE_SUB_NXDOMAIN:
+ case KR_RULE_SUB_NODATA:
ret = answer_zla_empty(ztype, qry, pkt, zla_lf, ttl);
if (ret == kr_error(EAGAIN))
goto shorten;
return ret ? ret : RET_ANSWERED;
- case VAL_ZLAT_REDIRECT:
+ case KR_RULE_SUB_REDIRECT:
ret = answer_zla_redirect(qry, pkt, ruleset_name, zla_lf, ttl);
return ret ? kr_error(ret) : RET_ANSWERED;
default:
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, uint32_t ttl)
{
- if (kr_fails_assert(type == VAL_ZLAT_EMPTY || type == VAL_ZLAT_NXDOMAIN
- || type == VAL_ZLAT_NODATA))
+ if (kr_fails_assert(type == KR_RULE_SUB_EMPTY || type == KR_RULE_SUB_NXDOMAIN
+ || type == KR_RULE_SUB_NODATA))
return kr_error(EINVAL);
knot_dname_t apex_name[KNOT_DNAME_MAXLEN];
CHECK_RET(ret);
const bool hit_apex = knot_dname_is_equal(qry->sname, apex_name);
- if (hit_apex && type == VAL_ZLAT_NODATA)
+ if (hit_apex && type == KR_RULE_SUB_NODATA)
return kr_error(EAGAIN);
/* Start constructing the (pseudo-)packet. */
memset(&arrset, 0, sizeof(arrset));
/* Construct SOA or NS data (hardcoded content). _EMPTY has a proper zone apex. */
- const bool want_NS = hit_apex && type == VAL_ZLAT_EMPTY && qry->stype == KNOT_RRTYPE_NS;
+ const bool want_NS = hit_apex && type == KR_RULE_SUB_EMPTY
+ && qry->stype == KNOT_RRTYPE_NS;
arrset.set.rr = knot_rrset_new(apex_name, want_NS ? KNOT_RRTYPE_NS : KNOT_RRTYPE_SOA,
KNOT_CLASS_IN, ttl, &pkt->mm);
if (kr_fails_assert(arrset.set.rr))
arrset.set.expiring = false;
/* Small differences if we exactly hit the name or even type. */
- if (type == VAL_ZLAT_NODATA || (type == VAL_ZLAT_EMPTY && hit_apex)) {
+ if (type == KR_RULE_SUB_NODATA || (type == KR_RULE_SUB_EMPTY && hit_apex)) {
knot_wire_set_rcode(pkt->wire, KNOT_RCODE_NOERROR);
} else {
knot_wire_set_rcode(pkt->wire, KNOT_RCODE_NXDOMAIN);
}
- if (type == VAL_ZLAT_EMPTY && hit_apex
+ if (type == KR_RULE_SUB_EMPTY && hit_apex
&& (qry->stype == KNOT_RRTYPE_SOA || qry->stype == KNOT_RRTYPE_NS)) {
ret = knot_pkt_begin(pkt, KNOT_ANSWER);
} else {
qry->flags.NO_MINIMIZE = true;
VERBOSE_MSG(qry, "=> satisfied by local data (%s zone)\n",
- type == VAL_ZLAT_EMPTY ? "empty" : "nxdomain");
+ type == KR_RULE_SUB_EMPTY ? "empty" : "nxdomain");
return kr_ok();
}
key.len = key_data + KEY_DNAME_END_OFFSET - (uint8_t *)key.data;
return key;
}
-int insert_trivial_zone(val_zla_type_t ztype, uint32_t ttl,
- const knot_dname_t *apex, kr_rule_tags_t tags)
+int kr_rule_local_subtree(const knot_dname_t *apex, enum kr_rule_sub_t type,
+ uint32_t ttl, kr_rule_tags_t tags)
{
+ // type-check
+ switch (type) {
+ case KR_RULE_SUB_EMPTY:
+ case KR_RULE_SUB_NXDOMAIN:
+ case KR_RULE_SUB_NODATA:
+ case KR_RULE_SUB_REDIRECT:
+ break;
+ default:
+ kr_assert(false);
+ return kr_error(EINVAL);
+ }
+ const val_zla_type_t ztype = type;
+
ENSURE_the_rules;
+
uint8_t key_data[KEY_MAXLEN];
knot_db_val_t key = zla_key(apex, key_data);
return kr_ok();
}
-int kr_rule_local_data_emptyzone(const knot_dname_t *apex, kr_rule_tags_t tags)
-{
- return insert_trivial_zone(VAL_ZLAT_EMPTY, RULE_TTL_DEFAULT, 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, RULE_TTL_DEFAULT, apex, tags);
-}
-int kr_rule_local_data_nodata(const knot_dname_t *apex, kr_rule_tags_t tags)
-{
- return insert_trivial_zone(VAL_ZLAT_NODATA, RULE_TTL_DEFAULT, 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, RULE_TTL_DEFAULT, apex, tags);
-}
-
/** Encode a subnet into a (longer) string.
*
int kr_view_select_action(const struct kr_request *req, knot_db_val_t *selected);
+/** Default TTL for answers from local data rules.
+ *
+ * Some types of rules save space when using this default.
+ * This definition exists mainly for usage from lua.
+ */
+KR_EXPORT extern
+const uint32_t KR_RULE_TTL_DEFAULT;
/* APIs to modify the rule DB.
*
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.
+enum kr_rule_sub_t {
+ /// Empty zone, i.e. with SOA and NS
+ KR_RULE_SUB_EMPTY = 1,
+ /// 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)
+ KR_RULE_SUB_NODATA,
+ /// Redirect: anything beneath has the same data as apex (except NS+SOA).
+ KR_RULE_SUB_REDIRECT,
+};
+/** Insert a simple sub-tree rule.
*
* - into the default rule-set
* - SOA and NS for generated answers aren't overridable.
- * - TTL is RULE_TTL_DEFAULT
*/
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 "NODATA zone". These functions are all similar. */
-KR_EXPORT
-int kr_rule_local_data_nodata(const knot_dname_t *apex, kr_rule_tags_t tags);
-
-/** Insert a redirect zone.
- * 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);
+int kr_rule_local_subtree(const knot_dname_t *apex, enum kr_rule_sub_t type,
+ uint32_t ttl, kr_rule_tags_t tags);
/** Insert a view action into the default ruleset.
*
knot_dname_t name_buf[KNOT_DNAME_MAXLEN];
const knot_dname_t *dname =
knot_dname_from_str(name_buf, names[i], sizeof(name_buf));
- int ret = kr_rule_local_data_emptyzone(dname, KR_RULE_TAGS_ALL);
+ int ret = kr_rule_local_subtree(dname, KR_RULE_SUB_EMPTY,
+ RULE_TTL_DEFAULT, KR_RULE_TAGS_ALL);
CHECK_RET(ret);
/* The double conversion is perhaps a bit wasteful, but it should be rare. */
/* LATER: add extra info with explanation? policy module had an ADDITIONAL
* record with explanation, but perhaps extended errors are more suitable?
- * Differentiating the message - perhaps splitting VAL_ZLAT_EMPTY into a few?
+ * Differentiating the message - perhaps splitting KR_RULE_SUB_EMPTY into a few?
*/
}
knot_dname_t localhost_dname[] = "\x09localhost\0";
{ // forward localhost
- int ret = kr_rule_local_data_redirect(localhost_dname, KR_RULE_TAGS_ALL);
+ int ret = kr_rule_local_subtree(localhost_dname, KR_RULE_SUB_REDIRECT,
+ RULE_TTL_DEFAULT, KR_RULE_TAGS_ALL);
CHECK_RET(ret);
knot_rrset_t rr = {
/** The first byte of zone-like apex value is its type. */
typedef uint8_t val_zla_type_t;
+/** This effectively contains enum kr_rule_sub_t */
enum {
- /** Empty zone. No data in DB value after this byte.
- *
- * TODO: add
- * - SOA rdata (maybe, optional, remainder of DB value)
- * Same for _NXDOMAIN and _NODATA, too.
- */
- VAL_ZLAT_EMPTY = 1,
- /** Forced NXDOMAIN. */
- VAL_ZLAT_NXDOMAIN,
- /** Forced NODATA. Does not apply on exact name (e.g. it's similar to DNAME) */
- VAL_ZLAT_NODATA,
- /** Redirect: anything beneath has the same data as apex (except NS+SOA). */
- VAL_ZLAT_REDIRECT,
/** Forward, i.e. override upstream for this subtree (resolver or auth). */
- VAL_ZLAT_FORWARD,
+ VAL_ZLAT_FORWARD = 128,
};
-/** For now see kr_rule_local_data_emptyzone() and friends.
- *
- * TODO: probably make something like this the preferred API. */
-int insert_trivial_zone(val_zla_type_t ztype, uint32_t ttl,
- const knot_dname_t *apex, kr_rule_tags_t tags);
extern /*const*/ char RULESET_DEFAULT[];
// Exact RPZ semantics would be hard here, it makes more sense
// to apply also to a subtree, and corresponding wildcard rule
// usually accompanies this rule anyway.
- ret = insert_trivial_zone(VAL_ZLAT_NXDOMAIN, s->r_ttl, apex, c->tags);
+ ret = kr_rule_local_subtree(apex, KR_RULE_SUB_NXDOMAIN, s->r_ttl, c->tags);
} else if (knot_dname_is_wildcard(s->r_data) && s->r_data[2] == 0) {
// "CNAME *." -> NODATA
knot_dname_t *apex = s->r_owner;
if (knot_dname_is_wildcard(apex)) {
apex += 2;
- ret = insert_trivial_zone(VAL_ZLAT_NODATA, s->r_ttl, apex, c->tags);
+ ret = kr_rule_local_subtree(apex, KR_RULE_SUB_NODATA,
+ s->r_ttl, c->tags);
} else { // using special kr_rule_ semantics of empty CNAME RRset
knot_rrset_t rrs;
knot_rrset_init(&rrs, apex, KNOT_RRTYPE_CNAME,
{% for subtree in cfg.local_data.subtrees %}
{% if subtree.roots -%}
{% for root in subtree.roots %}
-{{ local_data_subtree_root(subtree.type, root, subtree.tags) }}
+{{ local_data_subtree_root(root, subtree.type, subtree.ttl or cfg.local_data.ttl, subtree.tags) }}
{% endfor %}
{%- elif subtree.roots_file -%}
{# TODO: not implemented yet #}
assert(C.kr_rule_zonefile({{ id }})==0)
{%- endmacro %}
-{% macro local_data_emptyzone(dname, tags) -%}
-assert(C.kr_rule_local_data_emptyzone({{ dname }},{{ tags }})==0)
-{%- endmacro %}
-
-{% macro local_data_nxdomain(dname, tags) -%}
-assert(C.kr_rule_local_data_nxdomain({{ dname }},{{ tags }})==0)
-{%- endmacro %}
-
-{% macro local_data_subtree_root(type, root, tags) -%}
+{% macro local_data_subtree_root(root, type, ttl, tags) -%}
+{% if ttl %}
+{%- set get_ttl = ttl.seconds() -%}
+{%- else -%}
+{%- set get_ttl = 'C.KR_RULE_TTL_DEFAULT' -%}
+{% endif %}
{%- if tags -%}
{%- set get_tags = policy_get_tagset(tags) -%}
{%- else -%}
{%- set get_tags = '0' -%}
{%- endif -%}
-{%- if type == 'empty' -%}
-{{ local_data_emptyzone(policy_todname(root), get_tags) }}
-{%- elif type == 'nxdomain' -%}
-{{ local_data_nxdomain(policy_todname(root), get_tags) }}
-{%- else -%}
-{# TODO: implement other possible types #}
-{%- endif -%}
+assert(C.kr_rule_local_subtree(todname('{{ root }}'),
+ C.KR_RULE_SUB_{{ type.upper() }}, {{ get_ttl }}, {{ get_tags }}) == 0)
{%- endmacro %}