]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Send responses just before they enter the cache
authorWillem Toorop <willem@nlnetlabs.nl>
Sun, 16 Mar 2025 08:21:11 +0000 (09:21 +0100)
committerWillem Toorop <willem@nlnetlabs.nl>
Sun, 16 Mar 2025 08:21:11 +0000 (09:21 +0100)
Configured with the `distribute:` option in the `server:` section in the config.

daemon/worker.c
libunbound/libworker.c
services/mesh.c
services/outside_network.c
services/outside_network.h
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y

index 4f8d33caf2a5591a6dcdbe69d397da1ef29aabbd..e958f6ba818007a77fad2a83604765803b25c4fd 100644 (file)
@@ -2253,7 +2253,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
                worker->daemon->connect_dot_sslctx, cfg->delay_close,
                cfg->tls_use_sni, dtenv, cfg->udp_connect,
                cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
-               cfg->tcp_auth_query_timeout);
+               cfg->tcp_auth_query_timeout, cfg->dist, cfg->num_dist);
        if(!worker->back) {
                log_err("could not create outgoing sockets");
                worker_delete(worker);
index 6b2bf7a3c53b482fa77574406dfd76900b0411e5..c975711ec3cc91c4467b137439bb548d6561074d 100644 (file)
@@ -229,7 +229,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
                cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
                cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect,
                cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
-               cfg->tcp_auth_query_timeout);
+               cfg->tcp_auth_query_timeout, cfg->dist, cfg->num_dist);
        w->env->outnet = w->back;
        if(!w->is_bg || w->is_bg_thread) {
                lock_basic_unlock(&ctx->cfglock);
index 2289277eaca548910d6d2bd210e300102b719a64..2f2cbe98982b528cf39bc08526378ff04293b7a9 100644 (file)
@@ -45,6 +45,7 @@
 #include "config.h"
 #include "services/mesh.h"
 #include "services/outbound_list.h"
+#include "services/outside_network.h"
 #include "services/cache/dns.h"
 #include "services/cache/rrset.h"
 #include "services/cache/infra.h"
@@ -1523,6 +1524,26 @@ void mesh_query_done(struct mesh_state* mstate)
                        if(err) { log_err("%s", err); }
                }
        }
+       if(mstate->reply_list && rep) {
+               uint8_t data[8192];
+               struct sldns_buffer dest;
+               int i;
+
+               sldns_buffer_init_frm_data(&dest, data, sizeof(data));
+               reply_info_answer_encode(&mstate->s.qinfo, rep, 0 /* id */,
+                               0 /* qflags */, &dest, 0 /* current time */,
+                               1 /* cached */, mstate->s.env->scratch,
+                               sizeof(data) /* udpsize */, NULL /* edns */,
+                               1 /* dnssec */, 0 /* secure */);
+               log_err("Answer to be send to other unbounds, size: %d",
+                               (int)sldns_buffer_limit(&dest));
+               for(i = 0; i < mstate->s.env->outnet->num_dist; i++) {
+                       if(mstate->s.env->outnet->dist[i] != -1)
+                               send(mstate->s.env->outnet->dist[i],
+                                       data, sldns_buffer_limit(&dest), 0);
+               }
+                       
+       }
        for(r = mstate->reply_list; r; r = r->next) {
                struct timeval old;
                timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
index 0d7ec890573b7ffbd94c240620ca0625c49bba7c..ba9ff77eef7f136fb721465c4731283e858d38fc 100644 (file)
@@ -1678,7 +1678,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
        void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
        void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv,
        int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
-       int tcp_auth_query_timeout)
+       int tcp_auth_query_timeout, char** dist, int num_dist)
 {
        struct outside_network* outnet = (struct outside_network*)
                calloc(1, sizeof(struct outside_network));
@@ -1819,6 +1819,27 @@ outside_network_create(struct comm_base *base, size_t bufsize,
                        }
                }
        }
+       if (!(outnet->num_dist = num_dist))
+               outnet->dist = NULL;
+       else if ((outnet->dist = calloc(num_dist, sizeof(int)))) {
+               int i;
+
+               for(i = 0; i < num_dist; i++) {
+                       struct sockaddr_storage addr;
+                       socklen_t addrlen;
+                       int s = -1;
+
+                       if(!extstrtoaddr(dist[i], &addr, &addrlen, UNBOUND_DNS_PORT)
+                       || (s = socket(addr.ss_family, SOCK_DGRAM, 0)) == -1
+                       || !fd_set_nonblock(s)
+                       || connect(s, (struct sockaddr*)&addr, addrlen)) {
+                               if(s != -1)
+                                       close(s);
+                               s = -1;
+                       }
+                       outnet->dist[i] = s;
+               }
+       }
        return outnet;
 }
 
index 0a77e3388ddc97242d554357b38442f1d17736c7..881c2ef790b3377ae825dfa41a6b1a304fee7ce8 100644 (file)
@@ -190,6 +190,10 @@ struct outside_network {
        struct waiting_tcp* tcp_wait_first;
        /** last of waiting query list */
        struct waiting_tcp* tcp_wait_last;
+       /** number of IP addresses to send to be cached responses to */
+       int num_dist;
+       /** udp sockets to the addresses to send to be cached responses to */
+       int* dist;
 };
 
 /**
@@ -570,7 +574,7 @@ struct outside_network* outside_network_create(struct comm_base* base,
        void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
        void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv,
        int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
-       int tcp_auth_query_timeout);
+       int tcp_auth_query_timeout, char** dist, int num_dist);
 
 /**
  * Delete outside_network structure.
index f6e25a1ea37b9f8210e689c5c962b8dc6ab3d280..5779aa0f2a3eb25363b568a337cbd5395b99839a 100644 (file)
@@ -217,6 +217,8 @@ config_create(void)
        cfg->ip_dscp = 0;
        cfg->num_ifs = 0;
        cfg->ifs = NULL;
+       cfg->num_dist = 0;
+       cfg->dist = NULL;
        cfg->num_out_ifs = 0;
        cfg->out_ifs = NULL;
        cfg->stubs = NULL;
@@ -1090,6 +1092,7 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_YNO(opt, "log-time-iso", log_time_iso)
        else O_DEC(opt, "num-threads", num_threads)
        else O_IFC(opt, "interface", num_ifs, ifs)
+       else O_IFC(opt, "distribute", num_dist, dist)
        else O_IFC(opt, "outgoing-interface", num_out_ifs, out_ifs)
        else O_YNO(opt, "interface-automatic", if_automatic)
        else O_STR(opt, "interface-automatic-ports", if_automatic_ports)
@@ -1692,6 +1695,7 @@ config_delete(struct config_file* cfg)
                free(cfg->log_identity);
        }
        config_del_strarray(cfg->ifs, cfg->num_ifs);
+       config_del_strarray(cfg->dist, cfg->num_dist);
        config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
        config_delstubs(cfg->stubs);
        config_delstubs(cfg->forwards);
index 71e9cad2edcc743e341ff2046a96ab3c0259b4c3..716a561f0463a55e7512693cd0e1e3053e8b17bc 100644 (file)
@@ -244,6 +244,11 @@ struct config_file {
        /** interface description strings (IP addresses) */
        char **ifs;
 
+       /** number of addresses to distribute new responses. */
+       int num_dist;
+       /** distribute description strings (IP addresses) */
+       char **dist;
+
        /** number of outgoing interfaces to open.
         * If 0 default all interfaces. */
        int num_out_ifs;
index 4c0416f734df5102cce825cd37defb7f69715de8..c60b2430811396bcbe78df53384bacf1d0d9e903 100644 (file)
@@ -275,6 +275,7 @@ use-systemd{COLON}          { YDVAR(1, VAR_USE_SYSTEMD) }
 do-daemonize{COLON}            { YDVAR(1, VAR_DO_DAEMONIZE) }
 interface{COLON}               { YDVAR(1, VAR_INTERFACE) }
 ip-address{COLON}              { YDVAR(1, VAR_INTERFACE) }
+distribute{COLON}              { YDVAR(1, VAR_DISTRIBUTE ) }
 outgoing-interface{COLON}      { YDVAR(1, VAR_OUTGOING_INTERFACE) }
 interface-automatic{COLON}     { YDVAR(1, VAR_INTERFACE_AUTOMATIC) }
 interface-automatic-ports{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC_PORTS) }
index c10a5f475d3263809af878b0028d6ee28f2b542e..04dd38d024781cfcb6ad4b17f2809e774c03c177 100644 (file)
@@ -73,7 +73,7 @@ extern struct config_parser_state* cfg_parser;
 %token <str> STRING_ARG
 %token VAR_FORCE_TOPLEVEL
 %token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
-%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_PREFER_IP4
+%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_DISTRIBUTE VAR_PREFER_IP4
 %token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_NAT64 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
 %token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT
 %token VAR_EDNS_TCP_KEEPALIVE VAR_EDNS_TCP_KEEPALIVE_TIMEOUT
@@ -242,7 +242,7 @@ content_server: server_num_threads | server_verbosity | server_port |
        server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout |
        server_tcp_keepalive | server_tcp_keepalive_timeout |
        server_sock_queue_timeout |
-       server_interface | server_chroot | server_username |
+       server_interface | server_distribute | server_chroot | server_username |
        server_directory | server_logfile | server_pidfile |
        server_msg_cache_size | server_msg_cache_slabs |
        server_num_queries_per_thread | server_rrset_cache_size |
@@ -804,6 +804,19 @@ server_interface: VAR_INTERFACE STRING_ARG
                        cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = $2;
        }
        ;
+server_distribute: VAR_DISTRIBUTE STRING_ARG
+       {
+               OUTYY(("P(server_distribute:%s)\n", $2));
+               if(cfg_parser->cfg->num_dist == 0)
+                       cfg_parser->cfg->dist = calloc(1, sizeof(char*));
+               else cfg_parser->cfg->dist = realloc(cfg_parser->cfg->dist,
+                               (cfg_parser->cfg->num_dist+1)*sizeof(char*));
+               if(!cfg_parser->cfg->dist)
+                       yyerror("out of memory");
+               else
+                       cfg_parser->cfg->dist[cfg_parser->cfg->num_dist++] = $2;
+       }
+       ;
 server_outgoing_interface: VAR_OUTGOING_INTERFACE STRING_ARG
        {
                OUTYY(("P(server_outgoing_interface:%s)\n", $2));