]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: refactor stage 1
authorOto Šťáva <oto.stava@nic.cz>
Mon, 23 May 2022 10:18:38 +0000 (12:18 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Thu, 23 Jun 2022 10:16:57 +0000 (12:16 +0200)
31 files changed:
daemon/bindings/cache.c
daemon/bindings/event.c
daemon/bindings/modules.c
daemon/bindings/net.c
daemon/bindings/worker.c
daemon/engine.c
daemon/engine.h
daemon/ffimodule.c
daemon/ffimodule.h
daemon/io.c
daemon/lua/kres-gen-30.lua
daemon/lua/kres-gen-31.lua
daemon/lua/kres-gen.sh
daemon/lua/kres.lua
daemon/lua/sandbox.lua.in
daemon/main.c
daemon/network.c
daemon/network.h
daemon/proxyv2.c
daemon/proxyv2.h
daemon/tls.c
daemon/tls.h
daemon/tls_ephemeral_credentials.c
daemon/worker.c
daemon/worker.h
daemon/zimport.c
lib/resolve.c
lib/resolve.h
modules/edns_keepalive/edns_keepalive.c
modules/hints/hints.c
modules/nsid/nsid.c

index 4b1688228f715e734b8cd7848422722efab77c2e..8a848ec2ac96993b735a4a26d2380fb286b66a9f 100644 (file)
@@ -7,7 +7,7 @@
 /** @internal return cache, or throw lua error if not open */
 static struct kr_cache * cache_assert_open(lua_State *L)
 {
-       struct kr_cache *cache = &the_worker->engine->resolver.cache;
+       struct kr_cache *cache = &the_resolver->cache;
        if (kr_fails_assert(cache) || !kr_cache_is_open(cache))
                lua_error_p(L, "no cache is open yet, use cache.open() or cache.size, etc.");
        return cache;
@@ -16,12 +16,10 @@ static struct kr_cache * cache_assert_open(lua_State *L)
 /** Return available cached backends. */
 static int cache_backends(lua_State *L)
 {
-       struct engine *engine = the_worker->engine;
-
        lua_newtable(L);
-       for (unsigned i = 0; i < engine->backends.len; ++i) {
-               const struct kr_cdb_api *api = engine->backends.at[i];
-               lua_pushboolean(L, api == engine->resolver.cache.api);
+       for (unsigned i = 0; i < the_engine->backends.len; ++i) {
+               const struct kr_cdb_api *api = the_engine->backends.at[i];
+               lua_pushboolean(L, api == the_resolver->cache.api);
                lua_setfield(L, -2, api->name);
        }
        return 1;
@@ -99,16 +97,16 @@ static int cache_stats(lua_State *L)
        return 1;
 }
 
-static const struct kr_cdb_api *cache_select(struct engine *engine, const char **conf)
+static const struct kr_cdb_api *cache_select(const char **conf)
 {
        /* Return default backend */
        if (*conf == NULL || !strstr(*conf, "://")) {
-               return engine->backends.at[0];
+               return the_engine->backends.at[0];
        }
 
        /* Find storage backend from config prefix */
-       for (unsigned i = 0; i < engine->backends.len; ++i) {
-               const struct kr_cdb_api *api = engine->backends.at[i];
+       for (unsigned i = 0; i < the_engine->backends.len; ++i) {
+               const struct kr_cdb_api *api = the_engine->backends.at[i];
                if (strncmp(*conf, api->name, strlen(api->name)) == 0) {
                        *conf += strlen(api->name) + strlen("://");
                        return api;
@@ -170,8 +168,6 @@ static int cache_open(lua_State *L)
                lua_error_p(L, "expected 'open(number max_size, string config = \"\")'");
 
        /* Select cache storage backend */
-       struct engine *engine = the_worker->engine;
-
        lua_Integer csize_lua = lua_tointeger(L, 1);
        if (!(csize_lua >= 8192 && csize_lua < SIZE_MAX)) { /* min. is basically arbitrary */
                lua_error_p(L, "invalid cache size specified, it must be in range <8192, "
@@ -181,19 +177,19 @@ static int cache_open(lua_State *L)
 
        const char *conf = n > 1 ? lua_tostring(L, 2) : NULL;
        const char *uri = conf;
-       const struct kr_cdb_api *api = cache_select(engine, &conf);
+       const struct kr_cdb_api *api = cache_select(&conf);
        if (!api)
                lua_error_p(L, "unsupported cache backend");
 
        /* Close if already open */
-       kr_cache_close(&engine->resolver.cache);
+       kr_cache_close(&the_resolver->cache);
 
        /* Reopen cache */
        struct kr_cdb_opts opts = {
                (conf && strlen(conf)) ? conf : ".",
                cache_size
        };
-       int ret = kr_cache_open(&engine->resolver.cache, api, &opts, engine->pool);
+       int ret = kr_cache_open(&the_resolver->cache, api, &opts, &the_engine->pool);
        if (ret != 0) {
                char cwd[PATH_MAX];
                get_workdir(cwd, sizeof(cwd));
@@ -202,7 +198,7 @@ static int cache_open(lua_State *L)
        }
        /* Let's check_health() every five seconds to avoid keeping old cache alive
         * even in case of not having any work to do. */
-       ret = kr_cache_check_health(&engine->resolver.cache, 5000);
+       ret = kr_cache_check_health(&the_resolver->cache, 5000);
        if (ret != 0) {
                kr_log_error(CACHE, "periodic health check failed (ignored): %s\n",
                                kr_strerror(ret));
@@ -224,7 +220,7 @@ static int cache_open(lua_State *L)
 
 static int cache_close(lua_State *L)
 {
-       struct kr_cache *cache = &the_worker->engine->resolver.cache;
+       struct kr_cache *cache = &the_resolver->cache;
        if (!kr_cache_is_open(cache)) {
                return 0;
        }
@@ -264,8 +260,7 @@ static int cache_clear_everything(lua_State *L)
        lua_error_maybe(L, ret);
 
        /* Clear reputation tables */
-       struct kr_context *ctx = &the_worker->engine->resolver;
-       lru_reset(ctx->cache_cookie);
+       lru_reset(the_resolver->cache_cookie);
        lua_pushboolean(L, true);
        return 1;
 }
@@ -336,12 +331,10 @@ static int cache_get(lua_State *L)
  * in NS elections again. */
 static int cache_ns_tout(lua_State *L)
 {
-       struct kr_context *ctx = &the_worker->engine->resolver;
-
        /* Check parameters */
        int n = lua_gettop(L);
        if (n < 1) {
-               lua_pushinteger(L, ctx->cache_rtt_tout_retry_interval);
+               lua_pushinteger(L, the_resolver->cache_rtt_tout_retry_interval);
                return 1;
        }
 
@@ -354,8 +347,8 @@ static int cache_ns_tout(lua_State *L)
                                STR(UINT_MAX));
        }
 
-       ctx->cache_rtt_tout_retry_interval = interval_lua;
-       lua_pushinteger(L, ctx->cache_rtt_tout_retry_interval);
+       the_resolver->cache_rtt_tout_retry_interval = interval_lua;
+       lua_pushinteger(L, the_resolver->cache_rtt_tout_retry_interval);
        return 1;
 }
 
index 0c5a6ba97b8f53c01e18ab5993e19977b95049e6..cd0fb5453cf492821b5d19b044df96ce339c8db3 100644 (file)
@@ -9,7 +9,7 @@
 
 static void event_free(uv_timer_t *timer)
 {
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
        int ref = (intptr_t) timer->data;
        luaL_unref(L, LUA_REGISTRYINDEX, ref);
        free(timer);
@@ -17,7 +17,7 @@ static void event_free(uv_timer_t *timer)
 
 static void event_callback(uv_timer_t *timer)
 {
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
 
        /* Retrieve callback and execute */
        lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t) timer->data);
@@ -34,7 +34,7 @@ static void event_callback(uv_timer_t *timer)
 
 static void event_fdcallback(uv_poll_t* handle, int status, int events)
 {
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
 
        /* Retrieve callback and execute */
        lua_rawgeti(L, LUA_REGISTRYINDEX, (intptr_t) handle->data);
index 5116ff33c56d49aeb15ebb74e4b32a4eecf51647..00369dcbd327ff5d1b5d55b14018963012e9ab8b 100644 (file)
@@ -8,7 +8,7 @@
 /** List loaded modules */
 static int mod_list(lua_State *L)
 {
-       const module_array_t * const modules = &the_worker->engine->modules;
+       const module_array_t * const modules = engine_modules();
        lua_newtable(L);
        for (unsigned i = 0; i < modules->len; ++i) {
                struct kr_module *module = modules->at[i];
@@ -33,7 +33,7 @@ static int mod_load(lua_State *L)
        const char *precedence = strtok(NULL, " ");
        const char *ref = strtok(NULL, " ");
        /* Load engine module */
-       int ret = engine_register(the_worker->engine, name, precedence, ref);
+       int ret = engine_register(name, precedence, ref);
        free(declaration);
        if (ret != 0) {
                if (ret == kr_error(EIDRM)) {
@@ -55,7 +55,7 @@ static int mod_unload(lua_State *L)
        if (n != 1 || !lua_isstring(L, 1))
                lua_error_p(L, "expected 'unload(string name)'");
        /* Unload engine module */
-       int ret = engine_unregister(the_worker->engine, lua_tostring(L, 1));
+       int ret = engine_unregister(lua_tostring(L, 1));
        lua_error_maybe(L, ret);
 
        lua_pushboolean(L, 1);
index cd0a3e366f54346c2e46371a2c4fa69da06f39bb..52fa8cb50c6c156d853e55f1e2991eeb2a509f82 100644 (file)
@@ -110,7 +110,7 @@ static int net_list(lua_State *L)
 {
        lua_newtable(L);
        lua_pushinteger(L, 1);
-       trie_apply_with_key(the_worker->engine->net.endpoints, net_list_add, L);
+       trie_apply_with_key(the_network->endpoints, net_list_add, L);
        lua_pop(L, 1);
        return 1;
 }
@@ -134,21 +134,20 @@ static bool net_listen_addrs(lua_State *L, int port, endpoint_flags_t flags, int
        /* Case: string, representing a single address. */
        const char *str = lua_tostring(L, -1);
        if (str != NULL) {
-               struct network *net = &the_worker->engine->net;
                const bool is_unix = str[0] == '/';
                int ret = 0;
                if (!flags.kind && !flags.tls) { /* normal UDP or XDP */
                        flags.sock_type = SOCK_DGRAM;
-                       ret = network_listen(net, str, port, nic_queue, flags);
+                       ret = network_listen(str, port, nic_queue, flags);
                }
                if (!flags.kind && !flags.xdp && ret == 0) { /* common for TCP, DoT and DoH (v2) */
                        flags.sock_type = SOCK_STREAM;
-                       ret = network_listen(net, str, port, nic_queue, flags);
+                       ret = network_listen(str, port, nic_queue, flags);
                }
                if (flags.kind) {
                        flags.kind = strdup(flags.kind);
                        flags.sock_type = SOCK_STREAM; /* TODO: allow to override this? */
-                       ret = network_listen(net, str, (is_unix ? 0 : port), nic_queue, flags);
+                       ret = network_listen(str, (is_unix ? 0 : port), nic_queue, flags);
                }
                if (ret == 0) return true; /* success */
 
@@ -336,7 +335,6 @@ static void net_proxy_addr_put(lua_State *L, int family, trie_t *trie, int *i)
 /** Allow PROXYv2 headers for IP address. */
 static int net_proxy_allowed(lua_State *L)
 {
-       struct network *net = &the_worker->engine->net;
        int n = lua_gettop(L);
        int i = 1;
        const char *addr;
@@ -346,22 +344,22 @@ static int net_proxy_allowed(lua_State *L)
                lua_newtable(L);
                i = 1;
 
-               if (net->proxy_all4) {
+               if (the_network->proxy_all4) {
                        lua_pushinteger(L, i);
                        lua_pushstring(L, "0.0.0.0/0");
                        lua_settable(L, -3);
                        i += 1;
                } else {
-                       net_proxy_addr_put(L, AF_INET, net->proxy_addrs4, &i);
+                       net_proxy_addr_put(L, AF_INET, the_network->proxy_addrs4, &i);
                }
 
-               if (net->proxy_all6) {
+               if (the_network->proxy_all6) {
                        lua_pushinteger(L, i);
                        lua_pushstring(L, "::/0");
                        lua_settable(L, -3);
                        i += 1;
                } else {
-                       net_proxy_addr_put(L, AF_INET6, net->proxy_addrs6, &i);
+                       net_proxy_addr_put(L, AF_INET6, the_network->proxy_addrs6, &i);
                }
 
                return 1;
@@ -374,7 +372,7 @@ static int net_proxy_allowed(lua_State *L)
                lua_error_p(L, "net.proxy_allowed() argument must be string or table");
 
        /* Reset allowed proxy addresses */
-       network_proxy_reset(net);
+       network_proxy_reset();
 
        /* Add new proxy addresses */
        if (lua_istable(L, 1)) {
@@ -386,13 +384,13 @@ static int net_proxy_allowed(lua_State *L)
                        if (!lua_isstring(L, -1))
                                lua_error_p(L, "net.proxy_allowed() argument may only contain strings");
                        addr = lua_tostring(L, -1);
-                       int ret = network_proxy_allow(net, addr);
+                       int ret = network_proxy_allow(addr);
                        if (ret)
                                lua_error_p(L, "invalid argument");
                }
        } else if (lua_isstring(L, 1)) {
                addr = lua_tostring(L, 1);
-               int ret = network_proxy_allow(net, addr);
+               int ret = network_proxy_allow(addr);
                if (ret)
                        lua_error_p(L, "invalid argument");
        }
@@ -418,7 +416,7 @@ static int net_close(lua_State *L)
        if (!ok)
                lua_error_p(L, "expected 'close(string addr, [number port])'");
 
-       int ret = network_close(&the_worker->engine->net, addr, port);
+       int ret = network_close(addr, port);
        lua_pushboolean(L, ret == 0);
        return 1;
 }
@@ -488,11 +486,10 @@ static int net_interfaces(lua_State *L)
 /** Set UDP maximum payload size. */
 static int net_bufsize(lua_State *L)
 {
-       struct kr_context *ctx = &the_worker->engine->resolver;
        const int argc = lua_gettop(L);
        if (argc == 0) {
-               lua_pushinteger(L, knot_edns_get_payload(ctx->downstream_opt_rr));
-               lua_pushinteger(L, knot_edns_get_payload(ctx->upstream_opt_rr));
+               lua_pushinteger(L, knot_edns_get_payload(the_resolver->downstream_opt_rr));
+               lua_pushinteger(L, knot_edns_get_payload(the_resolver->upstream_opt_rr));
                return 2;
        }
 
@@ -500,8 +497,8 @@ static int net_bufsize(lua_State *L)
                int bufsize = lua_tointeger(L, 1);
                if (bufsize < 512 || bufsize > UINT16_MAX)
                        lua_error_p(L, "bufsize must be within <512, " STR(UINT16_MAX) ">");
-               knot_edns_set_payload(ctx->downstream_opt_rr, (uint16_t)bufsize);
-               knot_edns_set_payload(ctx->upstream_opt_rr, (uint16_t)bufsize);
+               knot_edns_set_payload(the_resolver->downstream_opt_rr, (uint16_t)bufsize);
+               knot_edns_set_payload(the_resolver->upstream_opt_rr, (uint16_t)bufsize);
        } else if (argc == 2) {
                int bufsize_downstream = lua_tointeger(L, 1);
                int bufsize_upstream = lua_tointeger(L, 2);
@@ -509,8 +506,8 @@ static int net_bufsize(lua_State *L)
                    || bufsize_downstream > UINT16_MAX || bufsize_upstream > UINT16_MAX) {
                        lua_error_p(L, "bufsize must be within <512, " STR(UINT16_MAX) ">");
                }
-               knot_edns_set_payload(ctx->downstream_opt_rr, (uint16_t)bufsize_downstream);
-               knot_edns_set_payload(ctx->upstream_opt_rr, (uint16_t)bufsize_upstream);
+               knot_edns_set_payload(the_resolver->downstream_opt_rr, (uint16_t)bufsize_downstream);
+               knot_edns_set_payload(the_resolver->upstream_opt_rr, (uint16_t)bufsize_upstream);
        }
        return 0;
 }
@@ -518,39 +515,37 @@ static int net_bufsize(lua_State *L)
 /** Set TCP pipelining size. */
 static int net_pipeline(lua_State *L)
 {
-       struct worker_ctx *worker = the_worker;
-       if (!worker) {
+       if (!the_worker) {
                return 0;
        }
        if (!lua_isnumber(L, 1)) {
-               lua_pushinteger(L, worker->tcp_pipeline_max);
+               lua_pushinteger(L, the_worker->tcp_pipeline_max);
                return 1;
        }
        int len = lua_tointeger(L, 1);
        if (len < 0 || len > UINT16_MAX)
                lua_error_p(L, "tcp_pipeline must be within <0, " STR(UINT16_MAX) ">");
-       worker->tcp_pipeline_max = len;
+       the_worker->tcp_pipeline_max = len;
        lua_pushinteger(L, len);
        return 1;
 }
 
 static int net_tls(lua_State *L)
 {
-       struct network *net = &the_worker->engine->net;
-       if (!net) {
+       if (kr_fails_assert(the_network)) {
                return 0;
        }
 
        /* Only return current credentials. */
        if (lua_gettop(L) == 0) {
                /* No credentials configured yet. */
-               if (!net->tls_credentials) {
+               if (!the_network->tls_credentials) {
                        return 0;
                }
                lua_newtable(L);
-               lua_pushstring(L, net->tls_credentials->tls_cert);
+               lua_pushstring(L, the_network->tls_credentials->tls_cert);
                lua_setfield(L, -2, "cert_file");
-               lua_pushstring(L, net->tls_credentials->tls_key);
+               lua_pushstring(L, the_network->tls_credentials->tls_key);
                lua_setfield(L, -2, "key_file");
                return 1;
        }
@@ -558,7 +553,7 @@ static int net_tls(lua_State *L)
        if ((lua_gettop(L) != 2) || !lua_isstring(L, 1) || !lua_isstring(L, 2))
                lua_error_p(L, "net.tls takes two parameters: (\"cert_file\", \"key_file\")");
 
-       int r = tls_certificate_set(net, lua_tostring(L, 1), lua_tostring(L, 2));
+       int r = tls_certificate_set(lua_tostring(L, 1), lua_tostring(L, 2));
        lua_error_maybe(L, r);
 
        lua_pushboolean(L, true);
@@ -714,9 +709,8 @@ static int net_tls_client(lua_State *L)
        /* TODO idea: allow starting the lua table with *multiple* IP targets,
         * meaning the authentication config should be applied to each.
         */
-       struct network *net = &the_worker->engine->net;
        if (lua_gettop(L) == 0)
-               return tls_params2lua(L, net->tls_client_params);
+               return tls_params2lua(L, the_network->tls_client_params);
        /* Various basic sanity-checking. */
        if (lua_gettop(L) != 1 || !lua_istable(L, 1))
                lua_error_maybe(L, EINVAL);
@@ -882,7 +876,7 @@ static int net_tls_client(lua_State *L)
        if (!addr)
                lua_error_p(L, "address '%s' could not be converted", addr_str);
        tls_client_param_t **oldcfgp = tls_client_param_getptr(
-                       &net->tls_client_params, addr, true);
+                       &the_network->tls_client_params, addr, true);
        free_const(addr);
        if (!oldcfgp)
                lua_error_p(L, "internal error when extending tls_client_params map");
@@ -925,8 +919,7 @@ int net_tls_client_clear(lua_State *L)
        if (!addr)
                lua_error_p(L, "invalid IP address");
        /* Do the actual removal. */
-       struct network *net = &the_worker->engine->net;
-       int r = tls_client_param_remove(net->tls_client_params, addr);
+       int r = tls_client_param_remove(the_network->tls_client_params, addr);
        free_const(addr);
        lua_error_maybe(L, r);
        lua_pushboolean(L, true);
@@ -935,18 +928,16 @@ int net_tls_client_clear(lua_State *L)
 
 static int net_tls_padding(lua_State *L)
 {
-       struct kr_context *ctx = &the_worker->engine->resolver;
-
        /* Only return current padding. */
        if (lua_gettop(L) == 0) {
-               if (ctx->tls_padding < 0) {
+               if (the_resolver->tls_padding < 0) {
                        lua_pushboolean(L, true);
                        return 1;
-               } else if (ctx->tls_padding == 0) {
+               } else if (the_resolver->tls_padding == 0) {
                        lua_pushboolean(L, false);
                        return 1;
                }
-               lua_pushinteger(L, ctx->tls_padding);
+               lua_pushinteger(L, the_resolver->tls_padding);
                return 1;
        }
 
@@ -957,15 +948,15 @@ static int net_tls_padding(lua_State *L)
        if (lua_isboolean(L, 1)) {
                bool x = lua_toboolean(L, 1);
                if (x) {
-                       ctx->tls_padding = -1;
+                       the_resolver->tls_padding = -1;
                } else {
-                       ctx->tls_padding = 0;
+                       the_resolver->tls_padding = 0;
                }
        } else if (lua_isnumber(L, 1)) {
                int padding = lua_tointeger(L, 1);
                if ((padding < 0) || (padding > MAX_TLS_PADDING))
                        lua_error_p(L, "%s", errstr);
-               ctx->tls_padding = padding;
+               the_resolver->tls_padding = padding;
        } else {
                lua_error_p(L, "%s", errstr);
        }
@@ -978,8 +969,6 @@ static int net_tls_padding(lua_State *L)
 
 static int net_tls_sticket_secret_string(lua_State *L)
 {
-       struct network *net = &the_worker->engine->net;
-
        size_t secret_len;
        const char *secret;
 
@@ -999,10 +988,10 @@ static int net_tls_sticket_secret_string(lua_State *L)
                }
        }
 
-       tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
-       net->tls_session_ticket_ctx =
-               tls_session_ticket_ctx_create(net->loop, secret, secret_len);
-       if (net->tls_session_ticket_ctx == NULL) {
+       tls_session_ticket_ctx_destroy(the_network->tls_session_ticket_ctx);
+       the_network->tls_session_ticket_ctx =
+               tls_session_ticket_ctx_create(the_network->loop, secret, secret_len);
+       if (the_network->tls_session_ticket_ctx == NULL) {
                lua_error_p(L,
                        "net.tls_sticket_secret_string - can't create session ticket context");
        }
@@ -1044,12 +1033,10 @@ static int net_tls_sticket_secret_file(lua_State *L)
        }
        fclose(fp);
 
-       struct network *net = &the_worker->engine->net;
-
-       tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
-       net->tls_session_ticket_ctx =
-               tls_session_ticket_ctx_create(net->loop, secret_buf, secret_len);
-       if (net->tls_session_ticket_ctx == NULL) {
+       tls_session_ticket_ctx_destroy(the_network->tls_session_ticket_ctx);
+       the_network->tls_session_ticket_ctx =
+               tls_session_ticket_ctx_create(the_network->loop, secret_buf, secret_len);
+       if (the_network->tls_session_ticket_ctx == NULL) {
                lua_error_p(L,
                        "net.tls_sticket_secret_file - can't create session ticket context");
        }
@@ -1131,14 +1118,12 @@ static int net_update_timeout(lua_State *L, uint64_t *timeout, const char *name)
 
 static int net_tcp_in_idle(lua_State *L)
 {
-       struct network *net = &the_worker->engine->net;
-       return net_update_timeout(L, &net->tcp.in_idle_timeout, "net.tcp_in_idle");
+       return net_update_timeout(L, &the_network->tcp.in_idle_timeout, "net.tcp_in_idle");
 }
 
 static int net_tls_handshake_timeout(lua_State *L)
 {
-       struct network *net = &the_worker->engine->net;
-       return net_update_timeout(L, &net->tcp.tls_handshake_timeout, "net.tls_handshake_timeout");
+       return net_update_timeout(L, &the_network->tcp.tls_handshake_timeout, "net.tls_handshake_timeout");
 }
 
 static int net_bpf_set(lua_State *L)
@@ -1159,7 +1144,7 @@ static int net_bpf_set(lua_State *L)
        }
        lua_pop(L, 1);
 
-       if (network_set_bpf(&the_worker->engine->net, progfd) == 0) {
+       if (network_set_bpf(progfd) == 0) {
                lua_error_p(L, "failed to attach BPF program to some networks: %s",
                                kr_strerror(errno));
        }
@@ -1178,7 +1163,7 @@ static int net_bpf_clear(lua_State *L)
 
 #if __linux__
 
-       network_clear_bpf(&the_worker->engine->net);
+       network_clear_bpf();
 
        lua_pushboolean(L, 1);
        return 1;
@@ -1197,12 +1182,11 @@ static int net_register_endpoint_kind(lua_State *L)
        }
        size_t kind_len;
        const char *kind = lua_tolstring(L, 1, &kind_len);
-       struct network *net = &the_worker->engine->net;
 
        /* Unregistering */
        if (param_count == 1) {
                void *val;
-               if (trie_del(net->endpoint_kinds, kind, kind_len, &val) == KNOT_EOK) {
+               if (trie_del(the_network->endpoint_kinds, kind, kind_len, &val) == KNOT_EOK) {
                        const int fun_id = (char *)val - (char *)NULL;
                        luaL_unref(L, LUA_REGISTRYINDEX, fun_id);
                        return 0;
@@ -1217,7 +1201,7 @@ static int net_register_endpoint_kind(lua_State *L)
        }
        const int fun_id = luaL_ref(L, LUA_REGISTRYINDEX);
                /* ^^ The function is on top of the stack, incidentally. */
-       void **pp = trie_get_ins(net->endpoint_kinds, kind, kind_len);
+       void **pp = trie_get_ins(the_network->endpoint_kinds, kind, kind_len);
        if (!pp) lua_error_maybe(L, kr_error(ENOMEM));
        if (*pp != NULL || !strcasecmp(kind, "dns") || !strcasecmp(kind, "tls"))
                lua_error_p(L, "attempt to register known kind '%s'\n", kind);
index f0a533f5309b55bb39f106cffbddb5f8856574a9..537a1bc358378fe1028ab97c6b8311eb2919fbba 100644 (file)
@@ -13,37 +13,36 @@ static inline double getseconds(uv_timeval_t *tv)
 /** Return worker statistics. */
 static int wrk_stats(lua_State *L)
 {
-       struct worker_ctx *worker = the_worker;
-       if (!worker) {
+       if (kr_fails_assert(the_worker)) {
                return 0;
        }
        lua_newtable(L);
-       lua_pushnumber(L, worker->stats.queries);
+       lua_pushnumber(L, the_worker->stats.queries);
        lua_setfield(L, -2, "queries");
-       lua_pushnumber(L, worker->stats.concurrent);
+       lua_pushnumber(L, the_worker->stats.concurrent);
        lua_setfield(L, -2, "concurrent");
-       lua_pushnumber(L, worker->stats.dropped);
+       lua_pushnumber(L, the_worker->stats.dropped);
        lua_setfield(L, -2, "dropped");
 
-       lua_pushnumber(L, worker->stats.timeout);
+       lua_pushnumber(L, the_worker->stats.timeout);
        lua_setfield(L, -2, "timeout");
-       lua_pushnumber(L, worker->stats.udp);
+       lua_pushnumber(L, the_worker->stats.udp);
        lua_setfield(L, -2, "udp");
-       lua_pushnumber(L, worker->stats.tcp);
+       lua_pushnumber(L, the_worker->stats.tcp);
        lua_setfield(L, -2, "tcp");
-       lua_pushnumber(L, worker->stats.tls);
+       lua_pushnumber(L, the_worker->stats.tls);
        lua_setfield(L, -2, "tls");
-       lua_pushnumber(L, worker->stats.ipv4);
+       lua_pushnumber(L, the_worker->stats.ipv4);
        lua_setfield(L, -2, "ipv4");
-       lua_pushnumber(L, worker->stats.ipv6);
+       lua_pushnumber(L, the_worker->stats.ipv6);
        lua_setfield(L, -2, "ipv6");
-       lua_pushnumber(L, worker->stats.err_udp);
+       lua_pushnumber(L, the_worker->stats.err_udp);
        lua_setfield(L, -2, "err_udp");
-       lua_pushnumber(L, worker->stats.err_tcp);
+       lua_pushnumber(L, the_worker->stats.err_tcp);
        lua_setfield(L, -2, "err_tcp");
-       lua_pushnumber(L, worker->stats.err_tls);
+       lua_pushnumber(L, the_worker->stats.err_tls);
        lua_setfield(L, -2, "err_tls");
-       lua_pushnumber(L, worker->stats.err_http);
+       lua_pushnumber(L, the_worker->stats.err_http);
        lua_setfield(L, -2, "err_http");
 
        /* Add subset of rusage that represents counters. */
index d18ed11d7d20d01f17a1afb99ae211178c5263a6..2e456b1352c8e54246c49b6c8274b904e26d7332 100644 (file)
 #include "lib/dnssec/ta.h"
 #include "lib/log.h"
 
-/* Magic defaults for the engine. */
-#ifndef LRU_RTT_SIZE
-#define LRU_RTT_SIZE 65536 /**< NS RTT cache size */
-#endif
-#ifndef LRU_REP_SIZE
-#define LRU_REP_SIZE (LRU_RTT_SIZE / 4) /**< NS reputation cache size */
-#endif
-#ifndef LRU_COOKIES_SIZE
-       #if ENABLE_COOKIES
-       #define LRU_COOKIES_SIZE LRU_RTT_SIZE /**< DNS cookies cache size. */
-       #else
-       #define LRU_COOKIES_SIZE LRU_ASSOC /* simpler than guards everywhere */
-       #endif
-#endif
-
-/**@internal Maximum number of incomplete TCP connections in queue.
-* Default is from empirical testing - in our case, more isn't necessarily better.
-* See https://gitlab.nic.cz/knot/knot-resolver/-/merge_requests/968
-* */
-#ifndef TCP_BACKLOG_DEFAULT
-#define TCP_BACKLOG_DEFAULT 128
-#endif
-
 /* Cleanup engine state every 5 minutes */
 const size_t CLEANUP_TIMER = 5*60*1000;
 
@@ -64,6 +41,9 @@ const size_t CLEANUP_TIMER = 5*60*1000;
  */
 struct args *the_args;
 
+static struct engine engine = {0};
+struct engine *the_engine = NULL;
+
 
 /** Print help and available commands. */
 static int l_help(lua_State *L)
@@ -140,7 +120,7 @@ static int l_setuser(lua_State *L)
 /** Quit current executable. */
 static int l_quit(lua_State *L)
 {
-       engine_stop(the_worker->engine);
+       engine_stop();
        return 0;
 }
 
@@ -257,22 +237,19 @@ bad_call:
        lua_error_p(L, "takes a table of string groups as parameter or nothing");
 }
 
-char *engine_get_hostname(struct engine *engine) {
+char *engine_get_hostname(void) {
        static char hostname_str[KNOT_DNAME_MAXLEN];
-       if (!engine) {
-               return NULL;
-       }
 
-       if (!engine->hostname) {
+       if (!the_engine->hostname) {
                if (gethostname(hostname_str, sizeof(hostname_str)) != 0)
                        return NULL;
                return hostname_str;
        }
-       return engine->hostname;
+       return the_engine->hostname;
 }
 
-int engine_set_hostname(struct engine *engine, const char *hostname) {
-       if (!engine || !hostname) {
+int engine_set_hostname(const char *hostname) {
+       if (!hostname) {
                return kr_error(EINVAL);
        }
 
@@ -280,11 +257,11 @@ int engine_set_hostname(struct engine *engine, const char *hostname) {
        if (!new_hostname) {
                return kr_error(ENOMEM);
        }
-       if (engine->hostname) {
-               free(engine->hostname);
+       if (the_engine->hostname) {
+               free(the_engine->hostname);
        }
-       engine->hostname = new_hostname;
-       network_new_hostname(&engine->net, engine);
+       the_engine->hostname = new_hostname;
+       network_new_hostname();
 
        return 0;
 }
@@ -292,18 +269,17 @@ int engine_set_hostname(struct engine *engine, const char *hostname) {
 /** Return hostname. */
 static int l_hostname(lua_State *L)
 {
-       struct engine *engine = the_worker->engine;
        if (lua_gettop(L) == 0) {
-               lua_pushstring(L, engine_get_hostname(engine));
+               lua_pushstring(L, engine_get_hostname());
                return 1;
        }
        if ((lua_gettop(L) != 1) || !lua_isstring(L, 1))
                lua_error_p(L, "hostname takes at most one parameter: (\"fqdn\")");
 
-       if (engine_set_hostname(engine, lua_tostring(L, 1)) != 0)
+       if (engine_set_hostname(lua_tostring(L, 1)) != 0)
                lua_error_p(L, "setting hostname failed");
 
-       lua_pushstring(L, engine_get_hostname(engine));
+       lua_pushstring(L, engine_get_hostname());
        return 1;
 }
 
@@ -317,10 +293,9 @@ static int l_package_version(lua_State *L)
 /** Load root hints from zonefile. */
 static int l_hint_root_file(lua_State *L)
 {
-       struct kr_context *ctx = &the_worker->engine->resolver;
        const char *file = lua_tostring(L, 1);
 
-       const char *err = engine_hint_root_file(ctx, file);
+       const char *err = engine_hint_root_file(file);
        if (err) {
                if (!file) {
                        file = ROOTHINTS;
@@ -343,15 +318,15 @@ static void roothints_add(zs_scanner_t *zs)
                kr_zonecut_add(hints, zs->r_owner, zs->r_data, zs->r_data_length);
        }
 }
-const char* engine_hint_root_file(struct kr_context *ctx, const char *file)
+const char* engine_hint_root_file(const char *file)
 {
        if (!file) {
                file = ROOTHINTS;
        }
-       if (strlen(file) == 0 || !ctx) {
+       if (strlen(file) == 0) {
                return "invalid parameters";
        }
-       struct kr_zonecut *root_hints = &ctx->root_hints;
+       struct kr_zonecut *root_hints = &the_resolver->root_hints;
 
        zs_scanner_t zs;
        if (zs_init(&zs, ".", 1, 0) != 0) {
@@ -482,86 +457,51 @@ static int l_fromjson(lua_State *L)
  * Engine API.
  */
 
-static int init_resolver(struct engine *engine)
-{
-       /* Note: whole *engine had been zeroed by engine_init(). */
-       struct kr_context * const ctx = &engine->resolver;
-       /* Default options (request flags). */
-       ctx->options.REORDER_RR = true;
-
-       /* Open resolution context */
-       ctx->trust_anchors = trie_create(NULL);
-       ctx->negative_anchors = trie_create(NULL);
-       ctx->pool = engine->pool;
-       ctx->modules = &engine->modules;
-       ctx->cache_rtt_tout_retry_interval = KR_NS_TIMEOUT_RETRY_INTERVAL;
-       /* Create OPT RR */
-       ctx->downstream_opt_rr = mm_alloc(engine->pool, sizeof(knot_rrset_t));
-       ctx->upstream_opt_rr = mm_alloc(engine->pool, sizeof(knot_rrset_t));
-       if (!ctx->downstream_opt_rr || !ctx->upstream_opt_rr) {
-               return kr_error(ENOMEM);
-       }
-       knot_edns_init(ctx->downstream_opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
-       knot_edns_init(ctx->upstream_opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
-       /* Use default TLS padding */
-       ctx->tls_padding = -1;
-       /* Empty init; filled via ./lua/postconfig.lua */
-       kr_zonecut_init(&ctx->root_hints, (const uint8_t *)"", engine->pool);
-       lru_create(&ctx->cache_cookie, LRU_COOKIES_SIZE, NULL, NULL);
-
-       /* Load basic modules */
-       engine_register(engine, "iterate", NULL, NULL);
-       engine_register(engine, "validate", NULL, NULL);
-       engine_register(engine, "cache", NULL, NULL);
-
-       return array_push(engine->backends, kr_cdb_lmdb());
-}
-
-static int init_state(struct engine *engine)
+static int init_state(void)
 {
        /* Initialize Lua state */
-       engine->L = luaL_newstate();
-       if (engine->L == NULL) {
+       the_engine->L = luaL_newstate();
+       if (the_engine->L == NULL) {
                return kr_error(ENOMEM);
        }
        /* Initialize used libraries. */
-       luaL_openlibs(engine->L);
+       luaL_openlibs(the_engine->L);
        /* Global functions */
-       lua_pushcfunction(engine->L, l_help);
-       lua_setglobal(engine->L, "help");
-       lua_pushcfunction(engine->L, l_quit);
-       lua_setglobal(engine->L, "quit");
-       lua_pushcfunction(engine->L, l_hostname);
-       lua_setglobal(engine->L, "hostname");
-       lua_pushcfunction(engine->L, l_package_version);
-       lua_setglobal(engine->L, "package_version");
-       lua_pushcfunction(engine->L, l_verbose);
-       lua_setglobal(engine->L, "verbose");
-       lua_pushcfunction(engine->L, l_log_level);
-       lua_setglobal(engine->L, "log_level");
-       lua_pushcfunction(engine->L, l_log_target);
-       lua_setglobal(engine->L, "log_target");
-       lua_pushcfunction(engine->L, l_log_groups);
-       lua_setglobal(engine->L, "log_groups");
-       lua_pushcfunction(engine->L, l_setuser);
-       lua_setglobal(engine->L, "user");
-       lua_pushcfunction(engine->L, l_hint_root_file);
-       lua_setglobal(engine->L, "_hint_root_file");
-       lua_pushliteral(engine->L, libknot_SONAME);
-       lua_setglobal(engine->L, "libknot_SONAME");
-       lua_pushliteral(engine->L, libzscanner_SONAME);
-       lua_setglobal(engine->L, "libzscanner_SONAME");
-       lua_pushcfunction(engine->L, l_tojson);
-       lua_setglobal(engine->L, "tojson");
-       lua_pushcfunction(engine->L, l_fromjson);
-       lua_setglobal(engine->L, "fromjson");
+       lua_pushcfunction(the_engine->L, l_help);
+       lua_setglobal(the_engine->L, "help");
+       lua_pushcfunction(the_engine->L, l_quit);
+       lua_setglobal(the_engine->L, "quit");
+       lua_pushcfunction(the_engine->L, l_hostname);
+       lua_setglobal(the_engine->L, "hostname");
+       lua_pushcfunction(the_engine->L, l_package_version);
+       lua_setglobal(the_engine->L, "package_version");
+       lua_pushcfunction(the_engine->L, l_verbose);
+       lua_setglobal(the_engine->L, "verbose");
+       lua_pushcfunction(the_engine->L, l_log_level);
+       lua_setglobal(the_engine->L, "log_level");
+       lua_pushcfunction(the_engine->L, l_log_target);
+       lua_setglobal(the_engine->L, "log_target");
+       lua_pushcfunction(the_engine->L, l_log_groups);
+       lua_setglobal(the_engine->L, "log_groups");
+       lua_pushcfunction(the_engine->L, l_setuser);
+       lua_setglobal(the_engine->L, "user");
+       lua_pushcfunction(the_engine->L, l_hint_root_file);
+       lua_setglobal(the_engine->L, "_hint_root_file");
+       lua_pushliteral(the_engine->L, libknot_SONAME);
+       lua_setglobal(the_engine->L, "libknot_SONAME");
+       lua_pushliteral(the_engine->L, libzscanner_SONAME);
+       lua_setglobal(the_engine->L, "libzscanner_SONAME");
+       lua_pushcfunction(the_engine->L, l_tojson);
+       lua_setglobal(the_engine->L, "tojson");
+       lua_pushcfunction(the_engine->L, l_fromjson);
+       lua_setglobal(the_engine->L, "fromjson");
        /* Random number generator */
-       lua_getfield(engine->L, LUA_GLOBALSINDEX, "math");
-       lua_getfield(engine->L, -1, "randomseed");
-       lua_remove(engine->L, -2);
+       lua_getfield(the_engine->L, LUA_GLOBALSINDEX, "math");
+       lua_getfield(the_engine->L, -1, "randomseed");
+       lua_remove(the_engine->L, -2);
        lua_Number seed = kr_rand_bytes(sizeof(lua_Number));
-       lua_pushnumber(engine->L, seed);
-       lua_call(engine->L, 1, 0);
+       lua_pushnumber(the_engine->L, seed);
+       lua_call(the_engine->L, 1, 0);
        return kr_ok();
 }
 
@@ -570,7 +510,7 @@ static int init_state(struct engine *engine)
  * KRESD_COVERAGE_STATS environment variable.
  * Do nothing if the variable is not set.
  */
-static void init_measurement(struct engine *engine)
+static void init_measurement(void)
 {
        const char * const statspath = getenv("KRESD_COVERAGE_STATS");
        if (!statspath)
@@ -588,20 +528,16 @@ static void init_measurement(struct engine *engine)
        if (kr_fails_assert(ret > 0))
                return;
 
-       ret = luaL_loadstring(engine->L, snippet);
+       ret = luaL_loadstring(the_engine->L, snippet);
        if (kr_fails_assert(ret == 0)) {
                free(snippet);
                return;
        }
-       lua_call(engine->L, 0, 0);
+       lua_call(the_engine->L, 0, 0);
        free(snippet);
 }
 
-int init_lua(struct engine *engine) {
-       if (!engine) {
-               return kr_error(EINVAL);
-       }
-
+int init_lua(void) {
        /* Use libdir path for including Lua scripts */
        char l_paths[MAXPATHLEN] = { 0 };
        #pragma GCC diagnostic push
@@ -615,44 +551,44 @@ int init_lua(struct engine *engine) {
                 LIBDIR, LIBEXT);
        #pragma GCC diagnostic pop
 
-       int ret = l_dobytecode(engine->L, l_paths, strlen(l_paths), "");
+       int ret = l_dobytecode(the_engine->L, l_paths, strlen(l_paths), "");
        if (ret != 0) {
-               lua_pop(engine->L, 1);
+               lua_pop(the_engine->L, 1);
                return ret;
        }
        return 0;
 }
 
 
-int engine_init(struct engine *engine, knot_mm_t *pool)
+int engine_init(void)
 {
-       if (engine == NULL) {
-               return kr_error(EINVAL);
-       }
-
-       memset(engine, 0, sizeof(*engine));
-       engine->pool = pool;
+       kr_require(!the_engine);
+       the_engine = &engine;
+       mm_ctx_mempool(&the_engine->pool, MM_DEFAULT_BLKSIZE);
 
        /* Initialize state */
-       int ret = init_state(engine);
+       int ret = init_state();
        if (ret != 0) {
-               engine_deinit(engine);
+               engine_deinit();
                return ret;
        }
-       init_measurement(engine);
-       /* Initialize resolver */
-       ret = init_resolver(engine);
+       init_measurement();
+
+       /* Load basic modules */
+       engine_register("iterate", NULL, NULL);
+       engine_register("validate", NULL, NULL);
+       engine_register("cache", NULL, NULL);
+
+       ret = array_push(the_engine->backends, kr_cdb_lmdb());
        if (ret != 0) {
-               engine_deinit(engine);
+               engine_deinit();
                return ret;
        }
-       /* Initialize network */
-       network_init(&engine->net, uv_default_loop(), TCP_BACKLOG_DEFAULT);
 
        /* Initialize lua */
-       ret = init_lua(engine);
+       ret = init_lua();
        if (ret != 0) {
-               engine_deinit(engine);
+               engine_deinit();
                return ret;
        }
 
@@ -660,21 +596,21 @@ int engine_init(struct engine *engine, knot_mm_t *pool)
 }
 
 /** Unregister a (found) module */
-static void engine_unload(struct engine *engine, struct kr_module *module)
+static void engine_unload(struct kr_module *module)
 {
        auto_free char *name = module->name ? strdup(module->name) : NULL;
        kr_module_unload(module); /* beware: lua/C mix, could be confusing */
        /* Clear in Lua world, but not for embedded modules ('cache' in particular). */
        if (name && !kr_module_get_embedded(name)) {
-               lua_pushnil(engine->L);
-               lua_setglobal(engine->L, name);
+               lua_pushnil(the_engine->L);
+               lua_setglobal(the_engine->L, name);
        }
        free(module);
 }
 
-void engine_deinit(struct engine *engine)
+void engine_deinit(void)
 {
-       if (!engine || kr_fails_assert(engine->L))
+       if (kr_fails_assert(the_engine->L))
                return;
        /* Only close sockets and services; no need to clean up mempool. */
 
@@ -682,28 +618,20 @@ void engine_deinit(struct engine *engine)
         * then we can unload modules during which we still want
         * e.g. the endpoint kind registry to work (inside ->net),
         * and this registry deinitialization uses the lua state. */
-       network_close_force(&engine->net);
-       for (size_t i = 0; i < engine->modules.len; ++i) {
-               engine_unload(engine, engine->modules.at[i]);
+       for (size_t i = 0; i < the_engine->modules.len; ++i) {
+               engine_unload(the_engine->modules.at[i]);
        }
-       kr_zonecut_deinit(&engine->resolver.root_hints);
-       kr_cache_close(&engine->resolver.cache);
 
-       /* The LRUs are currently malloc-ated and need to be freed. */
-       lru_free(engine->resolver.cache_cookie);
-
-       network_deinit(&engine->net);
-       ffimodule_deinit(engine->L);
-       lua_close(engine->L);
+       ffimodule_deinit(the_engine->L);
+       lua_close(the_engine->L);
 
        /* Free data structures */
-       array_clear(engine->modules);
-       array_clear(engine->backends);
-       kr_ta_clear(engine->resolver.trust_anchors);
-       trie_free(engine->resolver.trust_anchors);
-       kr_ta_clear(engine->resolver.negative_anchors);
-       trie_free(engine->resolver.negative_anchors);
-       free(engine->hostname);
+       array_clear(the_engine->modules);
+       array_clear(the_engine->backends);
+       free(the_engine->hostname);
+       mp_delete(the_engine->pool.ctx);
+
+       the_engine = NULL;
 }
 
 int engine_pcall(lua_State *L, int argc)
@@ -726,20 +654,20 @@ int engine_cmd(lua_State *L, const char *str, bool raw)
        return engine_pcall(L, 2);
 }
 
-int engine_load_sandbox(struct engine *engine)
+int engine_load_sandbox(void)
 {
        /* Init environment */
-       int ret = luaL_dofile(engine->L, LIBDIR "/sandbox.lua");
+       int ret = luaL_dofile(the_engine->L, LIBDIR "/sandbox.lua");
        if (ret != 0) {
-               kr_log_error(SYSTEM, "error %s\n", lua_tostring(engine->L, -1));
-               lua_pop(engine->L, 1);
+               kr_log_error(SYSTEM, "error %s\n", lua_tostring(the_engine->L, -1));
+               lua_pop(the_engine->L, 1);
                return kr_error(ENOEXEC);
        }
-       ret = ffimodule_init(engine->L);
+       ret = ffimodule_init(the_engine->L);
        return ret;
 }
 
-int engine_loadconf(struct engine *engine, const char *config_path)
+int engine_loadconf(const char *config_path)
 {
        if (kr_fails_assert(config_path))
                return kr_error(EINVAL);
@@ -748,28 +676,25 @@ int engine_loadconf(struct engine *engine, const char *config_path)
        get_workdir(cwd, sizeof(cwd));
        kr_log_debug(SYSTEM, "loading config '%s' (workdir '%s')\n", config_path, cwd);
 
-       int ret = luaL_dofile(engine->L, config_path);
+       int ret = luaL_dofile(the_engine->L, config_path);
        if (ret != 0) {
                kr_log_error(SYSTEM, "error while loading config: "
-                       "%s (workdir '%s')\n", lua_tostring(engine->L, -1), cwd);
-               lua_pop(engine->L, 1);
+                       "%s (workdir '%s')\n", lua_tostring(the_engine->L, -1), cwd);
+               lua_pop(the_engine->L, 1);
        }
        return ret;
 }
 
-int engine_start(struct engine *engine)
+int engine_start(void)
 {
        /* Clean up stack */
-       lua_settop(engine->L, 0);
+       lua_settop(the_engine->L, 0);
 
        return kr_ok();
 }
 
-void engine_stop(struct engine *engine)
+void engine_stop(void)
 {
-       if (!engine) {
-               return;
-       }
        uv_stop(uv_default_loop());
 }
 
@@ -787,14 +712,14 @@ static size_t module_find(module_array_t *mod_list, const char *name)
        return found;
 }
 
-int engine_register(struct engine *engine, const char *name, const char *precedence, const char* ref)
+int engine_register(const char *name, const char *precedence, const char* ref)
 {
-       if (kr_fails_assert(engine && name))
+       if (kr_fails_assert(name))
                return kr_error(EINVAL);
        /* Make sure module is unloaded */
-       (void) engine_unregister(engine, name);
+       (void) engine_unregister(name);
        /* Find the index of referenced module. */
-       module_array_t *mod_list = &engine->modules;
+       module_array_t *mod_list = &the_engine->modules;
        size_t ref_pos = mod_list->len;
        if (precedence && ref) {
                ref_pos = module_find(mod_list, ref);
@@ -807,13 +732,13 @@ int engine_register(struct engine *engine, const char *name, const char *precede
        if (!module) {
                return kr_error(ENOMEM);
        }
-       module->data = engine; /*< some outside modules may still use this value */
+       module->data = the_engine; /*< some outside modules may still use this value */
 
        int ret = kr_module_load(module, name, LIBDIR "/kres_modules");
        if (ret == 0) {
                /* We have a C module, loaded and init() was called.
                 * Now we need to prepare the lua side. */
-               lua_State *L = engine->L;
+               lua_State *L = the_engine->L;
                lua_getglobal(L, "modules_create_table_for_c");
                lua_pushpointer(L, module);
                if (lua_isnil(L, -2)) {
@@ -837,7 +762,7 @@ int engine_register(struct engine *engine, const char *name, const char *precede
 
        } else if (ret == kr_error(ENOENT)) {
                /* No luck with C module, so try to load and .init() lua module. */
-               ret = ffimodule_register_lua(engine, module, name);
+               ret = ffimodule_register_lua(module, name);
                if (ret != 0) {
                        kr_log_error(SYSTEM, "failed to load module '%s'\n", name);
                }
@@ -848,13 +773,13 @@ int engine_register(struct engine *engine, const char *name, const char *precede
        }
 
        if (ret != 0) {
-               engine_unload(engine, module);
+               engine_unload(module);
                return ret;
        }
 
-       /* Push to the right place in engine->modules */
-       if (array_push(engine->modules, module) < 0) {
-               engine_unload(engine, module);
+       /* Push to the right place in the_engine->modules */
+       if (array_push(the_engine->modules, module) < 0) {
+               engine_unload(module);
                return kr_error(ENOMEM);
        }
        if (precedence) {
@@ -877,12 +802,12 @@ int engine_register(struct engine *engine, const char *name, const char *precede
        return kr_ok();
 }
 
-int engine_unregister(struct engine *engine, const char *name)
+int engine_unregister(const char *name)
 {
-       module_array_t *mod_list = &engine->modules;
+       module_array_t *mod_list = &the_engine->modules;
        size_t found = module_find(mod_list, name);
        if (found < mod_list->len) {
-               engine_unload(engine, mod_list->at[found]);
+               engine_unload(mod_list->at[found]);
                array_del(*mod_list, found);
                return kr_ok();
        }
@@ -890,3 +815,7 @@ int engine_unregister(struct engine *engine, const char *name)
        return kr_error(ENOENT);
 }
 
+module_array_t *engine_modules(void)
+{
+       return &the_engine->modules;
+}
index d724f9255b4453bdf4551b7c835bfbdd27d2add9..2b45036a0d8698131d36b7b3410032f06a135bfd 100644 (file)
@@ -14,17 +14,22 @@ struct lua_State;
 #include "daemon/network.h"
 
 struct engine {
-    struct kr_context resolver;
-    struct network net;
     module_array_t modules;
     array_t(const struct kr_cdb_api *) backends;
-    knot_mm_t *pool;
+    knot_mm_t pool;
     char *hostname;
     struct lua_State *L;
 };
 
-int engine_init(struct engine *engine, knot_mm_t *pool);
-void engine_deinit(struct engine *engine);
+/** Pointer to the singleton engine state. NULL if not initialized. */
+KR_EXPORT extern struct engine *the_engine;
+
+/** Initializes the engine. */
+int engine_init(void);
+
+/* Deinitializes the engine. `network_unregister` should be called before
+ * this and before `network_deinit`. */
+void engine_deinit(void);
 
 /** Perform a lua command within the sandbox.
  *
@@ -36,18 +41,20 @@ int engine_cmd(struct lua_State *L, const char *str, bool raw);
 /** Execute current chunk in the sandbox */
 int engine_pcall(struct lua_State *L, int argc);
 
-int engine_load_sandbox(struct engine *engine);
-int engine_loadconf(struct engine *engine, const char *config_path);
+int engine_load_sandbox(void);
+int engine_loadconf(const char *config_path);
 
 /** Start the lua engine and execute the config. */
-int engine_start(struct engine *engine);
-void engine_stop(struct engine *engine);
-int engine_register(struct engine *engine, const char *name, const char *precedence, const char* ref);
-int engine_unregister(struct engine *engine, const char *name);
+int engine_start(void);
+void engine_stop(void);
+int engine_register(const char *name, const char *precedence, const char* ref);
+int engine_unregister(const char *name);
+/** Gets the list of the engine's registered modules. */
+module_array_t *engine_modules(void);
 
 /** Set/get the per engine hostname */
-char *engine_get_hostname(struct engine *engine);
-int engine_set_hostname(struct engine *engine, const char *hostname);
+char *engine_get_hostname(void);
+int engine_set_hostname(const char *hostname);
 
 /** Load root hints from a zonefile (or config-time default if NULL).
  *
@@ -55,7 +62,7 @@ int engine_set_hostname(struct engine *engine, const char *hostname);
  * @note exported to be usable from the hints module.
  */
 KR_EXPORT
-const char* engine_hint_root_file(struct kr_context *ctx, const char *file);
+const char* engine_hint_root_file(const char *file);
 
 /* @internal Array of ip address shorthand. */
 typedef array_t(char*) addr_array_t;
index 073b12c04138423762a37688752bf30e0ac9e406..5dfd523eb86f7195212762c58b96831597d4ff36 100644 (file)
@@ -74,7 +74,7 @@ static int l_ffi_modcb(lua_State *L, struct kr_module *module)
 static int l_ffi_deinit(struct kr_module *module)
 {
        /* Call .deinit(), if it exists. */
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
        lua_getglobal(L, module->name);
        lua_getfield(L, -1, "deinit");
        const int ret = l_ffi_modcb(L, module);
@@ -102,7 +102,7 @@ static int l_ffi_call_layer(kr_layer_t *ctx, int slot_ix)
        const int wrap_slot = l_ffi_wrap_slots[slot_ix];
        const int cb_slot = ctx->api->cb_slots[slot_ix];
        kr_require(wrap_slot > 0 && cb_slot > 0);
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
        lua_rawgeti(L, LUA_REGISTRYINDEX, wrap_slot);
        lua_rawgeti(L, LUA_REGISTRYINDEX, cb_slot);
        /* We pass the content of *ctx via a global structure to avoid
@@ -271,10 +271,10 @@ static kr_layer_api_t *l_ffi_layer_create(lua_State *L, struct kr_module *module
 
 #undef LAYER_REGISTER
 
-int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name)
+int ffimodule_register_lua(struct kr_module *module, const char *name)
 {
        /* Register module in Lua */
-       lua_State *L = engine->L;
+       lua_State *L = the_engine->L;
        lua_getglobal(L, "require");
        lua_pushfstring(L, "kres_modules.%s", name);
        if (lua_pcall(L, 1, LUA_MULTRET, 0) != 0) {
index f86c764c3426d812aeeaafdf7145846e6c984f91..1e48b281bd501e3c08da510a103bcf75fc018bc2 100644 (file)
@@ -24,7 +24,7 @@ struct kr_module;
  * @param  name   module name
  * @return        0 or an error
  */
-int ffimodule_register_lua(struct engine *engine, struct kr_module *module, const char *name);
+int ffimodule_register_lua(struct kr_module *module, const char *name);
 
 int ffimodule_init(lua_State *L);
 void ffimodule_deinit(lua_State *L);
index e1e5cac357cc2990def417476292640a83fbd49d..7724120bb1f7ca33cf8418fb1fdbe39779c75a7e 100644 (file)
@@ -40,7 +40,7 @@ static void check_bufsize(uv_handle_t* handle)
         * This is magic presuming we can pull in a whole recvmmsg width in one wave.
         * Linux will double this the bufsize wanted.
         */
-       const int bufsize_want = 2 * sizeof( ((struct worker_ctx *)NULL)->wire_buf ) ;
+       const int bufsize_want = 2 * sizeof(the_worker->wire_buf) ;
        negotiate_bufsize(uv_recv_buffer_size, handle, bufsize_want);
        negotiate_bufsize(uv_send_buffer_size, handle, bufsize_want);
 }
@@ -93,7 +93,7 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
        struct proxy_result proxy;
        bool has_proxy = false;
        if (!session_flags(s)->outgoing && proxy_header_present(data, data_len)) {
-               if (!proxy_allowed(&the_worker->engine->net, comm_addr)) {
+               if (!proxy_allowed(comm_addr)) {
                        kr_log_debug(IO, "<= ignoring PROXYv2 UDP from disallowed address '%s'\n",
                                        kr_straddr(comm_addr));
                        return;
@@ -310,8 +310,7 @@ void tcp_timeout_trigger(uv_timer_t *timer)
                                return;
                        }
                }
-               const struct network *net = &the_worker->engine->net;
-               uint64_t idle_in_timeout = net->tcp.in_idle_timeout;
+               uint64_t idle_in_timeout = the_network->tcp.in_idle_timeout;
                uint64_t last_activity = session_last_activity(s);
                uint64_t idle_time = kr_now() - last_activity;
                if (idle_time < idle_in_timeout) {
@@ -325,8 +324,8 @@ void tcp_timeout_trigger(uv_timer_t *timer)
                        kr_log_debug(IO, "=> closing connection to '%s'\n",
                                       peer_str ? peer_str : "");
                        if (session_flags(s)->outgoing) {
-                               worker_del_tcp_waiting(the_worker, peer);
-                               worker_del_tcp_connected(the_worker, peer);
+                               worker_del_tcp_waiting(peer);
+                               worker_del_tcp_connected(peer);
                        }
                        session_close(s);
                }
@@ -367,7 +366,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
        const struct sockaddr *dst_addr = NULL;
        if (!session_flags(s)->outgoing && !session_flags(s)->no_proxy &&
                        proxy_header_present(data, data_len)) {
-               if (!proxy_allowed(&the_worker->engine->net, src_addr)) {
+               if (!proxy_allowed(src_addr)) {
                        if (kr_log_is_debug(IO, NULL)) {
                                kr_log_debug(IO, "<= connection to '%s': PROXYv2 not allowed "
                                                "for this peer, close\n",
@@ -510,7 +509,6 @@ static void _tcp_accept(uv_stream_t *master, int status, bool tls, bool http)
                return;
        }
 
-       struct worker_ctx *worker = the_worker;
        uv_tcp_t *client = malloc(sizeof(uv_tcp_t));
        if (!client) {
                return;
@@ -519,8 +517,8 @@ static void _tcp_accept(uv_stream_t *master, int status, bool tls, bool http)
                            SOCK_STREAM, AF_UNSPEC, tls, http);
        if (res) {
                if (res == UV_EMFILE) {
-                       worker->too_many_open = true;
-                       worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+                       the_worker->too_many_open = true;
+                       the_worker->rconcurrent_highwatermark = the_worker->stats.rconcurrent;
                }
                /* Since res isn't OK struct session wasn't allocated \ borrowed.
                 * We must release client handle only.
@@ -562,15 +560,14 @@ static void _tcp_accept(uv_stream_t *master, int status, bool tls, bool http)
         * It will re-check every half of a request time limit if the connection
         * is idle and should be terminated, this is an educated guess. */
 
-       const struct network *net = &worker->engine->net;
-       uint64_t idle_in_timeout = net->tcp.in_idle_timeout;
+       uint64_t idle_in_timeout = the_network->tcp.in_idle_timeout;
 
        uint64_t timeout = KR_CONN_RTT_MAX / 2;
        if (tls) {
                timeout += TLS_MAX_HANDSHAKE_TIME;
                struct tls_ctx *ctx = session_tls_get_server_ctx(s);
                if (!ctx) {
-                       ctx = tls_new(worker);
+                       ctx = tls_new();
                        if (!ctx) {
                                session_close(s);
                                return;
@@ -777,7 +774,7 @@ void io_tty_process_input(uv_stream_t *stream, ssize_t nread, const uv_buf_t *bu
 
        /** Moving pointer to end of buffer with incomplete command. */
        char *pbuf = data->buf + data->blen;
-       lua_State *L = the_worker->engine->L;
+       lua_State *L = the_engine->L;
        while (cmd != NULL) {
                /* Last command is incomplete - save it and execute later */
                if (incomplete_cmd && cmd_next == NULL) {
index b4088ca6e30966a0dc4c8612bd15cb06b935c694..8b86935e02e229c94e36c48cda2fa477addbd449 100644 (file)
@@ -518,7 +518,6 @@ struct endpoint {
 };
 struct request_ctx {
        struct kr_request req;
-       struct worker_ctx *worker;
        struct qr_task *task;
        /* beware: hidden stub, to avoid hardcoding sockaddr lengths */
 };
@@ -531,14 +530,14 @@ knot_pkt_t *worker_resolve_mk_pkt(const char *, uint16_t, uint16_t, const struct
 struct qr_task *worker_resolve_start(knot_pkt_t *, struct kr_qflags);
 int zi_zone_import(const zi_config_t);
 struct engine {
-       struct kr_context resolver;
        char _stub[];
 };
 struct worker_ctx {
-       struct engine *engine;
        char _stub[];
 };
+struct kr_context *the_resolver;
 struct worker_ctx *the_worker;
+struct engine *the_engine;
 typedef struct {
        uint8_t bitmap[32];
        uint8_t length;
index bf8815a3062831e22657a1ada84d81dfec2ae47c..6c569f5948198a72697fc2e17bb5b24ee83fed2b 100644 (file)
@@ -518,7 +518,6 @@ struct endpoint {
 };
 struct request_ctx {
        struct kr_request req;
-       struct worker_ctx *worker;
        struct qr_task *task;
        /* beware: hidden stub, to avoid hardcoding sockaddr lengths */
 };
@@ -531,14 +530,14 @@ knot_pkt_t *worker_resolve_mk_pkt(const char *, uint16_t, uint16_t, const struct
 struct qr_task *worker_resolve_start(knot_pkt_t *, struct kr_qflags);
 int zi_zone_import(const zi_config_t);
 struct engine {
-       struct kr_context resolver;
        char _stub[];
 };
 struct worker_ctx {
-       struct engine *engine;
        char _stub[];
 };
+struct kr_context *the_resolver;
 struct worker_ctx *the_worker;
+struct engine *the_engine;
 typedef struct {
        uint8_t *params_position;
        uint8_t *mandatory_position;
index eb9fcedcdf051eb635016a3e0cdb860d2efd0cf5..6be72aa73a2d6f15d20fb35326dfb6aee730b80e 100755 (executable)
@@ -313,13 +313,15 @@ ${CDEFS} ${KRESD} functions <<-EOF
        zi_zone_import
 EOF
 
-echo "struct engine" | ${CDEFS} ${KRESD} types | sed '/struct network/,$ d'
+echo "struct engine" | ${CDEFS} ${KRESD} types | sed '/module_array_t/,$ d'
 printf "\tchar _stub[];\n};\n"
 
 echo "struct worker_ctx" | ${CDEFS} ${KRESD} types | sed '/uv_loop_t/,$ d'
 printf "\tchar _stub[];\n};\n"
 
+echo "struct kr_context *the_resolver;"
 echo "struct worker_ctx *the_worker;"
+echo "struct engine *the_engine;"
 
 
 ## libzscanner API for ./zonefile.lua
index 3d4e7ced23be06e66765f1410c165946c6029455..8dcc3f76ecb9e8350e37ee83856937eb757e825c 100644 (file)
@@ -1135,7 +1135,7 @@ kres = {
                if ret ~= 1 then return nil end
                return ffi.string(addr_buf, C.kr_family_len(family))
        end,
-       context = function () return ffi.C.the_worker.engine.resolver end,
+       context = function () return ffi.C.the_resolver end,
 
        knot_pkt_rr = knot_pkt_rr,
 }
index 7c6a818bb1d16367e85f490f8af2aab6ab3a317b..60fd299254799680befe4b32300d8a9c3a124b71 100644 (file)
@@ -263,7 +263,7 @@ function modules_create_table_for_c(kr_module_ud)
                                        elseif arg ~= nil then
                                                arg_conv = tostring(arg)
                                        end
-                                       local ret_cstr = cb(ffi.C.the_worker.engine, kr_module, arg_conv)
+                                       local ret_cstr = cb(ffi.C.the_engine, kr_module, arg_conv)
                                        if ret_cstr == nil then
                                                return nil
                                        end
index 12826ac289e61a9142bcc004c1853160dc7d4bf2..09fcb6acd03da08f23d6b7412c89d5b9cb29baf7 100644 (file)
 #endif
 #include <libknot/error.h>
 
+/**@internal Maximum number of incomplete TCP connections in queue.
+* Default is from empirical testing - in our case, more isn't necessarily better.
+* See https://gitlab.nic.cz/knot/knot-resolver/-/merge_requests/968
+* */
+#ifndef TCP_BACKLOG_DEFAULT
+#define TCP_BACKLOG_DEFAULT 128
+#endif
 
 struct args the_args_value;  /** Static allocation for the_args singleton. */
 
@@ -133,7 +140,7 @@ static void help(int argc, char *argv[])
 }
 
 /** \return exit code for main()  */
-static int run_worker(uv_loop_t *loop, struct engine *engine, bool leader, struct args *args)
+static int run_worker(uv_loop_t *loop, bool leader, struct args *args)
 {
        /* Only some kinds of stdin work with uv_pipe_t.
         * Otherwise we would abort() from libuv e.g. with </dev/null */
@@ -355,11 +362,11 @@ static int bind_sockets(addr_array_t *addrs, bool tls, flagged_fd_array_t *fds)
        return has_error ? EXIT_FAILURE : kr_ok();
 }
 
-static int start_listening(struct network *net, flagged_fd_array_t *fds) {
+static int start_listening(flagged_fd_array_t *fds) {
        int some_bad_ret = 0;
        for (size_t i = 0; i < fds->len; ++i) {
                flagged_fd_t *ffd = &fds->at[i];
-               int ret = network_listen_fd(net, ffd->fd, ffd->flags);
+               int ret = network_listen_fd(ffd->fd, ffd->flags);
                if (ret != 0) {
                        some_bad_ret = ret;
                        /* TODO: try logging address@port.  It's not too important,
@@ -483,17 +490,23 @@ int main(int argc, char **argv)
 
        kr_crypto_init();
 
+       network_init(uv_default_loop(), TCP_BACKLOG_DEFAULT);
+
        /* Create a server engine. */
-       knot_mm_t pool;
-       mm_ctx_mempool(&pool, MM_DEFAULT_BLKSIZE);
-       static struct engine engine;
-       ret = engine_init(&engine, &pool);
+       ret = engine_init();
        if (ret != 0) {
                kr_log_error(SYSTEM, "failed to initialize engine: %s\n", kr_strerror(ret));
                return EXIT_FAILURE;
        }
-       /* Initialize the worker */
-       ret = worker_init(&engine, the_args->forks);
+
+       /* Create resolver context. */
+       ret = kr_resolver_init(&the_engine->modules, &the_engine->pool);
+       if (ret != 0) {
+               kr_log_error(SYSTEM, "failed to initialize resolver: %s\n", kr_strerror(ret));
+               return EXIT_FAILURE;
+       }
+       /* Initialize the worker. */
+       ret = worker_init(the_args->forks);
        if (ret != 0) {
                kr_log_error(SYSTEM, "failed to initialize worker: %s\n", kr_strerror(ret));
                return EXIT_FAILURE;
@@ -536,7 +549,7 @@ int main(int argc, char **argv)
        }
 
        /* Start listening, in the sense of network_listen_fd(). */
-       if (start_listening(&engine.net, &the_args->fds) != 0) {
+       if (start_listening(&the_args->fds) != 0) {
                ret = EXIT_FAILURE;
                goto cleanup;
        }
@@ -550,42 +563,45 @@ int main(int argc, char **argv)
        }
 
        /* Start the scripting engine */
-       if (engine_load_sandbox(&engine) != 0) {
+       if (engine_load_sandbox() != 0) {
                ret = EXIT_FAILURE;
                goto cleanup;
        }
 
        for (i = 0; i < the_args->config.len; ++i) {
                const char *config = the_args->config.at[i];
-               if (engine_loadconf(&engine, config) != 0) {
+               if (engine_loadconf(config) != 0) {
                        ret = EXIT_FAILURE;
                        goto cleanup;
                }
-               lua_settop(engine.L, 0);
+               lua_settop(the_engine->L, 0);
        }
 
        drop_capabilities();
 
-       if (engine_start(&engine) != 0) {
+       if (engine_start() != 0) {
                ret = EXIT_FAILURE;
                goto cleanup;
        }
 
-       if (network_engage_endpoints(&engine.net)) {
+       if (network_engage_endpoints()) {
                ret = EXIT_FAILURE;
                goto cleanup;
        }
 
        /* Run the event loop */
-       ret = run_worker(loop, &engine, fork_id == 0, the_args);
+       ret = run_worker(loop, fork_id == 0, the_args);
 
 cleanup:/* Cleanup. */
-       engine_deinit(&engine);
+       network_unregister();
+
+       kr_resolver_deinit();
        worker_deinit();
+       engine_deinit();
+       network_deinit();
        if (loop != NULL) {
                uv_loop_close(loop);
        }
-       mp_delete(pool.ctx);
 cleanup_args:
        args_deinit(the_args);
        kr_crypto_cleanup();
index 66809dfffc4b5b2387c60411074da5b6084f04b4..4d83ac78cbe3eb421a952adfa18f2721effc8d87 100644 (file)
@@ -57,38 +57,41 @@ static_assert(_Alignof(struct endpoint_key) <= 4, "endpoint_key must be aligned
 static_assert(_Alignof(struct endpoint_key_sockaddr) <= 4, "endpoint_key must be aligned to <=4");
 static_assert(_Alignof(struct endpoint_key_ifname) <= 4, "endpoint_key must be aligned to <=4");
 
-void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog)
+static struct network the_network_value = {0};
+struct network *the_network = NULL;
+
+void network_init(uv_loop_t *loop, int tcp_backlog)
 {
-       if (net != NULL) {
-               net->loop = loop;
-               net->endpoints = trie_create(NULL);
-               net->endpoint_kinds = trie_create(NULL);
-               net->proxy_all4 = false;
-               net->proxy_all6 = false;
-               net->proxy_addrs4 = trie_create(NULL);
-               net->proxy_addrs6 = trie_create(NULL);
-               net->tls_client_params = NULL;
-               net->tls_session_ticket_ctx = /* unsync. random, by default */
-               tls_session_ticket_ctx_create(loop, NULL, 0);
-               net->tcp.in_idle_timeout = 10000;
-               net->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
-               net->tcp_backlog = tcp_backlog;
-       }
+       the_network = &the_network_value;
+
+       the_network->loop = loop;
+       the_network->endpoints = trie_create(NULL);
+       the_network->endpoint_kinds = trie_create(NULL);
+       the_network->proxy_all4 = false;
+       the_network->proxy_all6 = false;
+       the_network->proxy_addrs4 = trie_create(NULL);
+       the_network->proxy_addrs6 = trie_create(NULL);
+       the_network->tls_client_params = NULL;
+       the_network->tls_session_ticket_ctx = /* unsync. random, by default */
+       tls_session_ticket_ctx_create(loop, NULL, 0);
+       the_network->tcp.in_idle_timeout = 10000;
+       the_network->tcp.tls_handshake_timeout = TLS_MAX_HANDSHAKE_TIME;
+       the_network->tcp_backlog = tcp_backlog;
 }
 
 /** Notify the registered function about endpoint getting open.
  * If log_port < 1, don't log it. */
-static int endpoint_open_lua_cb(struct network *net, struct endpoint *ep,
+static int endpoint_open_lua_cb(struct endpoint *ep,
                                const char *log_addr)
 {
        const bool ok = ep->flags.kind && !ep->handle && !ep->engaged && ep->fd != -1;
        if (kr_fails_assert(ok))
                return kr_error(EINVAL);
        /* First find callback in the endpoint registry. */
-       lua_State *L = the_worker->engine->L;
-       void **pp = trie_get_try(net->endpoint_kinds, ep->flags.kind,
+       lua_State *L = the_engine->L;
+       void **pp = trie_get_try(the_network->endpoint_kinds, ep->flags.kind,
                                strlen(ep->flags.kind));
-       if (!pp && net->missing_kind_is_error) {
+       if (!pp && the_network->missing_kind_is_error) {
                kr_log_error(NETWORK, "error: network socket kind '%s' not handled when opening '%s",
                                ep->flags.kind, log_addr);
                if (ep->family != AF_UNIX)
@@ -127,20 +130,20 @@ static int engage_endpoint_array(const char *b_key, uint32_t key_len, trie_val_t
                struct endpoint *ep = &eps->at[i];
                const bool match = !ep->engaged && ep->flags.kind;
                if (!match) continue;
-               int ret = endpoint_open_lua_cb(net, ep, log_addr);
+               int ret = endpoint_open_lua_cb(ep, log_addr);
                if (ret) return ret;
        }
        return 0;
 }
 
-int network_engage_endpoints(struct network *net)
+int network_engage_endpoints(void)
 {
-       if (net->missing_kind_is_error)
+       if (the_network->missing_kind_is_error)
                return kr_ok(); /* maybe weird, but let's make it idempotent */
-       net->missing_kind_is_error = true;
-       int ret = trie_apply_with_key(net->endpoints, engage_endpoint_array, net);
+       the_network->missing_kind_is_error = true;
+       int ret = trie_apply_with_key(the_network->endpoints, engage_endpoint_array, the_network);
        if (ret) {
-               net->missing_kind_is_error = false; /* avoid the same errors when closing */
+               the_network->missing_kind_is_error = false; /* avoid the same errors when closing */
                return ret;
        }
        return kr_ok();
@@ -167,12 +170,12 @@ const char *network_endpoint_key_str(const struct endpoint_key *key)
 }
 
 /** Notify the registered function about endpoint about to be closed. */
-static void endpoint_close_lua_cb(struct network *net, struct endpoint *ep)
+static void endpoint_close_lua_cb(struct endpoint *ep)
 {
-       lua_State *L = the_worker->engine->L;
-       void **pp = trie_get_try(net->endpoint_kinds, ep->flags.kind,
+       lua_State *L = the_engine->L;
+       void **pp = trie_get_try(the_network->endpoint_kinds, ep->flags.kind,
                                strlen(ep->flags.kind));
-       if (!pp && net->missing_kind_is_error) {
+       if (!pp && the_network->missing_kind_is_error) {
                kr_log_error(NETWORK, "internal error: missing kind '%s' in endpoint registry\n",
                                ep->flags.kind);
                return;
@@ -190,7 +193,7 @@ static void endpoint_close_lua_cb(struct network *net, struct endpoint *ep)
        }
 }
 
-static void endpoint_close(struct network *net, struct endpoint *ep, bool force)
+static void endpoint_close(struct endpoint *ep, bool force)
 {
        const bool is_control = ep->flags.kind && strcmp(ep->flags.kind, "control") == 0;
        const bool is_xdp     = ep->family == AF_XDP;
@@ -212,7 +215,7 @@ static void endpoint_close(struct network *net, struct endpoint *ep, bool force)
                kr_assert(!ep->handle);
                /* Special lua-handled endpoint. */
                if (ep->engaged) {
-                       endpoint_close_lua_cb(net, ep);
+                       endpoint_close_lua_cb(ep);
                }
                if (ep->fd > 0) {
                        close(ep->fd); /* nothing to do with errors */
@@ -241,7 +244,7 @@ static int close_key(trie_val_t *val, void* net)
 {
        endpoint_array_t *ep_array = *val;
        for (int i = 0; i < ep_array->len; ++i) {
-               endpoint_close(net, &ep_array->at[i], true);
+               endpoint_close(&ep_array->at[i], true);
        }
        return 0;
 }
@@ -261,12 +264,12 @@ int kind_unregister(trie_val_t *tv, void *L)
        return 0;
 }
 
-void network_close_force(struct network *net)
+void network_close_force(void)
 {
-       if (net != NULL) {
-               trie_apply(net->endpoints, close_key, net);
-               trie_apply(net->endpoints, free_key, NULL);
-               trie_clear(net->endpoints);
+       if (the_network != NULL) {
+               trie_apply(the_network->endpoints, close_key, the_network);
+               trie_apply(the_network->endpoints, free_key, NULL);
+               trie_clear(the_network->endpoints);
        }
 }
 
@@ -281,25 +284,28 @@ void network_proxy_free_addr_data(trie_t* trie)
        trie_it_free(it);
 }
 
-void network_deinit(struct network *net)
+void network_unregister(void)
+{
+       network_close_force();
+       trie_apply(the_network->endpoint_kinds, kind_unregister, the_engine->L);
+}
+
+void network_deinit(void)
 {
-       if (net != NULL) {
-               network_close_force(net);
-               trie_apply(net->endpoint_kinds, kind_unregister, the_worker->engine->L);
-               trie_free(net->endpoint_kinds);
-               trie_free(net->endpoints);
-               network_proxy_free_addr_data(net->proxy_addrs4);
-               trie_free(net->proxy_addrs4);
-               network_proxy_free_addr_data(net->proxy_addrs6);
-               trie_free(net->proxy_addrs6);
+       trie_free(the_network->endpoint_kinds);
+       trie_free(the_network->endpoints);
+       network_proxy_free_addr_data(the_network->proxy_addrs4);
+       trie_free(the_network->proxy_addrs4);
+       network_proxy_free_addr_data(the_network->proxy_addrs6);
+       trie_free(the_network->proxy_addrs6);
 
-               tls_credentials_free(net->tls_credentials);
-               tls_client_params_free(net->tls_client_params);
-               tls_session_ticket_ctx_destroy(net->tls_session_ticket_ctx);
-               #ifndef NDEBUG
-                       memset(net, 0, sizeof(*net));
-               #endif
-       }
+       tls_credentials_free(the_network->tls_credentials);
+       tls_client_params_free(the_network->tls_client_params);
+       tls_session_ticket_ctx_destroy(the_network->tls_session_ticket_ctx);
+#ifndef NDEBUG
+       memset(the_network, 0, sizeof(*the_network));
+#endif
+       the_network = NULL;
 }
 
 static ssize_t endpoint_key_create(struct endpoint_key_storage *dst,
@@ -323,7 +329,7 @@ static ssize_t endpoint_key_create(struct endpoint_key_storage *dst,
 }
 
 /** Fetch or create endpoint array and insert endpoint (shallow memcpy). */
-static int insert_endpoint(struct network *net, const char *addr_str,
+static int insert_endpoint(const char *addr_str,
                            const struct sockaddr *addr, struct endpoint *ep)
 {
        /* Fetch or insert address into map */
@@ -331,7 +337,7 @@ static int insert_endpoint(struct network *net, const char *addr_str,
        ssize_t keylen = endpoint_key_create(&key, addr_str, addr);
        if (keylen < 0)
                return keylen;
-       trie_val_t *val = trie_get_ins(net->endpoints, key.bytes, keylen);
+       trie_val_t *val = trie_get_ins(the_network->endpoints, key.bytes, keylen);
        endpoint_array_t *ep_array;
        if (*val) {
                ep_array = *val;
@@ -351,7 +357,7 @@ static int insert_endpoint(struct network *net, const char *addr_str,
 
 /** Open endpoint protocols.  ep->flags were pre-set.
  * \p addr_str is only used for logging or for XDP "address". */
-static int open_endpoint(struct network *net, const char *addr_str,
+static int open_endpoint(const char *addr_str,
                         struct endpoint *ep, const struct sockaddr *sa)
 {
        const bool is_control = ep->flags.kind && strcmp(ep->flags.kind, "control") == 0;
@@ -379,7 +385,7 @@ static int open_endpoint(struct network *net, const char *addr_str,
        }
        if (ep->flags.kind && !is_control && !is_xdp) {
                /* This EP isn't to be managed internally after binding. */
-               return endpoint_open_lua_cb(net, ep, addr_str);
+               return endpoint_open_lua_cb(ep, addr_str);
        } else {
                ep->engaged = true;
                /* .engaged seems not really meaningful in this case, but... */
@@ -390,7 +396,7 @@ static int open_endpoint(struct network *net, const char *addr_str,
                uv_pipe_t *ep_handle = malloc(sizeof(uv_pipe_t));
                ep->handle = (uv_handle_t *)ep_handle;
                ret = !ep->handle ? ENOMEM
-                       : io_listen_pipe(net->loop, ep_handle, ep->fd);
+                       : io_listen_pipe(the_network->loop, ep_handle, ep->fd);
                goto finish_ret;
        }
 
@@ -410,7 +416,7 @@ static int open_endpoint(struct network *net, const char *addr_str,
                uv_poll_t *ep_handle = malloc(sizeof(uv_poll_t));
                ep->handle = (uv_handle_t *)ep_handle;
                ret = !ep->handle ? ENOMEM
-                       : io_listen_xdp(net->loop, ep, addr_str);
+                       : io_listen_xdp(the_network->loop, ep, addr_str);
        #else
                ret = ESOCKTNOSUPPORT;
        #endif
@@ -423,7 +429,7 @@ static int open_endpoint(struct network *net, const char *addr_str,
                uv_udp_t *ep_handle = malloc(sizeof(uv_udp_t));
                ep->handle = (uv_handle_t *)ep_handle;
                ret = !ep->handle ? ENOMEM
-                       : io_listen_udp(net->loop, ep_handle, ep->fd);
+                       : io_listen_udp(the_network->loop, ep_handle, ep->fd);
                goto finish_ret;
        } /* else */
 
@@ -431,8 +437,8 @@ static int open_endpoint(struct network *net, const char *addr_str,
                uv_tcp_t *ep_handle = malloc(sizeof(uv_tcp_t));
                ep->handle = (uv_handle_t *)ep_handle;
                ret = !ep->handle ? ENOMEM
-                       : io_listen_tcp(net->loop, ep_handle, ep->fd,
-                                       net->tcp_backlog, ep->flags.tls, ep->flags.http);
+                       : io_listen_tcp(the_network->loop, ep_handle, ep->fd,
+                                       the_network->tcp_backlog, ep->flags.tls, ep->flags.http);
                goto finish_ret;
        } /* else */
 
@@ -449,8 +455,7 @@ finish_ret:
  * Beware that there might be multiple matches, though that's not common.
  * The matching isn't really precise in the sense that it might not find
  * and endpoint that would *collide* the passed one. */
-static struct endpoint * endpoint_get(struct network *net,
-                                      const char *addr_str,
+static struct endpoint * endpoint_get(const char *addr_str,
                                       const struct sockaddr *sa,
                                       endpoint_flags_t flags)
 {
@@ -458,7 +463,7 @@ static struct endpoint * endpoint_get(struct network *net,
        ssize_t keylen = endpoint_key_create(&key, addr_str, sa);
        if (keylen < 0)
                return NULL;
-       trie_val_t *val = trie_get_try(net->endpoints, key.bytes, keylen);
+       trie_val_t *val = trie_get_try(the_network->endpoints, key.bytes, keylen);
        if (!val)
                return NULL;
        endpoint_array_t *ep_array = *val;
@@ -476,20 +481,20 @@ static struct endpoint * endpoint_get(struct network *net,
 /** \note pass (either sa != NULL xor ep.fd != -1) or XDP case (neither sa nor ep.fd)
  *  \note in XDP case addr_str is interface name
  *  \note ownership of ep.flags.* is taken on success. */
-static int create_endpoint(struct network *net, const char *addr_str,
+static int create_endpoint(const char *addr_str,
                            struct endpoint *ep, const struct sockaddr *sa)
 {
-       int ret = open_endpoint(net, addr_str, ep, sa);
+       int ret = open_endpoint(addr_str, ep, sa);
        if (ret == 0) {
-               ret = insert_endpoint(net, addr_str, sa, ep);
+               ret = insert_endpoint(addr_str, sa, ep);
        }
        if (ret != 0 && ep->handle) {
-               endpoint_close(net, ep, false);
+               endpoint_close(ep, false);
        }
        return ret;
 }
 
-int network_listen_fd(struct network *net, int fd, endpoint_flags_t flags)
+int network_listen_fd(int fd, endpoint_flags_t flags)
 {
        if (kr_fails_assert(!flags.xdp))
                return kr_error(EINVAL);
@@ -542,7 +547,7 @@ int network_listen_fd(struct network *net, int fd, endpoint_flags_t flags)
 
        /* always create endpoint for supervisor supplied fd
         * even if addr+port is not unique */
-       return create_endpoint(net, addr_str, &ep, (struct sockaddr *) &ss);
+       return create_endpoint(addr_str, &ep, (struct sockaddr *) &ss);
 }
 
 /** Try selecting XDP queue automatically. */
@@ -559,10 +564,10 @@ static int16_t nic_queue_auto(void)
        return -1;
 }
 
-int network_listen(struct network *net, const char *addr, uint16_t port,
+int network_listen(const char *addr, uint16_t port,
                   int16_t nic_queue, endpoint_flags_t flags)
 {
-       if (kr_fails_assert(net != NULL && addr != 0 && nic_queue >= -1))
+       if (kr_fails_assert(the_network != NULL && addr != 0 && nic_queue >= -1))
                return kr_error(EINVAL);
 
        if (flags.xdp && nic_queue < 0) {
@@ -595,7 +600,7 @@ int network_listen(struct network *net, const char *addr, uint16_t port,
        }
        // XDP: if addr failed to parse as address, we assume it's an interface name.
 
-       if (endpoint_get(net, addr, sa, flags)) {
+       if (endpoint_get(addr, sa, flags)) {
                return kr_error(EADDRINUSE); // Already listening
        }
 
@@ -606,7 +611,7 @@ int network_listen(struct network *net, const char *addr, uint16_t port,
        ep.family = flags.xdp ? AF_XDP : sa->sa_family;
        ep.nic_queue = nic_queue;
 
-       int ret = create_endpoint(net, addr, &ep, sa);
+       int ret = create_endpoint(addr, &ep, sa);
 
        // Error reporting: more precision.
        if (ret == KNOT_EINVAL && !sa && flags.xdp && ENABLE_XDP) {
@@ -619,9 +624,9 @@ int network_listen(struct network *net, const char *addr, uint16_t port,
        return ret;
 }
 
-int network_proxy_allow(struct network *net, const char* addr)
+int network_proxy_allow(const char* addr)
 {
-       if (kr_fails_assert(net != NULL && addr != NULL))
+       if (kr_fails_assert(the_network != NULL && addr != NULL))
                return kr_error(EINVAL);
 
        int family = kr_straddr_family(addr);
@@ -644,10 +649,10 @@ int network_proxy_allow(struct network *net, const char* addr)
                /* Netmask is zero: allow all addresses to use PROXYv2 */
                switch (family) {
                case AF_INET:
-                       net->proxy_all4 = true;
+                       the_network->proxy_all4 = true;
                        break;
                case AF_INET6:
-                       net->proxy_all6 = true;
+                       the_network->proxy_all6 = true;
                        break;
                default:
                        kr_assert(false);
@@ -662,11 +667,11 @@ int network_proxy_allow(struct network *net, const char* addr)
        switch (family) {
        case AF_INET:
                addr_length = sizeof(ia.ip4);
-               trie = net->proxy_addrs4;
+               trie = the_network->proxy_addrs4;
                break;
        case AF_INET6:
                addr_length = sizeof(ia.ip6);
-               trie = net->proxy_addrs6;
+               trie = the_network->proxy_addrs6;
                break;
        default:
                kr_assert(false);
@@ -697,18 +702,17 @@ int network_proxy_allow(struct network *net, const char* addr)
        return kr_ok();
 }
 
-void network_proxy_reset(struct network *net)
+void network_proxy_reset(void)
 {
-       net->proxy_all4 = false;
-       network_proxy_free_addr_data(net->proxy_addrs4);
-       trie_clear(net->proxy_addrs4);
-       net->proxy_all6 = false;
-       network_proxy_free_addr_data(net->proxy_addrs6);
-       trie_clear(net->proxy_addrs6);
+       the_network->proxy_all4 = false;
+       network_proxy_free_addr_data(the_network->proxy_addrs4);
+       trie_clear(the_network->proxy_addrs4);
+       the_network->proxy_all6 = false;
+       network_proxy_free_addr_data(the_network->proxy_addrs6);
+       trie_clear(the_network->proxy_addrs6);
 }
 
-static int endpoints_close(struct network *net,
-                           struct endpoint_key_storage *key, ssize_t keylen,
+static int endpoints_close(struct endpoint_key_storage *key, ssize_t keylen,
                            endpoint_array_t *ep_array, int port)
 {
        size_t i = 0;
@@ -716,7 +720,7 @@ static int endpoints_close(struct network *net,
        while (i < ep_array->len) {
                struct endpoint *ep = &ep_array->at[i];
                if (port < 0 || ep->port == port) {
-                       endpoint_close(net, ep, false);
+                       endpoint_close(ep, false);
                        array_del(*ep_array, i);
                        matched = true;
                        /* do not advance i */
@@ -758,7 +762,6 @@ struct endpoint_key_with_len {
 typedef array_t(struct endpoint_key_with_len) endpoint_key_array_t;
 
 struct endpoint_close_wildcard_context {
-       struct network *net;
        struct endpoint_key_storage *match_key;
        endpoint_key_array_t del;
        int ret;
@@ -773,7 +776,7 @@ static int endpoints_close_wildcard(const char *s_key, uint32_t keylen, trie_val
                return kr_ok();
 
        endpoint_array_t *ep_array = *val;
-       int ret = endpoints_close(ctx->net, key, keylen, ep_array, -1);
+       int ret = endpoints_close(key, keylen, ep_array, -1);
        if (ret)
                ctx->ret = ret;
 
@@ -788,7 +791,7 @@ static int endpoints_close_wildcard(const char *s_key, uint32_t keylen, trie_val
        return kr_ok();
 }
 
-int network_close(struct network *net, const char *addr_str, int port)
+int network_close(const char *addr_str, int port)
 {
        auto_free struct sockaddr *addr = kr_straddr_socket(addr_str, port, NULL);
        struct endpoint_key_storage key;
@@ -798,14 +801,14 @@ int network_close(struct network *net, const char *addr_str, int port)
 
        if (port < 0) {
                struct endpoint_close_wildcard_context ctx = {
-                       .net = net,
                        .match_key = &key
                };
                array_init(ctx.del);
-               trie_apply_with_key(net->endpoints, endpoints_close_wildcard, &ctx);
+               trie_apply_with_key(the_network->endpoints,
+                               endpoints_close_wildcard, &ctx);
                for (size_t i = 0; i < ctx.del.len; i++) {
                        trie_val_t val;
-                       trie_del(net->endpoints,
+                       trie_del(the_network->endpoints,
                                 ctx.del.at[i].key.bytes, ctx.del.at[i].keylen,
                                 &val);
                        if (val) {
@@ -816,31 +819,31 @@ int network_close(struct network *net, const char *addr_str, int port)
                return ctx.ret;
        }
 
-       trie_val_t *val = trie_get_try(net->endpoints, key.bytes, keylen);
+       trie_val_t *val = trie_get_try(the_network->endpoints, key.bytes, keylen);
        if (!val)
                return kr_error(ENOENT);
        endpoint_array_t *ep_array = *val;
-       int ret = endpoints_close(net, &key, keylen, ep_array, port);
+       int ret = endpoints_close(&key, keylen, ep_array, port);
 
        /* Collapse key if it has no endpoint. */
        if (ep_array->len == 0) {
                array_clear(*ep_array);
                free(ep_array);
-               trie_del(net->endpoints, key.bytes, keylen, NULL);
+               trie_del(the_network->endpoints, key.bytes, keylen, NULL);
        }
 
        return ret;
 }
 
-void network_new_hostname(struct network *net, struct engine *engine)
+void network_new_hostname(void)
 {
-       if (net->tls_credentials &&
-           net->tls_credentials->ephemeral_servicename) {
+       if (the_network->tls_credentials &&
+           the_network->tls_credentials->ephemeral_servicename) {
                struct tls_credentials *newcreds;
-               newcreds = tls_get_ephemeral_credentials(engine);
+               newcreds = tls_get_ephemeral_credentials();
                if (newcreds) {
-                       tls_credentials_release(net->tls_credentials);
-                       net->tls_credentials = newcreds;
+                       tls_credentials_release(the_network->tls_credentials);
+                       the_network->tls_credentials = newcreds;
                        kr_log_info(TLS, "Updated ephemeral X.509 cert with new hostname\n");
                } else {
                        kr_log_error(TLS, "Failed to update ephemeral X.509 cert with new hostname, using existing one\n");
@@ -871,17 +874,16 @@ static int set_bpf_cb(trie_val_t *val, void *ctx)
 }
 #endif
 
-int network_set_bpf(struct network *net, int bpf_fd)
+int network_set_bpf(int bpf_fd)
 {
 #ifdef SO_ATTACH_BPF
-       if (trie_apply(net->endpoints, set_bpf_cb, &bpf_fd) != 0) {
+       if (trie_apply(the_network->endpoints, set_bpf_cb, &bpf_fd) != 0) {
                /* set_bpf_cb() has returned error. */
-               network_clear_bpf(net);
+               network_clear_bpf();
                return 0;
        }
 #else
        kr_log_error(NETWORK, "SO_ATTACH_BPF socket option doesn't supported\n");
-       (void)net;
        (void)bpf_fd;
        return 0;
 #endif
@@ -912,12 +914,11 @@ static int clear_bpf_cb(trie_val_t *val, void *ctx)
 }
 #endif
 
-void network_clear_bpf(struct network *net)
+void network_clear_bpf(void)
 {
 #ifdef SO_DETACH_BPF
-       trie_apply(net->endpoints, clear_bpf_cb, NULL);
+       trie_apply(the_network->endpoints, clear_bpf_cb, NULL);
 #else
        kr_log_error(NETWORK, "SO_DETACH_BPF socket option doesn't supported\n");
-       (void)net;
 #endif
 }
index 8bc6a0a4da886eea26e16a970143a11139faabbb..d693424418fc240063fa91c2b5f016eff6d0d00c 100644 (file)
@@ -106,8 +106,19 @@ struct network {
        int tcp_backlog;
 };
 
-void network_init(struct network *net, uv_loop_t *loop, int tcp_backlog);
-void network_deinit(struct network *net);
+/** Pointer to the singleton network state. NULL if not initialized. */
+KR_EXPORT extern struct network *the_network;
+
+/** Initializes the network. */
+void network_init(uv_loop_t *loop, int tcp_backlog);
+
+/** Unregisters endpoints. Should be called before `network_deinit`
+ * and `engine_deinit`. */
+void network_unregister(void);
+
+/** Deinitializes the network. `network_unregister` should be called before
+ * this and before `engine_deinit`. */
+void network_deinit(void);
 
 /** Start listening on addr#port with flags.
  * \note if we did listen on that combination already,
@@ -118,45 +129,45 @@ void network_deinit(struct network *net);
  * \note In XDP mode, addr may be also interface name, so kr_error(ENODEV)
  *       is returned if some nonsense is passed
  */
-int network_listen(struct network *net, const char *addr, uint16_t port,
+int network_listen(const char *addr, uint16_t port,
                   int16_t nic_queue, endpoint_flags_t flags);
 
 /** Allow the specified address to send the PROXYv2 header.
  * \note the address may be specified with a netmask
  */
-int network_proxy_allow(struct network *net, const char* addr);
+int network_proxy_allow(const char* addr);
 
 /** Reset all addresses allowed to send the PROXYv2 header. No addresses will
  * be allowed to send PROXYv2 headers from the point of calling this function
  * until re-allowed via network_proxy_allow again.
  */
-void network_proxy_reset(struct network *net);
+void network_proxy_reset(void);
 
 /** Start listening on an open file-descriptor.
  * \note flags.sock_type isn't meaningful here.
  * \note ownership of flags.* is taken on success.  TODO: non-success?
  */
-int network_listen_fd(struct network *net, int fd, endpoint_flags_t flags);
+int network_listen_fd(int fd, endpoint_flags_t flags);
 
 /** Stop listening on all endpoints with matching addr#port.
  * port < 0 serves as a wild-card.
  * \return kr_error(ENOENT) if nothing matched. */
-int network_close(struct network *net, const char *addr, int port);
+int network_close(const char *addr, int port);
 
 /** Close all endpoints immediately (no waiting for UV loop). */
-void network_close_force(struct network *net);
+void network_close_force(void);
 
 /** Enforce that all endpoints are registered from now on.
  * This only does anything with struct endpoint::flags.kind != NULL. */
-int network_engage_endpoints(struct network *net);
+int network_engage_endpoints(void);
 
 /** Returns a string representation of the specified endpoint key.
  *
  * The result points into key or is on static storage like for kr_straddr() */
 const char *network_endpoint_key_str(const struct endpoint_key *key);
 
-int network_set_tls_cert(struct network *net, const char *cert);
-int network_set_tls_key(struct network *net, const char *key);
-void network_new_hostname(struct network *net, struct engine *engine);
-int network_set_bpf(struct network *net, int bpf_fd);
-void network_clear_bpf(struct network *net);
+int network_set_tls_cert(const char *cert);
+int network_set_tls_key(const char *key);
+void network_new_hostname(void);
+int network_set_bpf(int bpf_fd);
+void network_clear_bpf(void);
index a541541f70d8a292ffe4a10e9c2b78505ae1721c..c8c1893a1be332b7dfc2da6cb28448e25a90653c 100644 (file)
@@ -1,11 +1,12 @@
-/*  Copyright (C) 2014-2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/*  Copyright (C) 2014-2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *  SPDX-License-Identifier: GPL-3.0-or-later
  */
 
-#include "daemon/proxyv2.h"
-
+#include "daemon/network.h"
 #include "lib/generic/trie.h"
 
+#include "daemon/proxyv2.h"
+
 const char PROXY2_SIGNATURE[12] = {
        0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A
 };
@@ -128,25 +129,25 @@ static inline void next_tlv(struct proxy2_tlv **tlv)
 }
 
 
-bool proxy_allowed(const struct network *net, const struct sockaddr *saddr)
+bool proxy_allowed(const struct sockaddr *saddr)
 {
        union kr_in_addr addr;
        trie_t *trie;
        size_t addr_size;
        switch (saddr->sa_family) {
        case AF_INET:
-               if (net->proxy_all4)
+               if (the_network->proxy_all4)
                        return true;
 
-               trie = net->proxy_addrs4;
+               trie = the_network->proxy_addrs4;
                addr_size = sizeof(addr.ip4);
                addr.ip4 = ((struct sockaddr_in *) saddr)->sin_addr;
                break;
        case AF_INET6:
-               if (net->proxy_all6)
+               if (the_network->proxy_all6)
                        return true;
 
-               trie = net->proxy_addrs6;
+               trie = the_network->proxy_addrs6;
                addr_size = sizeof(addr.ip6);
                addr.ip6 = ((struct sockaddr_in6 *) saddr)->sin6_addr;
                break;
index 0167e6226a23b4aceb17329101cff8b84de1c796..045bcb8fa8502c42b751cda46272c5a850b6f6c5 100644 (file)
@@ -7,7 +7,6 @@
 #include <stdint.h>
 
 #include "daemon/session.h"
-#include "daemon/network.h"
 #include "lib/utils.h"
 
 extern const char PROXY2_SIGNATURE[12];
@@ -40,7 +39,7 @@ static inline bool proxy_header_present(const void* buf, const ssize_t nread)
 
 /** Checks whether the use of PROXYv2 protocol is allowed for the specified
  * address. */
-bool proxy_allowed(const struct network *net, const struct sockaddr *saddr);
+bool proxy_allowed(const struct sockaddr *saddr);
 
 /** Parses the PROXYv2 header from buf of size nread and writes the result into
  * out. The rest of the buffer is moved to free bytes of the specified session's
index 44a28b5490a26a470cfa263ca854206858ebfa42..fdf58b5dbc9526d6c081e6acebd17831e09bf114 100644 (file)
@@ -286,31 +286,30 @@ static int tls_handshake(struct tls_common_ctx *ctx, tls_handshake_cb handshake_
 }
 
 
-struct tls_ctx *tls_new(struct worker_ctx *worker)
+struct tls_ctx *tls_new(void)
 {
-       if (kr_fails_assert(worker && worker->engine))
+       if (kr_fails_assert(the_worker && the_engine))
                return NULL;
 
-       struct network *net = &worker->engine->net;
-       if (!net->tls_credentials) {
-               net->tls_credentials = tls_get_ephemeral_credentials(worker->engine);
-               if (!net->tls_credentials) {
+       if (!the_network->tls_credentials) {
+               the_network->tls_credentials = tls_get_ephemeral_credentials();
+               if (!the_network->tls_credentials) {
                        kr_log_error(TLS, "X.509 credentials are missing, and ephemeral credentials failed; no TLS\n");
                        return NULL;
                }
                kr_log_info(TLS, "Using ephemeral TLS credentials\n");
-               tls_credentials_log_pins(net->tls_credentials);
+               tls_credentials_log_pins(the_network->tls_credentials);
        }
 
        time_t now = time(NULL);
-       if (net->tls_credentials->valid_until != GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION) {
-               if (net->tls_credentials->ephemeral_servicename) {
+       if (the_network->tls_credentials->valid_until != GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION) {
+               if (the_network->tls_credentials->ephemeral_servicename) {
                        /* ephemeral cert: refresh if due to expire within a week */
-                       if (now >= net->tls_credentials->valid_until - EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE) {
-                               struct tls_credentials *newcreds = tls_get_ephemeral_credentials(worker->engine);
+                       if (now >= the_network->tls_credentials->valid_until - EPHEMERAL_CERT_EXPIRATION_SECONDS_RENEW_BEFORE) {
+                               struct tls_credentials *newcreds = tls_get_ephemeral_credentials();
                                if (newcreds) {
-                                       tls_credentials_release(net->tls_credentials);
-                                       net->tls_credentials = newcreds;
+                                       tls_credentials_release(the_network->tls_credentials);
+                                       the_network->tls_credentials = newcreds;
                                        kr_log_info(TLS, "Renewed expiring ephemeral X.509 cert\n");
                                } else {
                                        kr_log_error(TLS, "Failed to renew expiring ephemeral X.509 cert, using existing one\n");
@@ -318,9 +317,9 @@ struct tls_ctx *tls_new(struct worker_ctx *worker)
                        }
                } else {
                        /* non-ephemeral cert: warn once when certificate expires */
-                       if (now >= net->tls_credentials->valid_until) {
+                       if (now >= the_network->tls_credentials->valid_until) {
                                kr_log_error(TLS, "X.509 certificate has expired!\n");
-                               net->tls_credentials->valid_until = GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION;
+                               the_network->tls_credentials->valid_until = GNUTLS_X509_NO_WELL_DEFINED_EXPIRATION;
                        }
                }
        }
@@ -342,7 +341,7 @@ struct tls_ctx *tls_new(struct worker_ctx *worker)
                tls_free(tls);
                return NULL;
        }
-       tls->credentials = tls_credentials_reserve(net->tls_credentials);
+       tls->credentials = tls_credentials_reserve(the_network->tls_credentials);
        err = gnutls_credentials_set(tls->c.tls_session, GNUTLS_CRD_CERTIFICATE,
                                     tls->credentials->credentials);
        if (err != GNUTLS_E_SUCCESS) {
@@ -355,15 +354,14 @@ struct tls_ctx *tls_new(struct worker_ctx *worker)
                return NULL;
        }
 
-       tls->c.worker = worker;
        tls->c.client_side = false;
 
        gnutls_transport_set_pull_function(tls->c.tls_session, kres_gnutls_pull);
        gnutls_transport_set_vec_push_function(tls->c.tls_session, kres_gnutls_vec_push);
        gnutls_transport_set_ptr(tls->c.tls_session, tls);
 
-       if (net->tls_session_ticket_ctx) {
-               tls_session_ticket_enable(net->tls_session_ticket_ctx,
+       if (the_network->tls_session_ticket_ctx) {
+               tls_session_ticket_enable(the_network->tls_session_ticket_ctx,
                                          tls->c.tls_session);
        }
 
@@ -687,9 +685,9 @@ static time_t _get_end_entity_expiration(gnutls_certificate_credentials_t creds)
        return ret;
 }
 
-int tls_certificate_set(struct network *net, const char *tls_cert, const char *tls_key)
+int tls_certificate_set(const char *tls_cert, const char *tls_key)
 {
-       if (!net) {
+       if (kr_fails_assert(the_network)) {
                return kr_error(EINVAL);
        }
 
@@ -731,11 +729,11 @@ int tls_certificate_set(struct network *net, const char *tls_cert, const char *t
        tls_credentials->valid_until = _get_end_entity_expiration(tls_credentials->credentials);
 
        /* Exchange the x509 credentials */
-       struct tls_credentials *old_credentials = net->tls_credentials;
+       struct tls_credentials *old_credentials = the_network->tls_credentials;
 
        /* Start using the new x509_credentials */
-       net->tls_credentials = tls_credentials;
-       tls_credentials_log_pins(net->tls_credentials);
+       the_network->tls_credentials = tls_credentials;
+       tls_credentials_log_pins(the_network->tls_credentials);
 
        if (old_credentials) {
                err = tls_credentials_release(old_credentials);
@@ -1059,8 +1057,7 @@ static int client_verify_certificate(gnutls_session_t tls_session)
                return client_verify_certchain(ctx->c.tls_session, ctx->params->hostname);
 }
 
-struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry,
-                                           struct worker_ctx *worker)
+struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry)
 {
        struct tls_client_ctx *ctx = calloc(1, sizeof (struct tls_client_ctx));
        if (!ctx) {
@@ -1106,7 +1103,6 @@ struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry,
                return NULL;
        }
 
-       ctx->c.worker = worker;
        ctx->c.client_side = true;
 
        gnutls_transport_set_pull_function(ctx->c.tls_session, kres_gnutls_pull);
@@ -1162,7 +1158,7 @@ int tls_client_connect_start(struct tls_client_ctx *client_ctx,
        struct tls_common_ctx *ctx = &client_ctx->c;
 
        gnutls_session_set_ptr(ctx->tls_session, client_ctx);
-       gnutls_handshake_set_timeout(ctx->tls_session, ctx->worker->engine->net.tcp.tls_handshake_timeout);
+       gnutls_handshake_set_timeout(ctx->tls_session, the_network->tcp.tls_handshake_timeout);
        gnutls_transport_set_pull_timeout_function(ctx->tls_session, tls_pull_timeout_func);
        session_tls_set_client_ctx(session, client_ctx);
        ctx->handshake_cb = handshake_cb;
index 23cd903aa2e45205fe7938323c0924214665e20d..1eb43a65e13c543340e093553b74b7e4d6dfee8d 100644 (file)
@@ -121,7 +121,6 @@ struct tls_common_ctx {
        ssize_t consumed;
        uint8_t recv_buf[16384];
        tls_handshake_cb handshake_cb;
-       struct worker_ctx *worker;
        size_t write_queue_size;
 };
 
@@ -146,7 +145,7 @@ struct tls_client_ctx {
 };
 
 /*! Create an empty TLS context in query context */
-struct tls_ctx* tls_new(struct worker_ctx *worker);
+struct tls_ctx* tls_new(void);
 
 /*! Close a TLS context (call gnutls_bye()) */
 void tls_close(struct tls_common_ctx *ctx);
@@ -167,7 +166,7 @@ int tls_write(uv_write_t *req, uv_handle_t* handle, knot_pkt_t * pkt, uv_write_c
 ssize_t tls_process_input_data(struct session *s, const uint8_t *buf, ssize_t nread);
 
 /*! Set TLS certificate and key from files. */
-int tls_certificate_set(struct network *net, const char *tls_cert, const char *tls_key);
+int tls_certificate_set(const char *tls_cert, const char *tls_key);
 
 /*! Borrow TLS credentials for context. */
 struct tls_credentials *tls_credentials_reserve(struct tls_credentials *tls_credentials);
@@ -183,7 +182,7 @@ void tls_credentials_free(struct tls_credentials *tls_credentials);
 void tls_credentials_log_pins(struct tls_credentials *tls_credentials);
 
 /*! Generate new ephemeral TLS credentials. */
-struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine);
+struct tls_credentials * tls_get_ephemeral_credentials();
 
 /*! Get TLS handshake state. */
 tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx);
@@ -193,8 +192,7 @@ int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state);
 
 
 /*! Allocate new client TLS context */
-struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry,
-                                           struct worker_ctx *worker);
+struct tls_client_ctx *tls_client_ctx_new(tls_client_param_t *entry);
 
 /*! Free client TLS context */
 void tls_client_ctx_free(struct tls_client_ctx *ctx);
index 42e053b6f0a66e9b27297f5650e1fafa89e9e21e..e64b0c9d57b801f1b43c75dcd4da837b50abf284 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2016 American Civil Liberties Union (ACLU)
  * Copyright (C) 2016-2017 CZ.NIC, z.s.p.o.
- * 
+ *
  * Initial Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
  * SPDX-License-Identifier: GPL-3.0-or-later
  */
@@ -66,7 +66,7 @@ static gnutls_x509_privkey_t get_ephemeral_privkey ()
                kr_log_error(TLS, "unable to lock lockfile " EPHEMERAL_PRIVKEY_FILENAME ".lock\n");
                goto done;
        }
-       
+
        if ((err = gnutls_x509_privkey_init (&privkey)) < 0) {
                kr_log_error(TLS, "gnutls_x509_privkey_init() failed: %d (%s)\n",
                             err, gnutls_strerror_name(err));
@@ -189,7 +189,7 @@ bad:
        return NULL;
 }
 
-struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine)
+struct tls_credentials * tls_get_ephemeral_credentials()
 {
        struct tls_credentials *creds = NULL;
        gnutls_x509_privkey_t privkey = NULL;
@@ -208,14 +208,14 @@ struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine)
        }
 
        creds->valid_until = now + EPHEMERAL_CERT_EXPIRATION_SECONDS;
-       creds->ephemeral_servicename = strdup(engine_get_hostname(engine));
+       creds->ephemeral_servicename = strdup(engine_get_hostname());
        if (creds->ephemeral_servicename == NULL) {
                kr_log_error(TLS, "could not get server's hostname, using '" INVALID_HOSTNAME "' instead\n");
                if ((creds->ephemeral_servicename = strdup(INVALID_HOSTNAME)) == NULL) {
                        kr_log_error(TLS, "failed to allocate memory for ephemeral credentials\n");
                        goto failure;
                }
-       }               
+       }
        if ((privkey = get_ephemeral_privkey()) == NULL) {
                goto failure;
        }
index 7e6226c277c74d29ac13383ccdc64af3b64eda58..2a042957ea241b9e3012cb11c4a4355442f85ccf 100644 (file)
@@ -58,7 +58,6 @@ struct request_ctx
 {
        struct kr_request req;
 
-       struct worker_ctx *worker;
        struct qr_task *task;
        struct {
                /** NULL if the request didn't come over network. */
@@ -115,13 +114,7 @@ static int qr_task_send(struct qr_task *task, struct session *session,
                        const struct sockaddr *addr, knot_pkt_t *pkt);
 static int qr_task_finalize(struct qr_task *task, int state);
 static void qr_task_complete(struct qr_task *task);
-struct session* worker_find_tcp_connected(struct worker_ctx *worker,
-                                                const struct sockaddr *addr);
-static int worker_add_tcp_waiting(struct worker_ctx *worker,
-                                 const struct sockaddr *addr,
-                                 struct session *session);
-struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
-                                              const struct sockaddr *addr);
+static int worker_add_tcp_waiting(const struct sockaddr* addr, struct session *session);
 static void on_tcp_connect_timeout(uv_timer_t *timer);
 static void on_udp_timeout(uv_timer_t *timer);
 static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_source, knot_pkt_t *pkt);
@@ -132,8 +125,7 @@ struct worker_ctx *the_worker = NULL;
 
 /*! @internal Create a UDP/TCP handle for an outgoing AF_INET* connection.
  *  socktype is SOCK_* */
-static uv_handle_t *ioreq_spawn(struct worker_ctx *worker,
-                               int socktype, sa_family_t family, bool has_tls,
+static uv_handle_t *ioreq_spawn(int socktype, sa_family_t family, bool has_tls,
                                bool has_http)
 {
        bool precond = (socktype == SOCK_DGRAM || socktype == SOCK_STREAM)
@@ -149,11 +141,11 @@ static uv_handle_t *ioreq_spawn(struct worker_ctx *worker,
        if (!handle) {
                return NULL;
        }
-       int ret = io_create(worker->loop, handle, socktype, family, has_tls, has_http);
+       int ret = io_create(the_worker->loop, handle, socktype, family, has_tls, has_http);
        if (ret) {
                if (ret == UV_EMFILE) {
-                       worker->too_many_open = true;
-                       worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+                       the_worker->too_many_open = true;
+                       the_worker->rconcurrent_highwatermark = the_worker->stats.rconcurrent;
                }
                free(handle);
                return NULL;
@@ -162,9 +154,9 @@ static uv_handle_t *ioreq_spawn(struct worker_ctx *worker,
        /* Bind to outgoing address, according to IP v4/v6. */
        union kr_sockaddr *addr;
        if (family == AF_INET) {
-               addr = (union kr_sockaddr *)&worker->out_addr4;
+               addr = (union kr_sockaddr *)&the_worker->out_addr4;
        } else {
-               addr = (union kr_sockaddr *)&worker->out_addr6;
+               addr = (union kr_sockaddr *)&the_worker->out_addr6;
        }
        if (addr->ip.sa_family != AF_UNSPEC) {
                if (kr_fails_assert(addr->ip.sa_family == family)) {
@@ -225,12 +217,12 @@ static void mp_poison(struct mempool *mp, bool poison)
 /** @endcond */
 
 /** Get a mempool.  (Recycle if possible.)  */
-static inline struct mempool *pool_borrow(struct worker_ctx *worker)
+static inline struct mempool *pool_borrow(void)
 {
        struct mempool *mp = NULL;
-       if (worker->pool_mp.len > 0) {
-               mp = array_tail(worker->pool_mp);
-               array_pop(worker->pool_mp);
+       if (the_worker->pool_mp.len > 0) {
+               mp = array_tail(the_worker->pool_mp);
+               array_pop(the_worker->pool_mp);
                mp_poison(mp, 0);
        } else { /* No mempool on the freelist, create new one */
                mp = mp_new (4 * CPU_PAGE_SIZE);
@@ -239,11 +231,11 @@ static inline struct mempool *pool_borrow(struct worker_ctx *worker)
 }
 
 /** Return a mempool.  (Cache them up to some count.) */
-static inline void pool_release(struct worker_ctx *worker, struct mempool *mp)
+static inline void pool_release(struct mempool *mp)
 {
-       if (worker->pool_mp.len < MP_FREELIST_SIZE) {
+       if (the_worker->pool_mp.len < MP_FREELIST_SIZE) {
                mp_flush(mp);
-               array_push(worker->pool_mp, mp);
+               array_push(the_worker->pool_mp, mp);
                mp_poison(mp, 1);
        } else {
                mp_delete(mp);
@@ -325,16 +317,17 @@ static void free_wire(const struct request_ctx *ctx)
 #endif
 /* Helper functions for transport selection */
 static inline bool is_tls_capable(struct sockaddr *address) {
-       tls_client_param_t *tls_entry = tls_client_param_get(the_worker->engine->net.tls_client_params, address);
+       tls_client_param_t *tls_entry = tls_client_param_get(
+                       the_network->tls_client_params, address);
        return tls_entry;
 }
 
 static inline bool is_tcp_connected(struct sockaddr *address) {
-       return worker_find_tcp_connected(the_worker, address);
+       return worker_find_tcp_connected(address);
 }
 
 static inline bool is_tcp_waiting(struct sockaddr *address) {
-       return worker_find_tcp_waiting(the_worker, address);
+       return worker_find_tcp_waiting(address);
 }
 
 /** Create and initialize a request_ctx (on a fresh mempool).
@@ -342,41 +335,39 @@ static inline bool is_tcp_waiting(struct sockaddr *address) {
  * session and addr point to the source of the request, and they are NULL
  * in case the request didn't come from network.
  */
-static struct request_ctx *request_create(struct worker_ctx *worker,
-                                          struct session *session,
+static struct request_ctx *request_create(struct session *session,
                                           struct io_comm_data *comm,
                                           const uint8_t *eth_from,
                                           const uint8_t *eth_to,
                                           uint32_t uid)
 {
        knot_mm_t pool = {
-               .ctx = pool_borrow(worker),
+               .ctx = pool_borrow(),
                .alloc = (knot_mm_alloc_t) mp_alloc
        };
 
        /* Create request context */
        struct request_ctx *ctx = mm_calloc(&pool, 1, sizeof(*ctx));
        if (!ctx) {
-               pool_release(worker, pool.ctx);
+               pool_release(pool.ctx);
                return NULL;
        }
 
        /* TODO Relocate pool to struct request */
-       ctx->worker = worker;
        if (session && kr_fails_assert(session_flags(session)->outgoing == false)) {
-               pool_release(worker, pool.ctx);
+               pool_release(pool.ctx);
                return NULL;
        }
        ctx->source.session = session;
        if (kr_fails_assert(!!eth_to == !!eth_from)) {
-               pool_release(worker, pool.ctx);
+               pool_release(pool.ctx);
                return NULL;
        }
        const bool is_xdp = eth_to != NULL;
        if (is_xdp) {
        #if ENABLE_XDP
                if (kr_fails_assert(session)) {
-                       pool_release(worker, pool.ctx);
+                       pool_release(pool.ctx);
                        return NULL;
                }
                memcpy(&ctx->source.eth_addrs[0], eth_to,   sizeof(ctx->source.eth_addrs[0]));
@@ -384,7 +375,7 @@ static struct request_ctx *request_create(struct worker_ctx *worker,
                ctx->req.alloc_wire_cb = alloc_wire_cb;
        #else
                kr_assert(!EINVAL);
-               pool_release(worker, pool.ctx);
+               pool_release(pool.ctx);
                return NULL;
        #endif
        }
@@ -448,7 +439,7 @@ static struct request_ctx *request_create(struct worker_ctx *worker,
        array_init(req->selection_context.forwarding_targets);
        array_reserve_mm(req->selection_context.forwarding_targets, 1, kr_memreserve, &req->pool);
 
-       worker->stats.rconcurrent += 1;
+       the_worker->stats.rconcurrent += 1;
 
        return ctx;
 }
@@ -477,21 +468,18 @@ static int request_start(struct request_ctx *ctx, knot_pkt_t *query)
        req->qsource.packet = pkt;
 
        /* Start resolution */
-       struct worker_ctx *worker = ctx->worker;
-       struct engine *engine = worker->engine;
-       kr_resolve_begin(req, &engine->resolver);
-       worker->stats.queries += 1;
+       kr_resolve_begin(req, the_resolver);
+       the_worker->stats.queries += 1;
        return kr_ok();
 }
 
 static void request_free(struct request_ctx *ctx)
 {
-       struct worker_ctx *worker = ctx->worker;
        /* Dereference any Lua vars table if exists */
        if (ctx->req.vars_ref != LUA_NOREF) {
-               lua_State *L = worker->engine->L;
+               lua_State *L = the_engine->L;
                /* Get worker variables table */
-               lua_rawgeti(L, LUA_REGISTRYINDEX, worker->vars_table_ref);
+               lua_rawgeti(L, LUA_REGISTRYINDEX, the_worker->vars_table_ref);
                /* Get next free element (position 0) and store it under current reference (forming a list) */
                lua_rawgeti(L, -1, 0);
                lua_rawseti(L, -2, ctx->req.vars_ref);
@@ -517,9 +505,9 @@ static void request_free(struct request_ctx *ctx)
        #endif
        }
        /* Return mempool to ring or free it if it's full */
-       pool_release(worker, ctx->req.pool.ctx);
+       pool_release(ctx->req.pool.ctx);
        /* @note The 'task' is invalidated from now on. */
-       worker->stats.rconcurrent -= 1;
+       the_worker->stats.rconcurrent -= 1;
 }
 
 static struct qr_task *qr_task_create(struct request_ctx *ctx)
@@ -528,7 +516,7 @@ static struct qr_task *qr_task_create(struct request_ctx *ctx)
         * for UDP answers from upstream *and* from cache
         * and for sending queries upstream */
        uint16_t pktbuf_max = KR_EDNS_PAYLOAD;
-       const knot_rrset_t *opt_our = ctx->worker->engine->resolver.upstream_opt_rr;
+       const knot_rrset_t *opt_our = the_resolver->upstream_opt_rr;
        if (opt_our) {
                pktbuf_max = MAX(pktbuf_max, knot_edns_get_payload(opt_our));
        }
@@ -556,7 +544,7 @@ static struct qr_task *qr_task_create(struct request_ctx *ctx)
        /* Make the primary reference to task. */
        qr_task_ref(task);
        task->creation_time = kr_now();
-       ctx->worker->stats.concurrent += 1;
+       the_worker->stats.concurrent += 1;
        return task;
 }
 
@@ -568,14 +556,12 @@ static void qr_task_free(struct qr_task *task)
        if (kr_fails_assert(ctx))
                return;
 
-       struct worker_ctx *worker = ctx->worker;
-
        if (ctx->task == NULL) {
                request_free(ctx);
        }
 
        /* Update stats */
-       worker->stats.concurrent -= 1;
+       the_worker->stats.concurrent -= 1;
 }
 
 /*@ Register new qr_task within session. */
@@ -595,7 +581,7 @@ static int qr_task_register(struct qr_task *task, struct session *session)
         * an in effect shrink TCP window size. To get more precise throttling,
         * we would need to copy remainder of the unread buffer and reassemble
         * when resuming reading. This is NYI.  */
-       if (session_tasklist_get_len(session) >= task->ctx->worker->tcp_pipeline_max &&
+       if (session_tasklist_get_len(session) >= the_worker->tcp_pipeline_max &&
            !session_flags(session)->throttled && !session_flags(session)->closing) {
                session_stop_read(session);
                session_flags(session)->throttled = true;
@@ -679,9 +665,8 @@ int qr_task_on_send(struct qr_task *task, const uv_handle_t *handle, int status)
                if (session_flags(s)->outgoing || session_flags(s)->closing)
                        return status;
 
-               struct worker_ctx *worker = task->ctx->worker;
                if (session_flags(s)->throttled &&
-                   session_tasklist_get_len(s) < worker->tcp_pipeline_max/2) {
+                   session_tasklist_get_len(s) < the_worker->tcp_pipeline_max/2) {
                        /* Start reading again if the session is throttled and
                         * the number of outgoing requests is below watermark. */
                        session_start_read(s);
@@ -745,7 +730,6 @@ static int qr_task_send(struct qr_task *task, struct session *session,
                worker_task_pkt_set_msgid(task, msg_id);
        }
 
-       struct worker_ctx *worker = ctx->worker;
        /* Note time for upstream RTT */
        task->send_time = kr_now();
        task->recv_time = 0; // task structure is being reused so we have to zero this out here
@@ -810,43 +794,43 @@ static int qr_task_send(struct qr_task *task, struct session *session,
                if (session_flags(session)->outgoing) {
                        session_tasklist_add(session, task);
                }
-               if (worker->too_many_open &&
-                   worker->stats.rconcurrent <
-                       worker->rconcurrent_highwatermark - 10) {
-                       worker->too_many_open = false;
+               if (the_worker->too_many_open &&
+                   the_worker->stats.rconcurrent <
+                       the_worker->rconcurrent_highwatermark - 10) {
+                       the_worker->too_many_open = false;
                }
        } else {
                free(ioreq);
                qr_task_unref(task);
                if (ret == UV_EMFILE) {
-                       worker->too_many_open = true;
-                       worker->rconcurrent_highwatermark = worker->stats.rconcurrent;
+                       the_worker->too_many_open = true;
+                       the_worker->rconcurrent_highwatermark = the_worker->stats.rconcurrent;
                        ret = kr_error(UV_EMFILE);
                }
 
                if (session_flags(session)->has_http)
-                       worker->stats.err_http += 1;
+                       the_worker->stats.err_http += 1;
                else if (session_flags(session)->has_tls)
-                       worker->stats.err_tls += 1;
+                       the_worker->stats.err_tls += 1;
                else if (handle->type == UV_UDP)
-                       worker->stats.err_udp += 1;
+                       the_worker->stats.err_udp += 1;
                else
-                       worker->stats.err_tcp += 1;
+                       the_worker->stats.err_tcp += 1;
        }
 
        /* Update outgoing query statistics */
        if (session_flags(session)->outgoing && addr) {
                if (session_flags(session)->has_tls)
-                       worker->stats.tls += 1;
+                       the_worker->stats.tls += 1;
                else if (handle->type == UV_UDP)
-                       worker->stats.udp += 1;
+                       the_worker->stats.udp += 1;
                else
-                       worker->stats.tcp += 1;
+                       the_worker->stats.tcp += 1;
 
                if (addr->sa_family == AF_INET6)
-                       worker->stats.ipv6 += 1;
+                       the_worker->stats.ipv6 += 1;
                else if (addr->sa_family == AF_INET)
-                       worker->stats.ipv4 += 1;
+                       the_worker->stats.ipv4 += 1;
        }
        return ret;
 }
@@ -865,7 +849,7 @@ static int session_tls_hs_cb(struct session *session, int status)
        if (kr_fails_assert(session_flags(session)->outgoing))
                return kr_error(EINVAL);
        struct sockaddr *peer = session_get_peer(session);
-       int deletion_res = worker_del_tcp_waiting(the_worker, peer);
+       int deletion_res = worker_del_tcp_waiting(peer);
        int ret = kr_ok();
 
        if (status) {
@@ -915,7 +899,7 @@ static int session_tls_hs_cb(struct session *session, int status)
                }
        }
 
-       struct session *s = worker_find_tcp_connected(the_worker, peer);
+       struct session *s = worker_find_tcp_connected(peer);
        ret = kr_ok();
        if (deletion_res == kr_ok()) {
                /* peer was in the waiting list, add to the connected list. */
@@ -924,7 +908,7 @@ static int session_tls_hs_cb(struct session *session, int status)
                         * peer already is in the connected list. */
                        ret = kr_error(EINVAL);
                } else {
-                       ret = worker_add_tcp_connected(the_worker, peer, session);
+                       ret = worker_add_tcp_connected(peer, session);
                }
        } else {
                /* peer wasn't in the waiting list.
@@ -956,7 +940,7 @@ static int session_tls_hs_cb(struct session *session, int status)
                /* Something went wrong.
                 * Either addition to the list of connected sessions
                 * or write to upstream failed. */
-               worker_del_tcp_connected(the_worker, peer);
+               worker_del_tcp_connected(peer);
                session_waitinglist_finalize(session, KR_STATE_FAIL);
                session_tasklist_finalize(session, KR_STATE_FAIL);
                session_close(session);
@@ -975,11 +959,10 @@ static int send_waiting(struct session *session)
                struct qr_task *t = session_waitinglist_get(session);
                ret = qr_task_send(t, session, NULL, NULL);
                if (ret != 0) {
-                       struct worker_ctx *worker = t->ctx->worker;
                        struct sockaddr *peer = session_get_peer(session);
                        session_waitinglist_finalize(session, KR_STATE_FAIL);
                        session_tasklist_finalize(session, KR_STATE_FAIL);
-                       worker_del_tcp_connected(worker, peer);
+                       worker_del_tcp_connected(peer);
                        session_close(session);
                        break;
                }
@@ -990,8 +973,7 @@ static int send_waiting(struct session *session)
 
 static void on_connect(uv_connect_t *req, int status)
 {
-       struct worker_ctx *worker = the_worker;
-       kr_require(worker);
+       kr_require(the_worker);
        uv_stream_t *handle = req->handle;
        struct session *session = handle->data;
        struct sockaddr *peer = session_get_peer(session);
@@ -1001,7 +983,7 @@ static void on_connect(uv_connect_t *req, int status)
                return;
 
        if (session_flags(session)->closing) {
-               worker_del_tcp_waiting(worker, peer);
+               worker_del_tcp_waiting(peer);
                kr_assert(session_is_empty(session));
                return;
        }
@@ -1012,7 +994,7 @@ static void on_connect(uv_connect_t *req, int status)
         * If no, most likely this is timed out connection
         * which was removed from waiting list by
         * on_tcp_connect_timeout() callback. */
-       struct session *s = worker_find_tcp_waiting(worker, peer);
+       struct session *s = worker_find_tcp_waiting(peer);
        if (!s || s != session) {
                /* session isn't on the waiting list.
                 * it's timed out session. */
@@ -1028,7 +1010,7 @@ static void on_connect(uv_connect_t *req, int status)
                return;
        }
 
-       s = worker_find_tcp_connected(worker, peer);
+       s = worker_find_tcp_connected(peer);
        if (s) {
                /* session already in the connected list.
                 * Something went wrong, it can be due to races when kresd has tried
@@ -1051,7 +1033,7 @@ static void on_connect(uv_connect_t *req, int status)
                        kr_log_debug(WORKER, "=> connection to '%s' failed (%s), flagged as 'bad'\n",
                                        peer_str ? peer_str : "", uv_strerror(status));
                }
-               worker_del_tcp_waiting(worker, peer);
+               worker_del_tcp_waiting(peer);
                struct qr_task *task = session_waitinglist_get(session);
                if (task && status != UV_ETIMEDOUT) {
                        /* Penalize upstream.
@@ -1069,7 +1051,7 @@ static void on_connect(uv_connect_t *req, int status)
        if (!session_flags(session)->has_tls) {
                /* if there is a TLS, session still waiting for handshake,
                 * otherwise remove it from waiting list */
-               if (worker_del_tcp_waiting(worker, peer) != 0) {
+               if (worker_del_tcp_waiting(peer) != 0) {
                        /* session isn't in list of waiting queries, *
                         * something gone wrong */
                        session_waitinglist_finalize(session, KR_STATE_FAIL);
@@ -1098,7 +1080,7 @@ static void on_connect(uv_connect_t *req, int status)
                        return;
                }
        } else {
-               worker_add_tcp_connected(worker, peer, session);
+               worker_add_tcp_connected(peer, session);
        }
 
        ret = send_waiting(session);
@@ -1116,13 +1098,12 @@ static void on_tcp_connect_timeout(uv_timer_t *timer)
        struct session *session = timer->data;
 
        uv_timer_stop(timer);
-       struct worker_ctx *worker = the_worker;
-       kr_require(worker);
+       kr_require(the_worker);
 
        kr_assert(session_tasklist_is_empty(session));
 
        struct sockaddr *peer = session_get_peer(session);
-       worker_del_tcp_waiting(worker, peer);
+       worker_del_tcp_waiting(peer);
 
        struct qr_task *task = session_waitinglist_get(session);
        if (!task) {
@@ -1142,7 +1123,7 @@ static void on_tcp_connect_timeout(uv_timer_t *timer)
 
        qry->server_selection.error(qry, task->transport, KR_SELECTION_TCP_CONNECT_TIMEOUT);
 
-       worker->stats.timeout += session_waitinglist_get_len(session);
+       the_worker->stats.timeout += session_waitinglist_get_len(session);
        session_waitinglist_retry(session, true);
        kr_assert(session_tasklist_is_empty(session));
        /* uv_cancel() doesn't support uv_connect_t request,
@@ -1168,7 +1149,6 @@ static void on_udp_timeout(uv_timer_t *timer)
        struct qr_task *task = session_tasklist_get_first(session);
        if (!task)
                return;
-       struct worker_ctx *worker = task->ctx->worker;
 
        if (task->leading && task->pending_count > 0) {
                struct kr_query *qry = array_tail(task->ctx->req.rplan.pending);
@@ -1176,7 +1156,7 @@ static void on_udp_timeout(uv_timer_t *timer)
        }
 
        task->timeouts += 1;
-       worker->stats.timeout += 1;
+       the_worker->stats.timeout += 1;
        qr_task_step(task, NULL, NULL);
 }
 
@@ -1200,7 +1180,7 @@ static uv_handle_t *transmit(struct qr_task *task)
                if (kr_resolve_checkout(&ctx->req, NULL, transport, task->pktbuf) != 0) {
                        return ret;
                }
-               ret = ioreq_spawn(ctx->worker, SOCK_DGRAM, choice->sin6_family, false, false);
+               ret = ioreq_spawn(SOCK_DGRAM, choice->sin6_family, false, false);
                if (!ret) {
                        return ret;
                }
@@ -1238,7 +1218,7 @@ static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_
        const int klen = subreq_key(key, task->pktbuf);
        if (klen > 0) {
                void *val_deleted;
-               int ret = trie_del(task->ctx->worker->subreq_out, key, klen, &val_deleted);
+               int ret = trie_del(the_worker->subreq_out, key, klen, &val_deleted);
                kr_assert(ret == KNOT_EOK && val_deleted == task);
        }
        /* Notify waiting tasks. */
@@ -1274,7 +1254,7 @@ static void subreq_lead(struct qr_task *task)
        if (klen < 0)
                return;
        struct qr_task **tvp = (struct qr_task **)
-               trie_get_ins(task->ctx->worker->subreq_out, key, klen);
+               trie_get_ins(the_worker->subreq_out, key, klen);
        if (unlikely(!tvp))
                return; /*ENOMEM*/
        if (kr_fails_assert(*tvp == NULL))
@@ -1292,7 +1272,7 @@ static bool subreq_enqueue(struct qr_task *task)
        if (klen < 0)
                return false;
        struct qr_task **leader = (struct qr_task **)
-               trie_get_try(task->ctx->worker->subreq_out, key, klen);
+               trie_get_try(the_worker->subreq_out, key, klen);
        if (!leader /*ENOMEM*/ || !*leader)
                return false;
        /* Enqueue itself to leader for this subrequest. */
@@ -1472,8 +1452,6 @@ static int tcp_task_existing_connection(struct session *session, struct qr_task
 {
        if (kr_fails_assert(session_flags(session)->outgoing && !session_flags(session)->closing))
                return kr_error(EINVAL);
-       struct request_ctx *ctx = task->ctx;
-       struct worker_ctx *worker = ctx->worker;
 
        /* If there are any unsent queries, send it first. */
        int ret = send_waiting(session);
@@ -1482,7 +1460,7 @@ static int tcp_task_existing_connection(struct session *session, struct qr_task
        }
 
        /* No unsent queries at that point. */
-       if (session_tasklist_get_len(session) >= worker->tcp_pipeline_max) {
+       if (session_tasklist_get_len(session) >= the_worker->tcp_pipeline_max) {
                /* Too many outstanding queries, answer with SERVFAIL, */
                return kr_error(EINVAL);
        }
@@ -1493,7 +1471,7 @@ static int tcp_task_existing_connection(struct session *session, struct qr_task
                /* Error, finalize task with SERVFAIL and
                 * close connection to upstream. */
                session_tasklist_finalize(session, KR_STATE_FAIL);
-               worker_del_tcp_connected(worker, session_get_peer(session));
+               worker_del_tcp_connected(session_get_peer(session));
                session_close(session);
                return kr_error(EINVAL);
        }
@@ -1503,17 +1481,14 @@ static int tcp_task_existing_connection(struct session *session, struct qr_task
 
 static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr *addr)
 {
-       struct request_ctx *ctx = task->ctx;
-       struct worker_ctx *worker = ctx->worker;
-
        /* Check if there must be TLS */
        struct tls_client_ctx *tls_ctx = NULL;
-       struct network *net = &worker->engine->net;
-       tls_client_param_t *entry = tls_client_param_get(net->tls_client_params, addr);
+       tls_client_param_t *entry = tls_client_param_get(
+                       the_network->tls_client_params, addr);
        if (entry) {
                /* Address is configured to be used with TLS.
                 * We need to allocate auxiliary data structure. */
-               tls_ctx = tls_client_ctx_new(entry, worker);
+               tls_ctx = tls_client_ctx_new(entry);
                if (!tls_ctx) {
                        return kr_error(EINVAL);
                }
@@ -1526,7 +1501,7 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
        }
        bool has_http = false;
        bool has_tls = (tls_ctx != NULL);
-       uv_handle_t *client = ioreq_spawn(worker, SOCK_STREAM, addr->sa_family, has_tls, has_http);
+       uv_handle_t *client = ioreq_spawn(SOCK_STREAM, addr->sa_family, has_tls, has_http);
        if (!client) {
                tls_client_ctx_free(tls_ctx);
                free(conn);
@@ -1545,7 +1520,7 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
 
        /* Add address to the waiting list.
         * Now it "is waiting to be connected to." */
-       int ret = worker_add_tcp_waiting(worker, addr, session);
+       int ret = worker_add_tcp_waiting(addr, session);
        if (ret < 0) {
                free(conn);
                session_close(session);
@@ -1561,7 +1536,7 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
        ret = session_timer_start(session, on_tcp_connect_timeout,
                                  KR_CONN_RTT_MAX, 0);
        if (ret != 0) {
-               worker_del_tcp_waiting(worker, addr);
+               worker_del_tcp_waiting(addr);
                free(conn);
                session_close(session);
                return kr_error(EINVAL);
@@ -1577,7 +1552,7 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
        ret = uv_tcp_connect(conn, (uv_tcp_t *)client, addr , on_connect);
        if (ret != 0) {
                session_timer_stop(session);
-               worker_del_tcp_waiting(worker, addr);
+               worker_del_tcp_waiting(addr);
                free(conn);
                session_close(session);
                qry->server_selection.error(qry, task->transport, KR_SELECTION_TCP_CONNECT_FAILED);
@@ -1589,7 +1564,7 @@ static int tcp_task_make_connection(struct qr_task *task, const struct sockaddr
        ret = session_waitinglist_push(session, task);
        if (ret < 0) {
                session_timer_stop(session);
-               worker_del_tcp_waiting(worker, addr);
+               worker_del_tcp_waiting(addr);
                free(conn);
                session_close(session);
                return kr_error(EINVAL);
@@ -1623,11 +1598,11 @@ static int tcp_task_step(struct qr_task *task,
        }
        int ret;
        struct session* session = NULL;
-       if ((session = worker_find_tcp_waiting(ctx->worker, addr)) != NULL) {
+       if ((session = worker_find_tcp_waiting(addr)) != NULL) {
                /* Connection is in the list of waiting connections.
                 * It means that connection establishing is coming right now. */
                ret = tcp_task_waiting_connection(session, task);
-       } else if ((session = worker_find_tcp_connected(ctx->worker, addr)) != NULL) {
+       } else if ((session = worker_find_tcp_connected(addr)) != NULL) {
                /* Connection has been already established. */
                ret = tcp_task_existing_connection(session, task);
        } else {
@@ -1669,14 +1644,13 @@ static int qr_task_step(struct qr_task *task,
        if (kr_fails_assert(ctx))
                return qr_task_finalize(task, KR_STATE_FAIL);
        struct kr_request *req = &ctx->req;
-       struct worker_ctx *worker = ctx->worker;
 
-       if (worker->too_many_open) {
+       if (the_worker->too_many_open) {
                /* */
                struct kr_rplan *rplan = &req->rplan;
-               if (worker->stats.rconcurrent <
-                       worker->rconcurrent_highwatermark - 10) {
-                       worker->too_many_open = false;
+               if (the_worker->stats.rconcurrent <
+                       the_worker->rconcurrent_highwatermark - 10) {
+                       the_worker->too_many_open = false;
                } else {
                        if (packet && kr_rplan_empty(rplan)) {
                                /* new query; TODO - make this detection more obvious */
@@ -1803,7 +1777,7 @@ int worker_submit(struct session *session, struct io_comm_data *comm,
        const struct sockaddr *addr = NULL;
        if (!is_outgoing) { /* request from a client */
                struct request_ctx *ctx =
-                       request_create(the_worker, session, comm, eth_from,
+                       request_create(session, comm, eth_from,
                                       eth_to, knot_wire_get_id(pkt->wire));
                if (http_ctx)
                        queue_pop(http_ctx->streams);
@@ -1891,42 +1865,35 @@ static struct session *trie_find_tcp_session(trie_t *trie,
        return val ? *val : NULL;
 }
 
-int worker_add_tcp_connected(struct worker_ctx *worker,
-                                   const struct sockaddr* addr,
-                                   struct session *session)
+int worker_add_tcp_connected(const struct sockaddr* addr, struct session *session)
 {
-       return trie_add_tcp_session(worker->tcp_connected, addr, session);
+       return trie_add_tcp_session(the_worker->tcp_connected, addr, session);
 }
 
-int worker_del_tcp_connected(struct worker_ctx *worker,
-                                   const struct sockaddr* addr)
+int worker_del_tcp_connected(const struct sockaddr* addr)
 {
-       return trie_del_tcp_session(worker->tcp_connected, addr);
+       return trie_del_tcp_session(the_worker->tcp_connected, addr);
 }
 
-struct session* worker_find_tcp_connected(struct worker_ctx *worker,
-                                                const struct sockaddr* addr)
+struct session* worker_find_tcp_connected(const struct sockaddr* addr)
 {
-       return trie_find_tcp_session(worker->tcp_connected, addr);
+       return trie_find_tcp_session(the_worker->tcp_connected, addr);
 }
 
-static int worker_add_tcp_waiting(struct worker_ctx *worker,
-                                 const struct sockaddr* addr,
+static int worker_add_tcp_waiting(const struct sockaddr* addr,
                                  struct session *session)
 {
-       return trie_add_tcp_session(worker->tcp_waiting, addr, session);
+       return trie_add_tcp_session(the_worker->tcp_waiting, addr, session);
 }
 
-int worker_del_tcp_waiting(struct worker_ctx *worker,
-                          const struct sockaddr* addr)
+int worker_del_tcp_waiting(const struct sockaddr* addr)
 {
-       return trie_del_tcp_session(worker->tcp_waiting, addr);
+       return trie_del_tcp_session(the_worker->tcp_waiting, addr);
 }
 
-struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
-                                              const struct sockaddr* addr)
+struct session* worker_find_tcp_waiting(const struct sockaddr* addr)
 {
-       return trie_find_tcp_session(worker->tcp_waiting, addr);
+       return trie_find_tcp_session(the_worker->tcp_waiting, addr);
 }
 
 int worker_end_tcp(struct session *session)
@@ -1938,8 +1905,8 @@ int worker_end_tcp(struct session *session)
 
        struct sockaddr *peer = session_get_peer(session);
 
-       worker_del_tcp_waiting(the_worker, peer);
-       worker_del_tcp_connected(the_worker, peer);
+       worker_del_tcp_waiting(peer);
+       worker_del_tcp_connected(peer);
        session_flags(session)->connected = false;
 
        struct tls_client_ctx *tls_client_ctx = session_tls_get_client_ctx(session);
@@ -2008,7 +1975,7 @@ knot_pkt_t *worker_resolve_mk_pkt_dname(knot_dname_t *qname, uint16_t qtype, uin
 
        /* Add OPT RR, including wire format so modules can see both representations.
         * knot_pkt_put() copies the outside; we need to duplicate the inside manually. */
-       knot_rrset_t *opt = knot_rrset_copy(the_worker->engine->resolver.downstream_opt_rr, NULL);
+       knot_rrset_t *opt = knot_rrset_copy(the_resolver->downstream_opt_rr, NULL);
        if (!opt) {
                knot_pkt_free(pkt);
                return NULL;
@@ -2044,13 +2011,12 @@ knot_pkt_t *worker_resolve_mk_pkt(const char *qname_str, uint16_t qtype, uint16_
 
 struct qr_task *worker_resolve_start(knot_pkt_t *query, struct kr_qflags options)
 {
-       struct worker_ctx *worker = the_worker;
-       if (kr_fails_assert(worker && query))
+       if (kr_fails_assert(the_worker && query))
                return NULL;
 
 
-       struct request_ctx *ctx = request_create(worker, NULL, NULL, NULL, NULL,
-                                                worker->next_request_uid);
+       struct request_ctx *ctx = request_create(NULL, NULL, NULL, NULL,
+                                                the_worker->next_request_uid);
        if (!ctx)
                return NULL;
 
@@ -2072,9 +2038,9 @@ struct qr_task *worker_resolve_start(knot_pkt_t *query, struct kr_qflags options
                return NULL;
        }
 
-       worker->next_request_uid += 1;
-       if (worker->next_request_uid == 0)
-               worker->next_request_uid = UINT16_MAX + 1;
+       the_worker->next_request_uid += 1;
+       if (the_worker->next_request_uid == 0)
+               the_worker->next_request_uid = UINT16_MAX + 1;
 
        /* Set options late, as qr_task_start() -> kr_resolve_begin() rewrite it. */
        kr_qflags_set(&task->ctx->req.options, options);
@@ -2180,18 +2146,18 @@ bool worker_task_finished(struct qr_task *task)
 }
 
 /** Reserve worker buffers.  We assume worker's been zeroed. */
-static int worker_reserve(struct worker_ctx *worker, size_t ring_maxlen)
+static int worker_reserve(size_t ring_maxlen)
 {
-       worker->tcp_connected = trie_create(NULL);
-       worker->tcp_waiting = trie_create(NULL);
-       worker->subreq_out = trie_create(NULL);
+       the_worker->tcp_connected = trie_create(NULL);
+       the_worker->tcp_waiting = trie_create(NULL);
+       the_worker->subreq_out = trie_create(NULL);
 
-       array_init(worker->pool_mp);
-       if (array_reserve(worker->pool_mp, ring_maxlen)) {
+       array_init(the_worker->pool_mp);
+       if (array_reserve(the_worker->pool_mp, ring_maxlen)) {
                return kr_error(ENOMEM);
        }
 
-       mm_ctx_mempool(&worker->pkt_pool, 4 * sizeof(knot_pkt_t));
+       mm_ctx_mempool(&the_worker->pkt_pool, 4 * sizeof(knot_pkt_t));
 
        return kr_ok();
 }
@@ -2208,84 +2174,83 @@ static inline void reclaim_mp_freelist(mp_freelist_t *list)
 
 void worker_deinit(void)
 {
-       struct worker_ctx *worker = the_worker;
-       if (kr_fails_assert(worker))
+       if (kr_fails_assert(the_worker))
                return;
-       trie_free(worker->tcp_connected);
-       trie_free(worker->tcp_waiting);
-       trie_free(worker->subreq_out);
-       worker->subreq_out = NULL;
+       trie_free(the_worker->tcp_connected);
+       trie_free(the_worker->tcp_waiting);
+       trie_free(the_worker->subreq_out);
+       the_worker->subreq_out = NULL;
 
-       for (int i = 0; i < worker->doh_qry_headers.len; i++)
-               free((void *)worker->doh_qry_headers.at[i]);
-       array_clear(worker->doh_qry_headers);
+       for (int i = 0; i < the_worker->doh_qry_headers.len; i++)
+               free((void *)the_worker->doh_qry_headers.at[i]);
+       array_clear(the_worker->doh_qry_headers);
 
-       reclaim_mp_freelist(&worker->pool_mp);
-       mp_delete(worker->pkt_pool.ctx);
-       worker->pkt_pool.ctx = NULL;
+       reclaim_mp_freelist(&the_worker->pool_mp);
+       mp_delete(the_worker->pkt_pool.ctx);
+       the_worker->pkt_pool.ctx = NULL;
 
        the_worker = NULL;
 }
 
-int worker_init(struct engine *engine, int worker_count)
+int worker_init(void)
 {
-       if (kr_fails_assert(engine && engine->L && the_worker == NULL))
+       if (kr_fails_assert(the_worker == NULL))
                return kr_error(EINVAL);
-       kr_bindings_register(engine->L);
+       kr_bindings_register(the_engine->L); // TODO move
 
        /* Create main worker. */
-       struct worker_ctx *worker = &the_worker_value;
-       memset(worker, 0, sizeof(*worker));
-       worker->engine = engine;
+       the_worker = &the_worker_value;
+       memset(the_worker, 0, sizeof(*the_worker));
 
        uv_loop_t *loop = uv_default_loop();
-       worker->loop = loop;
+       the_worker->loop = loop;
 
-       worker->count = worker_count;
+       static const int worker_count = 1;
+       the_worker->count = worker_count;
 
        /* Register table for worker per-request variables */
-       lua_newtable(engine->L);
-       lua_setfield(engine->L, -2, "vars");
-       lua_getfield(engine->L, -1, "vars");
-       worker->vars_table_ref = luaL_ref(engine->L, LUA_REGISTRYINDEX);
-       lua_pop(engine->L, 1);
+       struct lua_State *L = the_engine->L;
+       lua_newtable(L);
+       lua_setfield(L, -2, "vars");
+       lua_getfield(L, -1, "vars");
+       the_worker->vars_table_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+       lua_pop(L, 1);
 
-       worker->tcp_pipeline_max = MAX_PIPELINED;
-       worker->out_addr4.sin_family = AF_UNSPEC;
-       worker->out_addr6.sin6_family = AF_UNSPEC;
+       the_worker->tcp_pipeline_max = MAX_PIPELINED;
+       the_worker->out_addr4.sin_family = AF_UNSPEC;
+       the_worker->out_addr6.sin6_family = AF_UNSPEC;
 
-       array_init(worker->doh_qry_headers);
+       array_init(the_worker->doh_qry_headers);
 
-       int ret = worker_reserve(worker, MP_FREELIST_SIZE);
+       int ret = worker_reserve(MP_FREELIST_SIZE);
        if (ret) return ret;
-       worker->next_request_uid = UINT16_MAX + 1;
+       the_worker->next_request_uid = UINT16_MAX + 1;
 
        /* Set some worker.* fields in Lua */
-       lua_getglobal(engine->L, "worker");
+       lua_getglobal(L, "worker");
        pid_t pid = getpid();
 
        auto_free char *pid_str = NULL;
        const char *inst_name = getenv("SYSTEMD_INSTANCE");
        if (inst_name) {
-               lua_pushstring(engine->L, inst_name);
+               lua_pushstring(L, inst_name);
        } else {
                ret = asprintf(&pid_str, "%ld", (long)pid);
                kr_assert(ret > 0);
-               lua_pushstring(engine->L, pid_str);
+               lua_pushstring(L, pid_str);
        }
-       lua_setfield(engine->L, -2, "id");
+       lua_setfield(L, -2, "id");
 
-       lua_pushnumber(engine->L, pid);
-       lua_setfield(engine->L, -2, "pid");
-       lua_pushnumber(engine->L, worker_count);
-       lua_setfield(engine->L, -2, "count");
+       lua_pushnumber(L, pid);
+       lua_setfield(L, -2, "pid");
+       lua_pushnumber(L, worker_count);
+       lua_setfield(L, -2, "count");
 
        char cwd[PATH_MAX];
        get_workdir(cwd, sizeof(cwd));
-       lua_pushstring(engine->L, cwd);
-       lua_setfield(engine->L, -2, "cwd");
+       lua_pushstring(L, cwd);
+       lua_setfield(L, -2, "cwd");
 
-       the_worker = worker;
        loop->data = the_worker;
        /* ^^^^ Now this shouldn't be used anymore, but it's hard to be 100% sure. */
        return kr_ok();
index 3314cebcd66973125bda5766a579f9eb5ae8d65d..050db0665bc58e6ac695a22d0f2c373ed6497bbe 100644 (file)
@@ -25,10 +25,10 @@ KR_EXPORT extern struct worker_ctx *the_worker;
 
 /** Create and initialize the worker.
  * \return error code (ENOMEM) */
-int worker_init(struct engine *engine, int worker_count);
+int worker_init();
 
 /** Destroy the worker (free memory). */
-void worker_deinit(void);
+void worker_deinit();
 
 /**
  * Process an incoming packet (query from a client or answer from upstream).
@@ -93,17 +93,11 @@ void worker_task_unref(struct qr_task *task);
 
 void worker_task_timeout_inc(struct qr_task *task);
 
-int worker_add_tcp_connected(struct worker_ctx *worker,
-                            const struct sockaddr *addr,
-                            struct session *session);
-int worker_del_tcp_connected(struct worker_ctx *worker,
-                            const struct sockaddr *addr);
-int worker_del_tcp_waiting(struct worker_ctx *worker,
-                          const struct sockaddr* addr);
-struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
-                                              const struct sockaddr* addr);
-struct session* worker_find_tcp_connected(struct worker_ctx *worker,
-                                              const struct sockaddr* addr);
+int worker_add_tcp_connected(const struct sockaddr *addr, struct session *session);
+int worker_del_tcp_connected(const struct sockaddr *addr);
+int worker_del_tcp_waiting(const struct sockaddr* addr);
+struct session* worker_find_tcp_waiting(const struct sockaddr* addr);
+struct session* worker_find_tcp_connected(const struct sockaddr* addr);
 knot_pkt_t *worker_task_get_pktbuf(const struct qr_task *task);
 
 struct request_ctx *worker_task_get_request(struct qr_task *task);
@@ -163,7 +157,6 @@ typedef array_t(const char *) doh_headerlist_t;
 
 /** \details Worker state is meant to persist during the whole life of daemon. */
 struct worker_ctx {
-       struct engine *engine;
        uv_loop_t *loop;
        int count;  /** unreliable, does not count systemd instance, do not use */
        int vars_table_ref;
index 55a651af91ddb6cf5bdac2c4e95a5b51f019644c..76f7f10440effd8e4c12ad1d302dd85e0a9b4156 100644 (file)
@@ -388,7 +388,7 @@ static int zi_rrset_import(trie_val_t *rr_p, void *z_import_v)
                rank = KR_RANK_AUTH|KR_RANK_INSECURE;
        }
 
-       int ret = kr_cache_insert_rr(&the_worker->engine->resolver.cache, rr, rrsig,
+       int ret = kr_cache_insert_rr(&the_resolver->cache, rr, rrsig,
                                        rank, z_import->timestamp_rr,
                                        // Optim.: only stash NSEC* params at the apex.
                                        origin_bailiwick == 0);
@@ -423,7 +423,7 @@ static void zi_zone_process(uv_timer_t *timer)
        kr_timer_start(&stopwatch);
 
        int ret = trie_apply(z_import->rrsets, zi_rrset_import, z_import);
-       (void)kr_cache_commit(&the_worker->engine->resolver.cache); // RW transaction open
+       (void)kr_cache_commit(&the_resolver->cache); // RW transaction open
        if (ret == 0) {
                kr_log_info(PREFILL, "performance: validating and caching took %.3lf s\n",
                        kr_timer_elapsed(&stopwatch));
@@ -649,11 +649,10 @@ int zi_zone_import(const zi_config_t config)
    //// Initialize validator context with the DNSKEY.
        if (c->downgrade)
                goto zonemd;
-       struct kr_context *resolver = &the_worker->engine->resolver;
        const knot_rrset_t * const ds = c->ds ? c->ds :
-               kr_ta_get(resolver->trust_anchors, z_import->origin);
+               kr_ta_get(the_resolver->trust_anchors, z_import->origin);
        if (!ds) {
-               if (!kr_ta_closest(resolver, z_import->origin, KNOT_RRTYPE_DNSKEY))
+               if (!kr_ta_closest(the_resolver, z_import->origin, KNOT_RRTYPE_DNSKEY))
                        goto zonemd; // our TAs say we're insecure
                kr_log_error(PREFILL, "no DS found for `%s`, fail\n", zone_name_str);
                ret = kr_error(ENOENT);
index a1bed095dc15ea567d78fdaacceeb4d921e9b2b0..ad37f1a89026739ad3a67eea9c4b31e4ca326291 100644 (file)
 
 #define VERBOSE_MSG(qry, ...) kr_log_q((qry), RESOLVER,  __VA_ARGS__)
 
+/** Magic defaults */
+#ifndef LRU_RTT_SIZE
+#define LRU_RTT_SIZE 65536 /**< NS RTT cache size */
+#endif
+#ifndef LRU_REP_SIZE
+#define LRU_REP_SIZE (LRU_RTT_SIZE / 4) /**< NS reputation cache size */
+#endif
+#ifndef LRU_COOKIES_SIZE
+       #if ENABLE_COOKIES
+       #define LRU_COOKIES_SIZE LRU_RTT_SIZE /**< DNS cookies cache size. */
+       #else
+       #define LRU_COOKIES_SIZE LRU_ASSOC /* simpler than guards everywhere */
+       #endif
+#endif
+
+static struct kr_context the_resolver_value = {0};
+struct kr_context *the_resolver = NULL;
+
 bool kr_rank_check(uint8_t rank)
 {
        switch (rank & ~KR_RANK_AUTH) {
@@ -638,6 +656,52 @@ static int query_finalize(struct kr_request *request, struct kr_query *qry, knot
        return kr_ok();
 }
 
+int kr_resolver_init(module_array_t *modules, knot_mm_t *pool)
+{
+       the_resolver = &the_resolver_value;
+
+       /* Default options (request flags). */
+       the_resolver->options.REORDER_RR = true;
+
+       /* Open resolution context */
+       the_resolver->trust_anchors = trie_create(NULL);
+       the_resolver->negative_anchors = trie_create(NULL);
+       the_resolver->pool = pool;
+       the_resolver->modules = modules;
+       the_resolver->cache_rtt_tout_retry_interval = KR_NS_TIMEOUT_RETRY_INTERVAL;
+       /* Create OPT RR */
+       the_resolver->downstream_opt_rr = mm_alloc(pool, sizeof(knot_rrset_t));
+       the_resolver->upstream_opt_rr = mm_alloc(pool, sizeof(knot_rrset_t));
+       if (!the_resolver->downstream_opt_rr || !the_resolver->upstream_opt_rr) {
+               return kr_error(ENOMEM);
+       }
+       knot_edns_init(the_resolver->downstream_opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, pool);
+       knot_edns_init(the_resolver->upstream_opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, pool);
+       /* Use default TLS padding */
+       the_resolver->tls_padding = -1;
+       /* Empty init; filled via ./lua/postconfig.lua */
+       kr_zonecut_init(&the_resolver->root_hints, (const uint8_t *)"", pool);
+       lru_create(&the_resolver->cache_cookie, LRU_COOKIES_SIZE, NULL, NULL);
+
+       return kr_ok();
+}
+
+void kr_resolver_deinit(void)
+{
+       kr_zonecut_deinit(&the_resolver->root_hints);
+       kr_cache_close(&the_resolver->cache);
+
+       /* The LRUs are currently malloc-ated and need to be freed. */
+       lru_free(the_resolver->cache_cookie);
+
+       kr_ta_clear(the_resolver->trust_anchors);
+       trie_free(the_resolver->trust_anchors);
+       kr_ta_clear(the_resolver->negative_anchors);
+       trie_free(the_resolver->negative_anchors);
+
+       the_resolver = NULL;
+}
+
 int kr_resolve_begin(struct kr_request *request, struct kr_context *ctx)
 {
        /* Initialize request */
index 64c9fc3c604c906062e5cd0287ad46b23847c234..c94739d001629194e8f3e7f32584b3e10f23f5f0 100644 (file)
@@ -174,6 +174,17 @@ struct kr_context
        knot_mm_t *pool;
 };
 
+/** Pointer to the singleton resolver context. NULL if not initialized */
+KR_EXPORT extern struct kr_context *the_resolver;
+
+/** Initializes the resolver. */
+KR_EXPORT
+int kr_resolver_init(module_array_t *modules, knot_mm_t *pool);
+
+/** Cleans up the resolver. */
+KR_EXPORT
+void kr_resolver_deinit(void);
+
 /* Kept outside, because kres-gen.lua can't handle this depth
  * (and lines here were too long anyway). */
 struct kr_request_qsource_flags {
index 609aa9d131b6e3ddf73cf4cdfccd989c6c0ae4b2..45027ae0166a0679861ea4685a00a74a598eae93 100644 (file)
@@ -29,8 +29,7 @@ static int edns_keepalive_finalize(kr_layer_t *ctx)
        if (!ka_want) {
                return ctx->state;
        }
-       const struct network *net = &the_worker->engine->net;
-       uint64_t timeout = net->tcp.in_idle_timeout / 100;
+       uint64_t timeout = the_network->tcp.in_idle_timeout / 100;
        if (timeout > UINT16_MAX) {
                timeout = UINT16_MAX;
        }
index eb79a3d67e37744c4f88cc7613bd2c0da3ab3162..6ea1780d65def2cbc56a0d8628eac6d048668b41 100644 (file)
@@ -525,9 +525,7 @@ static void unpack_hint(struct kr_zonecut *root_hints, JsonNode *table, const ch
  */
 static char* hint_root(void *env, struct kr_module *module, const char *args)
 {
-       struct engine *engine = env;
-       struct kr_context *ctx = &engine->resolver;
-       struct kr_zonecut *root_hints = &ctx->root_hints;
+       struct kr_zonecut *root_hints = &the_resolver->root_hints;
        /* Replace root hints if parameter is set */
        if (args && args[0] != '\0') {
                JsonNode *root_node = json_decode(args);
@@ -541,11 +539,9 @@ static char* hint_root(void *env, struct kr_module *module, const char *args)
 
 static char* hint_root_file(void *env, struct kr_module *module, const char *args)
 {
-       struct engine *engine = env;
-       struct kr_context *ctx = &engine->resolver;
-       const char *err_msg = engine_hint_root_file(ctx, args);
+       const char *err_msg = engine_hint_root_file(args);
        if (err_msg) {
-               luaL_error(engine->L, "error when opening '%s': %s", args, err_msg);
+               luaL_error(the_engine->L, "error when opening '%s': %s", args, err_msg);
        }
        return strdup(err_msg ? err_msg : "");
 }
index a67dcdb5a616a0b833e0c71d6f6aebea58e69274..a106d17d47c9c30583b1f88a17af68760bcded7c 100644 (file)
@@ -59,13 +59,12 @@ static int nsid_finalize(kr_layer_t *ctx) {
 
 static char* nsid_name(void *env, struct kr_module *module, const char *args)
 {
-       struct engine *engine = env;
        struct nsid_config *config = module->data;
        if (args) {  /* set */
                /* API is not binary safe, we need to fix this one day */
                uint8_t *arg_copy = (uint8_t *)strdup(args);
                if (arg_copy == NULL)
-                       luaL_error(engine->L, "[nsid] error while allocating new NSID value\n");
+                       luaL_error(the_engine->L, "[nsid] error while allocating new NSID value\n");
                free(config->local_nsid);
                config->local_nsid = arg_copy;
                config->local_nsid_len = strlen(args);