From: Willem Toorop Date: Sun, 16 Mar 2025 08:21:11 +0000 (+0100) Subject: Send responses just before they enter the cache X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=86526c75a3443536607dc5bac6f306aa3619e8b3;p=thirdparty%2Funbound.git Send responses just before they enter the cache Configured with the `distribute:` option in the `server:` section in the config. --- diff --git a/daemon/worker.c b/daemon/worker.c index 4f8d33caf..e958f6ba8 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -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); diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 6b2bf7a3c..c975711ec 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -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); diff --git a/services/mesh.c b/services/mesh.c index 2289277ea..2f2cbe989 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -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); diff --git a/services/outside_network.c b/services/outside_network.c index 0d7ec8905..ba9ff77ee 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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; } diff --git a/services/outside_network.h b/services/outside_network.h index 0a77e3388..881c2ef79 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -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. diff --git a/util/config_file.c b/util/config_file.c index f6e25a1ea..5779aa0f2 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -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); diff --git a/util/config_file.h b/util/config_file.h index 71e9cad2e..716a561f0 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -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; diff --git a/util/configlexer.lex b/util/configlexer.lex index 4c0416f73..c60b24308 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -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) } diff --git a/util/configparser.y b/util/configparser.y index c10a5f475..04dd38d02 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -73,7 +73,7 @@ extern struct config_parser_state* cfg_parser; %token 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));