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->dist, cfg->num_dist);
+ cfg->tcp_auth_query_timeout, (const char**)cfg->dist,
+ (const char**)cfg->dist_tsig, 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->dist, cfg->num_dist);
+ cfg->tcp_auth_query_timeout, (const char**)cfg->dist,
+ (const char**)cfg->dist_tsig,
+ cfg->num_dist);
w->env->outnet = w->back;
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
#include "util/alloc.h"
#include "util/config_file.h"
#include "util/edns.h"
+#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "services/localzone.h"
#include "respip/respip.h"
#include "services/listen_dnsport.h"
#include "util/timeval_func.h"
+#include "util/allow_response_list.h"
+#include "util/tsig.h"
#ifdef CLIENT_SUBNET
#include "edns-subnet/subnetmod.h"
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",
+ log_err("Answer to be send to %d other unbounds, size: %d",
+ mstate->s.env->outnet->num_dist,
(int)sldns_buffer_limit(&dest));
for(i = 0; i < mstate->s.env->outnet->num_dist; i++) {
- if(mstate->s.env->outnet->dist[i] != -1)
+ struct tsig_key* key;
+ int r;
+ uint8_t data_signed[8192];
+ struct sldns_buffer dest_signed;
+
+ if(mstate->s.env->outnet->dist[i] == -1
+ || mstate->s.env->outnet->dist_tsig[i] == NULL)
+ continue;
+ if(mstate->s.env->outnet->dist_tsig[i] == TSIG_NOKEY) {
send(mstate->s.env->outnet->dist[i],
data, sldns_buffer_limit(&dest), 0);
+ continue;
+ }
+ lock_rw_rdlock(&mstate->s.env->tsig_key_table->lock);
+ key = tsig_key_table_search_fromstr(
+ mstate->s.env->tsig_key_table,
+ mstate->s.env->outnet->dist_tsig[i]);
+ if(!key) {
+ lock_rw_unlock(
+ &mstate->s.env->tsig_key_table->lock);
+ log_err("tsig key \"%s\" not found when "
+ "distributing responses",
+ mstate->s.env->outnet->dist_tsig[i]);
+ continue;
+ }
+ sldns_buffer_init_frm_data(&dest_signed,
+ data_signed, sizeof(data_signed));
+ sldns_buffer_write(&dest_signed,
+ data, sldns_buffer_limit(&dest));
+ if((r = tsig_sign_shared(&dest_signed, key->name,
+ key->algo->wireformat_name,
+ key->data, key->data_len,
+ *mstate->s.env->now))) {
+ lock_rw_unlock(
+ &mstate->s.env->tsig_key_table->lock);
+ log_err("tsig key \"%s\" failed to sign"
+ "distributing response: %s",
+ key->name_str,
+ sldns_lookup_by_id(sldns_tsig_errors, r)?
+ sldns_lookup_by_id(sldns_tsig_errors, r)->name:"??");
+ continue;
+ }
+ lock_rw_unlock(&mstate->s.env->tsig_key_table->lock);
+ send(mstate->s.env->outnet->dist[i], data_signed,
+ sldns_buffer_position(&dest_signed), 0);
}
-
}
for(r = mstate->reply_list; r; r = r->next) {
#include "util/random.h"
#include "util/fptr_wlist.h"
#include "util/edns.h"
+#include "util/allow_response_list.h"
#include "sldns/sbuffer.h"
#include "dnstap/dnstap.h"
#ifdef HAVE_OPENSSL_SSL_H
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, char** dist, int num_dist)
+ int tcp_auth_query_timeout, const char** dist, const char** dist_tsig,
+ 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)))) {
+ else if ((outnet->dist = calloc(num_dist, sizeof(int))) &&
+ (outnet->dist_tsig = calloc(num_dist, sizeof(const char*)))) {
int i;
for(i = 0; i < num_dist; i++) {
s = -1;
}
outnet->dist[i] = s;
+ outnet->dist_tsig[i] = dist_tsig[i] == NULL ? NULL
+ : strcmp(dist_tsig[i], TSIG_NOKEY)
+ ? strdup(dist_tsig[i])
+ : TSIG_NOKEY;
}
}
return outnet;
p = np;
}
}
+ if(outnet->num_dist > 0 && outnet->dist != NULL)
+ free(outnet->dist);
free(outnet);
}
int num_dist;
/** udp sockets to the addresses to send to be cached responses to */
int* dist;
+ /** names of TSIG keys with which to sign the outgoing responses */
+ const char** dist_tsig;
};
/**
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, char** dist, int num_dist);
+ int tcp_auth_query_timeout, const char** dist, const char** dist_tsig,
+ int num_dist);
/**
* Delete outside_network structure.
int num_dist;
/** distribute description strings (IP addresses) */
char **dist;
+ /** distribute description strings (IP addresses) */
+ char **dist_tsig;
/** list of allowed responses, linked list */
struct config_str2list* allow_response_list;
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 ) }
+distribute{COLON} { YDVAR(2, VAR_DISTRIBUTE ) }
allow-response{COLON} { YDVAR(2, VAR_ALLOW_RESPONSE) }
outgoing-interface{COLON} { YDVAR(1, VAR_OUTGOING_INTERFACE) }
interface-automatic{COLON} { YDVAR(1, VAR_INTERFACE_AUTOMATIC) }
cfg_parser->cfg->ifs[cfg_parser->cfg->num_ifs++] = $2;
}
;
-server_distribute: VAR_DISTRIBUTE STRING_ARG
+server_distribute: VAR_DISTRIBUTE STRING_ARG STRING_ARG
{
- OUTYY(("P(server_distribute:%s)\n", $2));
- if(cfg_parser->cfg->num_dist == 0)
+ OUTYY(("P(server_distribute: %s %s)\n", $2, $3));
+ 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->dist_tsig = 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)
+ cfg_parser->cfg->dist_tsig = realloc(
+ cfg_parser->cfg->dist_tsig,
+ (cfg_parser->cfg->num_dist+1)*sizeof(char*));
+ }
+ if(!cfg_parser->cfg->dist || !cfg_parser->cfg->dist_tsig)
yyerror("out of memory");
- else
- cfg_parser->cfg->dist[cfg_parser->cfg->num_dist++] = $2;
+ else {
+ cfg_parser->cfg->dist[cfg_parser->cfg->num_dist] = $2;
+ cfg_parser->cfg->dist_tsig[cfg_parser->cfg->num_dist]
+ = $3;
+ cfg_parser->cfg->num_dist += 1;
+ }
}
;
server_allow_response: VAR_ALLOW_RESPONSE STRING_ARG STRING_ARG