diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index ad6469766ed8910924abe457face9306e48c7c1e..2823711700a6cec6cbc3e6dd183907ee74d3a359 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -34,6 +34,7 @@ #include "knot/conf/conf.h" #include "knot/conf/scheme.h" #include "knot/common/log.h" +#include "knot/nameserver/query_module.h" #include "libknot/errcode.h" #include "libknot/yparser/yptrafo.h" #include "contrib/wire_ctx.h" @@ -77,33 +78,31 @@ int mod_id_to_bin( // Check for "mod_name/mod_id" format. const uint8_t *pos = (uint8_t *)strchr((char *)in->position, '/'); - if (pos == NULL || pos >= stop) { - return KNOT_EINVAL; - } - - // Check for missing module name. if (pos == in->position) { + // Missing module name. + return KNOT_EINVAL; + } else if (pos >= stop - 1) { + // Missing module identifier after slash. return KNOT_EINVAL; } // Write mod_name in the yp_name_t format. - uint8_t name_len = pos - in->position; + uint8_t name_len = (pos != NULL) ? (pos - in->position) : + wire_ctx_available(in); wire_ctx_write_u8(out, name_len); wire_ctx_write(out, in->position, name_len); wire_ctx_skip(in, name_len); - // Skip the separator. - wire_ctx_skip(in, sizeof(uint8_t)); - - // Check for missing id. - if (wire_ctx_available(in) == 0) { - return KNOT_EINVAL; - } + // Check for mod_id. + if (pos != NULL) { + // Skip the separator. + wire_ctx_skip(in, sizeof(uint8_t)); - // Write mod_id as a zero terminated string. - int ret = yp_str_to_bin(in, out, stop); - if (ret != KNOT_EOK) { - return ret; + // Write mod_id as a zero terminated string. + int ret = yp_str_to_bin(in, out, stop); + if (ret != KNOT_EOK) { + return ret; + } } YP_CHECK_RET; @@ -119,13 +118,16 @@ int mod_id_to_txt( wire_ctx_write(out, in->position, name_len); wire_ctx_skip(in, name_len); - // Write the separator. - wire_ctx_write_u8(out, '/'); + // Check for mod_id. + if (wire_ctx_available(in) > 0) { + // Write the separator. + wire_ctx_write_u8(out, '/'); - // Write mod_id. - int ret = yp_str_to_txt(in, out); - if (ret != KNOT_EOK) { - return ret; + // Write mod_id. + int ret = yp_str_to_txt(in, out); + if (ret != KNOT_EOK) { + return ret; + } } YP_CHECK_RET; @@ -332,6 +334,16 @@ int check_modref( const uint8_t *id = args->data + 1 + args->data[0]; size_t id_len = args->data_len - 1 - args->data[0]; + // Check if the module requires some configuration. + if (id_len == 0) { + static_module_t *mod = find_module(mod_name); + if (mod == NULL) { + return KNOT_EINVAL; + } + + return mod->opt_conf ? KNOT_EOK : KNOT_YP_ENOID; + } + // Try to find a module with the id. if (!conf_rawid_exists_txn(args->conf, args->txn, mod_name, id, id_len)) { args->err_str = "invalid module reference"; diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c index f60069d7947c874d912ed7d0d3b24421b07e9de2..204db16912e5f6adb17c820b2f3203f28103b6c9 100644 --- a/src/knot/nameserver/query_module.c +++ b/src/knot/nameserver/query_module.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,27 +32,20 @@ #include "knot/modules/whoami.h" #include "knot/modules/noudp.h" -typedef struct static_module { - const yp_name_t *name; - qmodule_load_t load; - qmodule_unload_t unload; - unsigned scope; -} static_module_t; - /*! \note All modules should be dynamically loaded later on. */ static_module_t MODULES[] = { - { C_MOD_SYNTH_RECORD, &synth_record_load, &synth_record_unload, MOD_SCOPE_ANY }, - { C_MOD_DNSPROXY, &dnsproxy_load, &dnsproxy_unload, MOD_SCOPE_ANY }, - { C_MOD_ONLINE_SIGN, &online_sign_load, &online_sign_unload, MOD_SCOPE_ZONE }, + { C_MOD_SYNTH_RECORD, &synth_record_load, &synth_record_unload, MOD_SCOPE_ANY }, + { C_MOD_DNSPROXY, &dnsproxy_load, &dnsproxy_unload, MOD_SCOPE_ANY }, + { C_MOD_ONLINE_SIGN, &online_sign_load, &online_sign_unload, MOD_SCOPE_ZONE, true }, #ifdef HAVE_ROSEDB - { C_MOD_ROSEDB, &rosedb_load, &rosedb_unload, MOD_SCOPE_ANY }, + { C_MOD_ROSEDB, &rosedb_load, &rosedb_unload, MOD_SCOPE_ANY }, #endif #if USE_DNSTAP - { C_MOD_DNSTAP, &dnstap_load, &dnstap_unload, MOD_SCOPE_ANY }, + { C_MOD_DNSTAP, &dnstap_load, &dnstap_unload, MOD_SCOPE_ANY }, #endif - { C_MOD_WHOAMI, &whoami_load, &whoami_unload, MOD_SCOPE_ANY }, - { C_MOD_NOUDP, &noudp_load, &noudp_unload, MOD_SCOPE_ANY }, - { NULL } + { C_MOD_WHOAMI, &whoami_load, &whoami_unload, MOD_SCOPE_ANY, true }, + { C_MOD_NOUDP, &noudp_load, &noudp_unload, MOD_SCOPE_ANY, true }, + { NULL } }; struct query_plan *query_plan_create(knot_mm_t *mm) @@ -114,7 +107,7 @@ int query_plan_step(struct query_plan *plan, int stage, qmodule_process_t proces return KNOT_EOK; } -static static_module_t *find_module(const yp_name_t *name) +static_module_t *find_module(const yp_name_t *name) { /* Search for the module by name. */ static_module_t *module = NULL; diff --git a/src/knot/nameserver/query_module.h b/src/knot/nameserver/query_module.h index 599afb73b20f2eecf3069f07563336a913ed9e83..1b7e129f6dd94b1ad0b27b3130d9f1599e3c7906 100644 --- a/src/knot/nameserver/query_module.h +++ b/src/knot/nameserver/query_module.h @@ -78,6 +78,14 @@ typedef int (*qmodule_load_t)(struct query_plan *plan, struct query_module *self typedef int (*qmodule_unload_t)(struct query_module *self); typedef int (*qmodule_process_t)(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx); +typedef struct static_module { + const yp_name_t *name; + qmodule_load_t load; + qmodule_unload_t unload; + unsigned scope; + bool opt_conf; +} static_module_t; + /*! * Query module is a dynamically loadable unit that can alter query processing plan. * Module requires load and unload callback handlers and is provided with a context @@ -110,6 +118,8 @@ struct query_plan { list_t stage[QUERY_PLAN_STAGES]; }; +static_module_t *find_module(const yp_name_t *name); + /*! \brief Create an empty query plan. */ struct query_plan *query_plan_create(knot_mm_t *mm); diff --git a/tests-extra/tools/dnstest/module.py b/tests-extra/tools/dnstest/module.py index 5b6457754c2e537a2ebbe69671f0cc0604a68c57..df40d466a7328edafe806b10be2f46793b542c46 100644 --- a/tests-extra/tools/dnstest/module.py +++ b/tests-extra/tools/dnstest/module.py @@ -16,6 +16,8 @@ class KnotModule(object): src_name = None # Module name in the configuration. conf_name = None + # Empty configuration + empty = False def __init__(self): self.conf_id = "id%s" % type(self).count @@ -47,9 +49,12 @@ class KnotModule(object): raise Skip("Module '%s' not detected" % cls.conf_name) def get_conf_ref(self): - return "%s/%s" % (self.conf_name, self.conf_id) + if self.empty: + return str(self.conf_name) + else: + return "%s/%s" % (self.conf_name, self.conf_id) - def get_conf(self): pass + def get_conf(self, conf=None): pass class ModSynthRecord(KnotModule): '''Automatic forward/reverse records module''' @@ -139,20 +144,11 @@ class ModWhoami(KnotModule): src_name = "whoami_load" conf_name = "mod-whoami" + empty = True def __init__(self): super().__init__() - def get_conf(self, conf=None): - if not conf: - conf = dnstest.config.KnotConf() - - conf.begin(self.conf_name) - conf.id_item("id", self.conf_id) - conf.end() - - return conf - class ModRosedb(KnotModule): '''Rosedb module''' diff --git a/tests/conf_tools.c b/tests/conf_tools.c index e3e450835948802cbe0841ca3bc387e08b9825da..a9f617ae41361f109aca8cbbc0941526b7bd2635 100644 --- a/tests/conf_tools.c +++ b/tests/conf_tools.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -140,7 +140,7 @@ int main(int argc, char *argv[]) /* Module id tests. */ mod_id_test("module/id", "\x06moduleid"); - mod_id_bad_test("module", KNOT_EINVAL); + mod_id_test("module", "\x06module"); mod_id_bad_test("module/", KNOT_EINVAL); mod_id_bad_test("/", KNOT_EINVAL); mod_id_bad_test("/id", KNOT_EINVAL);