Configured with the `distribute:` option in the `server:` section in the config.
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);
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);
#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"
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);
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));
}
}
}
+ 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;
}
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;
};
/**
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.
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;
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)
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);
/** 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;
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) }
%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
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 |
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));