mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-11 22:19:52 +00:00
Merge branch 'branch-1.25.2'
This commit is contained in:
@@ -23021,6 +23021,29 @@ printf "%s\n" "no" >&6; }
|
|||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||||
|
|
||||||
|
ac_fn_check_decl "$LINENO" "CLOCK_MONOTONIC
|
||||||
|
" "ac_cv_have_decl_CLOCK_MONOTONIC_________" "$ac_includes_default
|
||||||
|
#ifdef TIME_WITH_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
# else
|
||||||
|
# include <time.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
" "$ac_c_undeclared_builtin_options" "CFLAGS"
|
||||||
|
if test "x$ac_cv_have_decl_CLOCK_MONOTONIC_________" = xyes
|
||||||
|
then :
|
||||||
|
|
||||||
|
|
||||||
|
else $as_nop
|
||||||
|
as_fn_error $? "ngtcp2 for QUIC needs at least CLOCK_MONOTONIC on the system" "$LINENO" 5
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set static linking for uninstalled libraries if requested
|
# set static linking for uninstalled libraries if requested
|
||||||
|
|||||||
@@ -1747,6 +1747,22 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_CHECK_DECL([CLOCK_MONOTONIC]
|
||||||
|
, []
|
||||||
|
, [AC_MSG_ERROR([ngtcp2 for QUIC needs at least CLOCK_MONOTONIC on the system])]
|
||||||
|
, [AC_INCLUDES_DEFAULT
|
||||||
|
#ifdef TIME_WITH_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
# else
|
||||||
|
# include <time.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
])
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# set static linking for uninstalled libraries if requested
|
# set static linking for uninstalled libraries if requested
|
||||||
|
|||||||
+8
-4
@@ -79,6 +79,7 @@
|
|||||||
#include "util/tcp_conn_limit.h"
|
#include "util/tcp_conn_limit.h"
|
||||||
#include "util/edns.h"
|
#include "util/edns.h"
|
||||||
#include "services/listen_dnsport.h"
|
#include "services/listen_dnsport.h"
|
||||||
|
#include "services/outside_network.h"
|
||||||
#include "services/cache/rrset.h"
|
#include "services/cache/rrset.h"
|
||||||
#include "services/cache/infra.h"
|
#include "services/cache/infra.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
@@ -825,6 +826,10 @@ daemon_create_workers(struct daemon* daemon)
|
|||||||
fatal_exit("out of memory during daemon init");
|
fatal_exit("out of memory during daemon init");
|
||||||
numport = daemon_get_shufport(daemon, shufport);
|
numport = daemon_get_shufport(daemon, shufport);
|
||||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
||||||
|
if(!(daemon->shared_ports = shared_ports_create(daemon->cfg->out_ifs,
|
||||||
|
daemon->cfg->num_out_ifs, daemon->cfg->do_ip4,
|
||||||
|
daemon->cfg->do_ip6, shufport, numport)))
|
||||||
|
fatal_exit("could not setup shared ports: out of memory");
|
||||||
|
|
||||||
#ifdef HAVE_NGTCP2
|
#ifdef HAVE_NGTCP2
|
||||||
if (cfg_has_quic(daemon->cfg)) {
|
if (cfg_has_quic(daemon->cfg)) {
|
||||||
@@ -855,10 +860,7 @@ daemon_create_workers(struct daemon* daemon)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
for(i=0; i<daemon->num; i++) {
|
for(i=0; i<daemon->num; i++) {
|
||||||
if(!(daemon->workers[i] = worker_create(daemon, i,
|
if(!(daemon->workers[i] = worker_create(daemon, i)))
|
||||||
shufport+numport*i/daemon->num,
|
|
||||||
numport*(i+1)/daemon->num - numport*i/daemon->num)))
|
|
||||||
/* the above is not ports/numthr, due to rounding */
|
|
||||||
fatal_exit("could not create worker");
|
fatal_exit("could not create worker");
|
||||||
}
|
}
|
||||||
/* create per-worker alloc caches if not reusing existing ones. */
|
/* create per-worker alloc caches if not reusing existing ones. */
|
||||||
@@ -1219,6 +1221,8 @@ daemon_cleanup(struct daemon* daemon)
|
|||||||
if(!daemon->reuse_cache || daemon->need_to_exit)
|
if(!daemon->reuse_cache || daemon->need_to_exit)
|
||||||
daemon_clear_allocs(daemon);
|
daemon_clear_allocs(daemon);
|
||||||
daemon->num = 0;
|
daemon->num = 0;
|
||||||
|
shared_ports_delete(daemon->shared_ports);
|
||||||
|
daemon->shared_ports = NULL;
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
dt_delete(daemon->dtenv);
|
dt_delete(daemon->dtenv);
|
||||||
daemon->dtenv = NULL;
|
daemon->dtenv = NULL;
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ struct doq_table;
|
|||||||
struct cookie_secrets;
|
struct cookie_secrets;
|
||||||
struct fast_reload_thread;
|
struct fast_reload_thread;
|
||||||
struct fast_reload_printq;
|
struct fast_reload_printq;
|
||||||
|
struct shared_ports;
|
||||||
|
|
||||||
#include "dnstap/dnstap_config.h"
|
#include "dnstap/dnstap_config.h"
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
@@ -97,6 +98,8 @@ struct daemon {
|
|||||||
int rc_port;
|
int rc_port;
|
||||||
/** listening ports for remote control */
|
/** listening ports for remote control */
|
||||||
struct listen_port* rc_ports;
|
struct listen_port* rc_ports;
|
||||||
|
/** the shared ports structure, with random ports numbers. */
|
||||||
|
struct shared_ports* shared_ports;
|
||||||
/** remote control connections management (for first worker) */
|
/** remote control connections management (for first worker) */
|
||||||
struct daemon_remote* rc;
|
struct daemon_remote* rc;
|
||||||
/** ssl context for listening to dnstcp over ssl */
|
/** ssl context for listening to dnstcp over ssl */
|
||||||
|
|||||||
@@ -1735,6 +1735,14 @@ do_view_data_add(RES* ssl, struct worker* worker, char* arg)
|
|||||||
ssl_printf(ssl,"error out of memory\n");
|
ssl_printf(ssl,"error out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!v->isfirst) {
|
||||||
|
/* Global local-zone is not used for this view,
|
||||||
|
* therefore add defaults to this view-specific
|
||||||
|
* local-zone. */
|
||||||
|
struct config_file lz_cfg;
|
||||||
|
memset(&lz_cfg, 0, sizeof(lz_cfg));
|
||||||
|
local_zone_enter_defaults(v->local_zones, &lz_cfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
do_data_add(ssl, v->local_zones, arg2);
|
do_data_add(ssl, v->local_zones, arg2);
|
||||||
lock_rw_unlock(&v->lock);
|
lock_rw_unlock(&v->lock);
|
||||||
@@ -1760,6 +1768,14 @@ do_view_datas_add(struct daemon_remote* rc, RES* ssl, struct worker* worker,
|
|||||||
ssl_printf(ssl,"error out of memory\n");
|
ssl_printf(ssl,"error out of memory\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!v->isfirst) {
|
||||||
|
/* Global local-zone is not used for this view,
|
||||||
|
* therefore add defaults to this view-specific
|
||||||
|
* local-zone. */
|
||||||
|
struct config_file lz_cfg;
|
||||||
|
memset(&lz_cfg, 0, sizeof(lz_cfg));
|
||||||
|
local_zone_enter_defaults(v->local_zones, &lz_cfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* put the view name in the command buf */
|
/* put the view name in the command buf */
|
||||||
(void)snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s ", arg);
|
(void)snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s ", arg);
|
||||||
|
|||||||
+17
-13
@@ -1555,6 +1555,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
|
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
|
||||||
|
sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
dname_str(qinfo.qname, buf);
|
dname_str(qinfo.qname, buf);
|
||||||
@@ -1573,6 +1574,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||||||
query_error(c->buffer, LDNS_RCODE_SERVFAIL,
|
query_error(c->buffer, LDNS_RCODE_SERVFAIL,
|
||||||
qinfo.qname_len);
|
qinfo.qname_len);
|
||||||
worker->stats.num_query_dnscrypt_cleartext++;
|
worker->stats.num_query_dnscrypt_cleartext++;
|
||||||
|
sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
worker->stats.num_query_dnscrypt_cert++;
|
worker->stats.num_query_dnscrypt_cert++;
|
||||||
@@ -1833,7 +1835,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||||||
server_stats_insquery(&worker->stats, c, qinfo.qtype,
|
server_stats_insquery(&worker->stats, c, qinfo.qtype,
|
||||||
qinfo.qclass, &edns, repinfo);
|
qinfo.qclass, &edns, repinfo);
|
||||||
if(c->type != comm_udp)
|
if(c->type != comm_udp)
|
||||||
|
#ifdef USE_DNSCRYPT
|
||||||
|
edns.udp_size = (c->dnscrypt && repinfo->is_dnscrypted)
|
||||||
|
? sldns_buffer_capacity(c->buffer) - DNSCRYPT_REPLY_HEADER_SIZE
|
||||||
|
: 65535;
|
||||||
|
#else
|
||||||
edns.udp_size = 65535; /* max size for TCP replies */
|
edns.udp_size = 65535; /* max size for TCP replies */
|
||||||
|
#endif
|
||||||
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
|
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
|
||||||
&edns, repinfo, c->buffer)) {
|
&edns, repinfo, c->buffer)) {
|
||||||
regional_free_all(worker->scratchpad);
|
regional_free_all(worker->scratchpad);
|
||||||
@@ -2121,7 +2129,7 @@ send_reply_rc:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef USE_DNSCRYPT
|
#ifdef USE_DNSCRYPT
|
||||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
if(!dnsc_handle_uncurved_request(repinfo, c->buffer)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2234,23 +2242,16 @@ void worker_probe_timer_cb(void* arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct worker*
|
struct worker*
|
||||||
worker_create(struct daemon* daemon, int id, int* ports, int n)
|
worker_create(struct daemon* daemon, int id)
|
||||||
{
|
{
|
||||||
unsigned int seed;
|
unsigned int seed;
|
||||||
struct worker* worker = (struct worker*)calloc(1,
|
struct worker* worker = (struct worker*)calloc(1,
|
||||||
sizeof(struct worker));
|
sizeof(struct worker));
|
||||||
if(!worker)
|
if(!worker)
|
||||||
return NULL;
|
return NULL;
|
||||||
worker->numports = n;
|
|
||||||
worker->ports = (int*)memdup(ports, sizeof(int)*n);
|
|
||||||
if(!worker->ports) {
|
|
||||||
free(worker);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
worker->daemon = daemon;
|
worker->daemon = daemon;
|
||||||
worker->thread_num = id;
|
worker->thread_num = id;
|
||||||
if(!(worker->cmd = tube_create())) {
|
if(!(worker->cmd = tube_create())) {
|
||||||
free(worker->ports);
|
|
||||||
free(worker);
|
free(worker);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -2258,7 +2259,6 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)
|
|||||||
if(!(worker->rndstate = ub_initstate(daemon->rand))) {
|
if(!(worker->rndstate = ub_initstate(daemon->rand))) {
|
||||||
log_err("could not init random numbers.");
|
log_err("could not init random numbers.");
|
||||||
tube_delete(worker->cmd);
|
tube_delete(worker->cmd);
|
||||||
free(worker->ports);
|
|
||||||
free(worker);
|
free(worker);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -2357,14 +2357,14 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
|||||||
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||||
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
|
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
|
||||||
worker->daemon->env->infra_cache, worker->rndstate,
|
worker->daemon->env->infra_cache, worker->rndstate,
|
||||||
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
|
cfg->use_caps_bits_for_id,
|
||||||
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
|
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
|
||||||
&worker_alloc_cleanup, worker,
|
&worker_alloc_cleanup, worker,
|
||||||
cfg->do_udp || cfg->udp_upstream_without_downstream,
|
cfg->do_udp || cfg->udp_upstream_without_downstream,
|
||||||
worker->daemon->connect_dot_sslctx, cfg->delay_close,
|
worker->daemon->connect_dot_sslctx, cfg->delay_close,
|
||||||
cfg->tls_use_sni, dtenv, cfg->udp_connect,
|
cfg->tls_use_sni, dtenv, cfg->udp_connect,
|
||||||
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
|
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
|
||||||
cfg->tcp_auth_query_timeout);
|
cfg->tcp_auth_query_timeout, worker->daemon->shared_ports);
|
||||||
if(!worker->back) {
|
if(!worker->back) {
|
||||||
log_err("could not create outgoing sockets");
|
log_err("could not create outgoing sockets");
|
||||||
worker_delete(worker);
|
worker_delete(worker);
|
||||||
@@ -2517,7 +2517,6 @@ worker_delete(struct worker* worker)
|
|||||||
tube_delete(worker->cmd);
|
tube_delete(worker->cmd);
|
||||||
comm_timer_delete(worker->stat_timer);
|
comm_timer_delete(worker->stat_timer);
|
||||||
comm_timer_delete(worker->env.probe_timer);
|
comm_timer_delete(worker->env.probe_timer);
|
||||||
free(worker->ports);
|
|
||||||
if(worker->thread_num == 0) {
|
if(worker->thread_num == 0) {
|
||||||
#ifdef UB_ON_WINDOWS
|
#ifdef UB_ON_WINDOWS
|
||||||
wsvc_desetup_worker(worker);
|
wsvc_desetup_worker(worker);
|
||||||
@@ -2653,6 +2652,11 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
|||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
|
|||||||
+1
-7
@@ -104,10 +104,6 @@ struct worker {
|
|||||||
struct listen_dnsport* front;
|
struct listen_dnsport* front;
|
||||||
/** the backside outside network interface to the auth servers */
|
/** the backside outside network interface to the auth servers */
|
||||||
struct outside_network* back;
|
struct outside_network* back;
|
||||||
/** ports to be used by this worker. */
|
|
||||||
int* ports;
|
|
||||||
/** number of ports for this worker */
|
|
||||||
int numports;
|
|
||||||
/** the signal handler */
|
/** the signal handler */
|
||||||
struct comm_signal* comsig;
|
struct comm_signal* comsig;
|
||||||
/** commpoint to listen to commands. */
|
/** commpoint to listen to commands. */
|
||||||
@@ -146,11 +142,9 @@ struct worker {
|
|||||||
* with backpointers only. Use worker_init on it later.
|
* with backpointers only. Use worker_init on it later.
|
||||||
* @param daemon: the daemon that this worker thread is part of.
|
* @param daemon: the daemon that this worker thread is part of.
|
||||||
* @param id: the thread number from 0.. numthreads-1.
|
* @param id: the thread number from 0.. numthreads-1.
|
||||||
* @param ports: the ports it is allowed to use, array.
|
|
||||||
* @param n: the number of ports.
|
|
||||||
* @return: the new worker or NULL on alloc failure.
|
* @return: the new worker or NULL on alloc failure.
|
||||||
*/
|
*/
|
||||||
struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n);
|
struct worker* worker_create(struct daemon* daemon, int id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize worker.
|
* Initialize worker.
|
||||||
|
|||||||
+23
-3
@@ -474,10 +474,18 @@ dnscrypt_server_curve(const dnsccert *cert,
|
|||||||
uint8_t *const buf = sldns_buffer_begin(buffer);
|
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||||
size_t len = sldns_buffer_limit(buffer);
|
size_t len = sldns_buffer_limit(buffer);
|
||||||
|
|
||||||
|
if(len + DNSCRYPT_REPLY_HEADER_SIZE > sldns_buffer_capacity(buffer))
|
||||||
|
return -1;
|
||||||
|
sldns_buffer_clear(buffer);
|
||||||
|
|
||||||
if(udp){
|
if(udp){
|
||||||
if (max_len > max_reply_size)
|
if (max_len > max_reply_size)
|
||||||
max_len = max_reply_size;
|
max_len = max_reply_size;
|
||||||
}
|
}
|
||||||
|
if(max_len > sldns_buffer_capacity(buffer))
|
||||||
|
max_len = sldns_buffer_capacity(buffer);
|
||||||
|
if(max_len > 65535)
|
||||||
|
max_len = 65535;
|
||||||
|
|
||||||
|
|
||||||
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
|
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
|
||||||
@@ -520,6 +528,7 @@ dnscrypt_server_curve(const dnsccert *cert,
|
|||||||
DNSCRYPT_MAGIC_HEADER_LEN,
|
DNSCRYPT_MAGIC_HEADER_LEN,
|
||||||
nonce,
|
nonce,
|
||||||
crypto_box_NONCEBYTES);
|
crypto_box_NONCEBYTES);
|
||||||
|
sldns_buffer_flip(buffer);
|
||||||
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -663,6 +672,8 @@ dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
|||||||
}
|
}
|
||||||
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
||||||
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
||||||
|
if(!certs[i].keypair)
|
||||||
|
continue;
|
||||||
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
||||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||||
return &certs[i];
|
return &certs[i];
|
||||||
@@ -804,6 +815,7 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
|||||||
sizeof *env->keypairs);
|
sizeof *env->keypairs);
|
||||||
env->certs = sodium_allocarray(env->signed_certs_count,
|
env->certs = sodium_allocarray(env->signed_certs_count,
|
||||||
sizeof *env->certs);
|
sizeof *env->certs);
|
||||||
|
memset(env->certs, 0, env->signed_certs_count * sizeof(*env->certs));
|
||||||
|
|
||||||
cert_id = 0U;
|
cert_id = 0U;
|
||||||
keypair_id = 0U;
|
keypair_id = 0U;
|
||||||
@@ -919,12 +931,13 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dnsc_handle_uncurved_request(struct comm_reply *repinfo)
|
dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
||||||
|
struct sldns_buffer* buffer)
|
||||||
{
|
{
|
||||||
if(!repinfo->c->dnscrypt) {
|
if(!repinfo->c->dnscrypt) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
|
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer);
|
||||||
if(!repinfo->is_dnscrypted) {
|
if(!repinfo->is_dnscrypted) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -970,12 +983,19 @@ dnsc_create(void)
|
|||||||
int
|
int
|
||||||
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
||||||
{
|
{
|
||||||
|
int nkeys;
|
||||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||||
}
|
}
|
||||||
if(dnsc_parse_keys(env, cfg) <= 0) {
|
nkeys = dnsc_parse_keys(env, cfg);
|
||||||
|
if(nkeys <= 0) {
|
||||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
||||||
}
|
}
|
||||||
|
if((size_t)nkeys < env->signed_certs_count) {
|
||||||
|
fatal_exit("dnsc_apply_cfg: %u dnscrypt-provider-cert file(s) have no "
|
||||||
|
"matching dnscrypt-secret-key",
|
||||||
|
(unsigned)(env->signed_certs_count - (size_t)nkeys));
|
||||||
|
}
|
||||||
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||||
env->provider_name = cfg->dnscrypt_provider;
|
env->provider_name = cfg->dnscrypt_provider;
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -128,7 +128,8 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
|||||||
* \return 0 in case of failure.
|
* \return 0 in case of failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
|
int dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
||||||
|
struct sldns_buffer* buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the size of the shared secret cache entry.
|
* Computes the size of the shared secret cache entry.
|
||||||
|
|||||||
@@ -1737,6 +1737,11 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
|||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
|
|||||||
@@ -2055,6 +2055,13 @@ These options are part of the ``server:`` section.
|
|||||||
flushing away any poison.
|
flushing away any poison.
|
||||||
A value of 10 million is suggested.
|
A value of 10 million is suggested.
|
||||||
|
|
||||||
|
It is useful to add 0.0.0.0/8 and '::' to the
|
||||||
|
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` list.
|
||||||
|
Otherwise they may be answered, from localhost, and the different source
|
||||||
|
makes an unwanted reply that unnecessarily ticks up.
|
||||||
|
The :ref:`do-not-query-localhost<unbound.conf.do-not-query-localhost>`
|
||||||
|
option includes them, the zero subnets, when it is enabled.
|
||||||
|
|
||||||
Default: 0 (disabled)
|
Default: 0 (disabled)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,18 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
|
|||||||
if(cfg->do_ip6) {
|
if(cfg->do_ip6) {
|
||||||
if(!donotq_str_cfg(dq, "::1"))
|
if(!donotq_str_cfg(dq, "::1"))
|
||||||
return 0;
|
return 0;
|
||||||
|
if(!donotq_str_cfg(dq, "::ffff:127.0.0.0/104"))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* RFC 1122 3.2.1.3 / RFC 6890 / RFC 4291 2.5.2: not valid as
|
||||||
|
* destination; on Linux these route to the local host. */
|
||||||
|
if(!donotq_str_cfg(dq, "0.0.0.0/8"))
|
||||||
|
return 0;
|
||||||
|
if(cfg->do_ip6) {
|
||||||
|
if(!donotq_str_cfg(dq, "::"))
|
||||||
|
return 0;
|
||||||
|
if(!donotq_str_cfg(dq, "::ffff:0:0/96"))
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addr_tree_init_parents(&dq->tree);
|
addr_tree_init_parents(&dq->tree);
|
||||||
|
|||||||
+47
-20
@@ -81,7 +81,8 @@ int BLACKLIST_PENALTY = (120000*4);
|
|||||||
/** Timeout when only a single probe query per IP is allowed. */
|
/** Timeout when only a single probe query per IP is allowed. */
|
||||||
int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
|
int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
|
||||||
|
|
||||||
static void target_count_increase_nx(struct iter_qstate* iq, int num);
|
static void target_count_increase_nx(struct module_qstate* qstate,
|
||||||
|
struct iter_qstate* iq, int num);
|
||||||
|
|
||||||
int
|
int
|
||||||
iter_init(struct module_env* env, int id)
|
iter_init(struct module_env* env, int id)
|
||||||
@@ -250,7 +251,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
|||||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
|
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
|
||||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||||
dpns->resolved = 1; /* mark as failed */
|
dpns->resolved = 1; /* mark as failed */
|
||||||
target_count_increase_nx(super_iq, 1);
|
target_count_increase_nx(super, super_iq, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
|
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
|
||||||
@@ -734,7 +735,7 @@ is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
|
|||||||
* created for the parent query.
|
* created for the parent query.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
target_count_create(struct iter_qstate* iq)
|
target_count_create(struct module_qstate* qstate, struct iter_qstate* iq)
|
||||||
{
|
{
|
||||||
if(!iq->target_count) {
|
if(!iq->target_count) {
|
||||||
iq->target_count = (int*)calloc(TARGET_COUNT_MAX, sizeof(int));
|
iq->target_count = (int*)calloc(TARGET_COUNT_MAX, sizeof(int));
|
||||||
@@ -742,33 +743,57 @@ target_count_create(struct iter_qstate* iq)
|
|||||||
if(iq->target_count) {
|
if(iq->target_count) {
|
||||||
iq->target_count[TARGET_COUNT_REF] = 1;
|
iq->target_count[TARGET_COUNT_REF] = 1;
|
||||||
iq->nxns_dp = (uint8_t**)calloc(1, sizeof(uint8_t*));
|
iq->nxns_dp = (uint8_t**)calloc(1, sizeof(uint8_t*));
|
||||||
|
/* continue global quota from where it was. */
|
||||||
|
if(qstate->global_quota_reached >
|
||||||
|
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA])
|
||||||
|
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] =
|
||||||
|
qstate->global_quota_reached;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
target_count_increase(struct iter_qstate* iq, int num)
|
target_count_store(struct module_qstate* qstate, struct iter_qstate* iq)
|
||||||
{
|
{
|
||||||
target_count_create(iq);
|
if(iq->target_count) {
|
||||||
|
/* By storing the global quota counter, it stays
|
||||||
|
* there to be picked up if the module is restarted,
|
||||||
|
* eg. due to a validator retry, and then the
|
||||||
|
* target_count_create routine picks it up. */
|
||||||
|
if(iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] >
|
||||||
|
qstate->global_quota_reached)
|
||||||
|
qstate->global_quota_reached =
|
||||||
|
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
target_count_increase(struct module_qstate* qstate,
|
||||||
|
struct iter_qstate* iq, int num)
|
||||||
|
{
|
||||||
|
target_count_create(qstate, iq);
|
||||||
if(iq->target_count)
|
if(iq->target_count)
|
||||||
iq->target_count[TARGET_COUNT_QUERIES] += num;
|
iq->target_count[TARGET_COUNT_QUERIES] += num;
|
||||||
iq->dp_target_count++;
|
iq->dp_target_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
target_count_increase_nx(struct iter_qstate* iq, int num)
|
target_count_increase_nx(struct module_qstate* qstate,
|
||||||
|
struct iter_qstate* iq, int num)
|
||||||
{
|
{
|
||||||
target_count_create(iq);
|
target_count_create(qstate, iq);
|
||||||
if(iq->target_count)
|
if(iq->target_count)
|
||||||
iq->target_count[TARGET_COUNT_NX] += num;
|
iq->target_count[TARGET_COUNT_NX] += num;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
target_count_increase_global_quota(struct iter_qstate* iq, int num)
|
target_count_increase_global_quota(struct module_qstate* qstate,
|
||||||
|
struct iter_qstate* iq, int num)
|
||||||
{
|
{
|
||||||
target_count_create(iq);
|
target_count_create(qstate, iq);
|
||||||
if(iq->target_count)
|
if(iq->target_count)
|
||||||
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] += num;
|
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] += num;
|
||||||
|
target_count_store(qstate, iq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -861,7 +886,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
|||||||
subiq = (struct iter_qstate*)subq->minfo[id];
|
subiq = (struct iter_qstate*)subq->minfo[id];
|
||||||
memset(subiq, 0, sizeof(*subiq));
|
memset(subiq, 0, sizeof(*subiq));
|
||||||
subiq->num_target_queries = 0;
|
subiq->num_target_queries = 0;
|
||||||
target_count_create(iq);
|
target_count_create(qstate, iq);
|
||||||
subiq->target_count = iq->target_count;
|
subiq->target_count = iq->target_count;
|
||||||
if(iq->target_count) {
|
if(iq->target_count) {
|
||||||
iq->target_count[TARGET_COUNT_REF] ++; /* extra reference */
|
iq->target_count[TARGET_COUNT_REF] ++; /* extra reference */
|
||||||
@@ -2235,7 +2260,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
iq->num_target_queries += qs;
|
iq->num_target_queries += qs;
|
||||||
target_count_increase(iq, qs);
|
target_count_increase(qstate, iq, qs);
|
||||||
if(qs != 0) {
|
if(qs != 0) {
|
||||||
qstate->ext_state[id] = module_wait_subquery;
|
qstate->ext_state[id] = module_wait_subquery;
|
||||||
return 0; /* and wait for them */
|
return 0; /* and wait for them */
|
||||||
@@ -2291,7 +2316,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
* lookups at a time. */
|
* lookups at a time. */
|
||||||
verbose(VERB_ALGO, "try parent-side glue lookup");
|
verbose(VERB_ALGO, "try parent-side glue lookup");
|
||||||
iq->num_target_queries += query_count;
|
iq->num_target_queries += query_count;
|
||||||
target_count_increase(iq, query_count);
|
target_count_increase(qstate, iq, query_count);
|
||||||
qstate->ext_state[id] = module_wait_subquery;
|
qstate->ext_state[id] = module_wait_subquery;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2311,7 +2336,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
if(query_count != 0) { /* suspend to await results */
|
if(query_count != 0) { /* suspend to await results */
|
||||||
verbose(VERB_ALGO, "try parent-side glue lookup");
|
verbose(VERB_ALGO, "try parent-side glue lookup");
|
||||||
iq->num_target_queries += query_count;
|
iq->num_target_queries += query_count;
|
||||||
target_count_increase(iq, query_count);
|
target_count_increase(qstate, iq, query_count);
|
||||||
qstate->ext_state[id] = module_wait_subquery;
|
qstate->ext_state[id] = module_wait_subquery;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2795,7 +2820,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
iq->num_target_queries += extra;
|
iq->num_target_queries += extra;
|
||||||
target_count_increase(iq, extra);
|
target_count_increase(qstate, iq, extra);
|
||||||
if(iq->num_target_queries > 0) {
|
if(iq->num_target_queries > 0) {
|
||||||
/* wait to get all targets, we want to try em */
|
/* wait to get all targets, we want to try em */
|
||||||
verbose(VERB_ALGO, "wait for all targets for fallback");
|
verbose(VERB_ALGO, "wait for all targets for fallback");
|
||||||
@@ -2846,7 +2871,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
/* errors ignored, these targets are not strictly necessary for
|
/* errors ignored, these targets are not strictly necessary for
|
||||||
* this result, we do not have to reply with SERVFAIL */
|
* this result, we do not have to reply with SERVFAIL */
|
||||||
iq->num_target_queries += extra;
|
iq->num_target_queries += extra;
|
||||||
target_count_increase(iq, extra);
|
target_count_increase(qstate, iq, extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the current set of unused targets to our queue. */
|
/* Add the current set of unused targets to our queue. */
|
||||||
@@ -2969,7 +2994,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
LDNS_RCODE_SERVFAIL);
|
LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
iq->num_target_queries += qs;
|
iq->num_target_queries += qs;
|
||||||
target_count_increase(iq, qs);
|
target_count_increase(qstate, iq, qs);
|
||||||
}
|
}
|
||||||
/* Since a target query might have been made, we
|
/* Since a target query might have been made, we
|
||||||
* need to check again. */
|
* need to check again. */
|
||||||
@@ -3029,7 +3054,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
* this result, we do not have to reply with SERVFAIL */
|
* this result, we do not have to reply with SERVFAIL */
|
||||||
if(extra > 0) {
|
if(extra > 0) {
|
||||||
iq->num_target_queries += extra;
|
iq->num_target_queries += extra;
|
||||||
target_count_increase(iq, extra);
|
target_count_increase(qstate, iq, extra);
|
||||||
check_waiting_queries(iq, qstate, id);
|
check_waiting_queries(iq, qstate, id);
|
||||||
/* undo qname minimise step because we'll get back here
|
/* undo qname minimise step because we'll get back here
|
||||||
* to do it again */
|
* to do it again */
|
||||||
@@ -3042,7 +3067,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target_count_increase_global_quota(iq, 1);
|
target_count_increase_global_quota(qstate, iq, 1);
|
||||||
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
|
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
|
||||||
> MAX_GLOBAL_QUOTA) {
|
> MAX_GLOBAL_QUOTA) {
|
||||||
char s[LDNS_MAX_DOMAINLEN];
|
char s[LDNS_MAX_DOMAINLEN];
|
||||||
@@ -3897,7 +3922,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
|||||||
/* no new addresses, increase the nxns counter, like
|
/* no new addresses, increase the nxns counter, like
|
||||||
* this could be a list of wildcards with no new
|
* this could be a list of wildcards with no new
|
||||||
* addresses */
|
* addresses */
|
||||||
target_count_increase_nx(foriq, 1);
|
target_count_increase_nx(qstate, foriq, 1);
|
||||||
}
|
}
|
||||||
verbose(VERB_ALGO, "added target response");
|
verbose(VERB_ALGO, "added target response");
|
||||||
delegpt_log(VERB_ALGO, foriq->dp);
|
delegpt_log(VERB_ALGO, foriq->dp);
|
||||||
@@ -3909,7 +3934,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
|||||||
dpns->resolved = 1; /* fail the target */
|
dpns->resolved = 1; /* fail the target */
|
||||||
/* do not count cached answers */
|
/* do not count cached answers */
|
||||||
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
|
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
|
||||||
target_count_increase_nx(foriq, 1);
|
target_count_increase_nx(qstate, foriq, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4159,6 +4184,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||||||
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
|
||||||
iq->deleg_msg?iq->deleg_msg->rep:
|
iq->deleg_msg?iq->deleg_msg->rep:
|
||||||
(iq->response?iq->response->rep:NULL));
|
(iq->response?iq->response->rep:NULL));
|
||||||
|
target_count_store(qstate, iq);
|
||||||
if(!iq->response) {
|
if(!iq->response) {
|
||||||
verbose(VERB_ALGO, "No response is set, servfail");
|
verbose(VERB_ALGO, "No response is set, servfail");
|
||||||
errinf(qstate, "(no response found at query finish)");
|
errinf(qstate, "(no response found at query finish)");
|
||||||
@@ -4577,6 +4603,7 @@ iter_clear(struct module_qstate* qstate, int id)
|
|||||||
iq = (struct iter_qstate*)qstate->minfo[id];
|
iq = (struct iter_qstate*)qstate->minfo[id];
|
||||||
if(iq) {
|
if(iq) {
|
||||||
outbound_list_clear(&iq->outlist);
|
outbound_list_clear(&iq->outlist);
|
||||||
|
target_count_store(qstate, iq);
|
||||||
if(iq->target_count && --iq->target_count[TARGET_COUNT_REF] == 0) {
|
if(iq->target_count && --iq->target_count[TARGET_COUNT_REF] == 0) {
|
||||||
free(iq->target_count);
|
free(iq->target_count);
|
||||||
if(*iq->nxns_dp) free(*iq->nxns_dp);
|
if(*iq->nxns_dp) free(*iq->nxns_dp);
|
||||||
|
|||||||
+11
-2
@@ -105,6 +105,7 @@ libworker_delete_env(struct libworker* w)
|
|||||||
SSL_CTX_free(w->sslctx);
|
SSL_CTX_free(w->sslctx);
|
||||||
#endif
|
#endif
|
||||||
outside_network_delete(w->back);
|
outside_network_delete(w->back);
|
||||||
|
shared_ports_delete(w->shared_ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** delete libworker struct */
|
/** delete libworker struct */
|
||||||
@@ -219,17 +220,25 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
|||||||
libworker_delete(w);
|
libworker_delete(w);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if(!(w->shared_ports = shared_ports_create(cfg->out_ifs,
|
||||||
|
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, ports, numports))) {
|
||||||
|
if(!w->is_bg || w->is_bg_thread) {
|
||||||
|
lock_basic_unlock(&ctx->cfglock);
|
||||||
|
}
|
||||||
|
libworker_delete(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
|
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
|
||||||
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
|
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
|
||||||
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
|
||||||
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
|
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
|
||||||
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
|
||||||
ports, numports, cfg->unwanted_threshold,
|
cfg->unwanted_threshold,
|
||||||
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
|
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
|
||||||
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
|
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
|
||||||
cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect,
|
cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect,
|
||||||
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
|
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
|
||||||
cfg->tcp_auth_query_timeout);
|
cfg->tcp_auth_query_timeout, w->shared_ports);
|
||||||
w->env->outnet = w->back;
|
w->env->outnet = w->back;
|
||||||
if(!w->is_bg || w->is_bg_thread) {
|
if(!w->is_bg || w->is_bg_thread) {
|
||||||
lock_basic_unlock(&ctx->cfglock);
|
lock_basic_unlock(&ctx->cfglock);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ struct tube;
|
|||||||
struct sldns_buffer;
|
struct sldns_buffer;
|
||||||
struct ub_event_base;
|
struct ub_event_base;
|
||||||
struct query_info;
|
struct query_info;
|
||||||
|
struct shared_ports;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The library-worker status structure
|
* The library-worker status structure
|
||||||
@@ -84,6 +85,8 @@ struct libworker {
|
|||||||
struct comm_base* base;
|
struct comm_base* base;
|
||||||
/** the backside outside network interface to the auth servers */
|
/** the backside outside network interface to the auth servers */
|
||||||
struct outside_network* back;
|
struct outside_network* back;
|
||||||
|
/** shared ports structure */
|
||||||
|
struct shared_ports* shared_ports;
|
||||||
/** random() table for this worker. */
|
/** random() table for this worker. */
|
||||||
struct ub_randstate* rndstate;
|
struct ub_randstate* rndstate;
|
||||||
/** sslcontext for SSL wrapped DNS over TCP queries */
|
/** sslcontext for SSL wrapped DNS over TCP queries */
|
||||||
|
|||||||
+7
-1
@@ -1121,7 +1121,13 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||||||
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA ||
|
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA ||
|
||||||
qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) &&
|
qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) &&
|
||||||
qstate->return_msg && qstate->return_msg->rep) {
|
qstate->return_msg && qstate->return_msg->rep &&
|
||||||
|
!(qstate->env->need_to_validate &&
|
||||||
|
(!(qstate->query_flags & BIT_CD)
|
||||||
|
|| qstate->env->cfg->ignore_cd) &&
|
||||||
|
(qstate->return_msg->rep->security <= sec_status_bogus
|
||||||
|
|| qstate->return_msg->rep->security ==
|
||||||
|
sec_status_secure_sentinel_fail))) {
|
||||||
struct reply_info* new_rep = qstate->return_msg->rep;
|
struct reply_info* new_rep = qstate->return_msg->rep;
|
||||||
struct ub_packed_rrset_key* alias_rrset = NULL;
|
struct ub_packed_rrset_key* alias_rrset = NULL;
|
||||||
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
|
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
|
||||||
|
|||||||
+22
-6
@@ -5880,8 +5880,7 @@ xfer_target_equals_answer_name(struct auth_master* lookup_target,
|
|||||||
|
|
||||||
/** callback for task_transfer lookup of host name, of A or AAAA */
|
/** callback for task_transfer lookup of host name, of A or AAAA */
|
||||||
void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus),
|
enum sec_status sec, char* why_bogus, int ATTR_UNUSED(was_ratelimited))
|
||||||
int ATTR_UNUSED(was_ratelimited))
|
|
||||||
{
|
{
|
||||||
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
||||||
struct module_env* env;
|
struct module_env* env;
|
||||||
@@ -5894,7 +5893,16 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* process result */
|
/* process result */
|
||||||
if(rcode == LDNS_RCODE_NOERROR) {
|
if(sec == sec_status_bogus || sec == sec_status_secure_sentinel_fail) {
|
||||||
|
if(verbosity >= VERB_OPS) {
|
||||||
|
char zname[LDNS_MAX_DOMAINLEN];
|
||||||
|
dname_str(xfr->name, zname);
|
||||||
|
verbose(VERB_OPS, "auth zone %s: primary %s address lookup is DNSSEC bogus: %s",
|
||||||
|
zname, xfr->task_transfer->lookup_target->host,
|
||||||
|
(why_bogus?why_bogus:""));
|
||||||
|
}
|
||||||
|
/* fall through to next-lookup / next-master */
|
||||||
|
} else if(rcode == LDNS_RCODE_NOERROR) {
|
||||||
uint16_t wanted_qtype = LDNS_RR_TYPE_A;
|
uint16_t wanted_qtype = LDNS_RR_TYPE_A;
|
||||||
struct regional* temp = env->scratch;
|
struct regional* temp = env->scratch;
|
||||||
struct query_info rq;
|
struct query_info rq;
|
||||||
@@ -7031,8 +7039,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
|||||||
|
|
||||||
/** callback for task_probe lookup of host name, of A or AAAA */
|
/** callback for task_probe lookup of host name, of A or AAAA */
|
||||||
void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||||
enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus),
|
enum sec_status sec, char* why_bogus, int ATTR_UNUSED(was_ratelimited))
|
||||||
int ATTR_UNUSED(was_ratelimited))
|
|
||||||
{
|
{
|
||||||
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
struct auth_xfer* xfr = (struct auth_xfer*)arg;
|
||||||
struct module_env* env;
|
struct module_env* env;
|
||||||
@@ -7045,7 +7052,16 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* process result */
|
/* process result */
|
||||||
if(rcode == LDNS_RCODE_NOERROR) {
|
if(sec == sec_status_bogus || sec == sec_status_secure_sentinel_fail) {
|
||||||
|
if(verbosity >= VERB_OPS) {
|
||||||
|
char zname[LDNS_MAX_DOMAINLEN];
|
||||||
|
dname_str(xfr->name, zname);
|
||||||
|
verbose(VERB_OPS, "auth zone %s: primary %s address probe lookup is DNSSEC bogus: %s",
|
||||||
|
zname, xfr->task_transfer->lookup_target->host,
|
||||||
|
(why_bogus?why_bogus:""));
|
||||||
|
}
|
||||||
|
/* fall through to next-lookup / next-master */
|
||||||
|
} else if(rcode == LDNS_RCODE_NOERROR) {
|
||||||
uint16_t wanted_qtype = LDNS_RR_TYPE_A;
|
uint16_t wanted_qtype = LDNS_RR_TYPE_A;
|
||||||
struct regional* temp = env->scratch;
|
struct regional* temp = env->scratch;
|
||||||
struct query_info rq;
|
struct query_info rq;
|
||||||
|
|||||||
Vendored
+3
-1
@@ -277,6 +277,8 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
|||||||
|
|
||||||
/* snip off front label */
|
/* snip off front label */
|
||||||
lablen = *qname;
|
lablen = *qname;
|
||||||
|
if(lablen == 0)
|
||||||
|
break;
|
||||||
qname += lablen + 1;
|
qname += lablen + 1;
|
||||||
qnamelen -= lablen + 1;
|
qnamelen -= lablen + 1;
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1077,7 @@ dns_cache_lookup(struct module_env* env,
|
|||||||
if(env->cfg->harden_below_nxdomain) {
|
if(env->cfg->harden_below_nxdomain) {
|
||||||
while(!dname_is_root(k.qname)) {
|
while(!dname_is_root(k.qname)) {
|
||||||
if(dpname && dpnamelen
|
if(dpname && dpnamelen
|
||||||
&& !dname_subdomain_c(k.qname, dpname))
|
&& !dname_strict_subdomain_c(k.qname, dpname))
|
||||||
break; /* no synth nxdomain above the stub */
|
break; /* no synth nxdomain above the stub */
|
||||||
dname_remove_label(&k.qname, &k.qname_len);
|
dname_remove_label(&k.qname, &k.qname_len);
|
||||||
h = query_info_hash(&k, flags);
|
h = query_info_hash(&k, flags);
|
||||||
|
|||||||
Vendored
+41
-3
@@ -50,6 +50,7 @@
|
|||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/alloc.h"
|
#include "util/alloc.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
|
#include "validator/val_utils.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
rrset_markdel(void* key)
|
rrset_markdel(void* key)
|
||||||
@@ -126,7 +127,8 @@ rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
|||||||
|
|
||||||
/** see if rrset needs to be updated in the cache */
|
/** see if rrset needs to be updated in the cache */
|
||||||
static int
|
static int
|
||||||
need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns,
|
||||||
|
int a_aaaa)
|
||||||
{
|
{
|
||||||
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
|
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
|
||||||
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
||||||
@@ -151,9 +153,13 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
|||||||
return 0;
|
return 0;
|
||||||
/* ghost-domain: never let an NS overwrite extend lifetime
|
/* ghost-domain: never let an NS overwrite extend lifetime
|
||||||
* past the entry it replaces, regardless of trust. */
|
* past the entry it replaces, regardless of trust. */
|
||||||
if(ns && !TTL_IS_EXPIRED(cached->ttl, timenow) &&
|
/* Also for A/AAAA and it is glue. */
|
||||||
|
if((ns ||
|
||||||
|
(a_aaaa && cached->trust==rrset_trust_add_noAA))
|
||||||
|
&& !TTL_IS_EXPIRED(cached->ttl, timenow) &&
|
||||||
newd->ttl > cached->ttl) {
|
newd->ttl > cached->ttl) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
if(a_aaaa) newd->trust=rrset_trust_add_noAA;
|
||||||
newd->ttl = cached->ttl;
|
newd->ttl = cached->ttl;
|
||||||
for(i=0; i<(newd->count+newd->rrsig_count); i++)
|
for(i=0; i<(newd->count+newd->rrsig_count); i++)
|
||||||
if(newd->rr_ttl[i] > newd->ttl)
|
if(newd->rr_ttl[i] > newd->ttl)
|
||||||
@@ -230,7 +236,8 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
|||||||
equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
|
equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
|
||||||
data, (struct packed_rrset_data*)e->data);
|
data, (struct packed_rrset_data*)e->data);
|
||||||
if(!need_to_update_rrset(k->entry.data, e->data, timenow,
|
if(!need_to_update_rrset(k->entry.data, e->data, timenow,
|
||||||
equal, (rrset_type==LDNS_RR_TYPE_NS))) {
|
equal, (rrset_type==LDNS_RR_TYPE_NS),
|
||||||
|
(rrset_type==LDNS_RR_TYPE_A || rrset_type==LDNS_RR_TYPE_AAAA))) {
|
||||||
/* cache is superior, return that value */
|
/* cache is superior, return that value */
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
ub_packed_rrset_parsedelete(k, alloc);
|
ub_packed_rrset_parsedelete(k, alloc);
|
||||||
@@ -262,6 +269,29 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** See if the name is a within signer authority */
|
||||||
|
static int
|
||||||
|
dname_subdomain_rrsig_signers(uint8_t* dname,
|
||||||
|
struct ub_packed_rrset_key* rrset)
|
||||||
|
{
|
||||||
|
struct packed_rrset_data* d = (struct packed_rrset_data*)
|
||||||
|
rrset->entry.data;
|
||||||
|
size_t i;
|
||||||
|
if(!d || !d->rrsig_count)
|
||||||
|
return 0;
|
||||||
|
for(i=0; i<d->rrsig_count; i++) {
|
||||||
|
uint8_t* sname = NULL;
|
||||||
|
size_t slen = 0;
|
||||||
|
rrsig_get_signer(d->rr_data[d->count+i], d->rr_len[d->count+i],
|
||||||
|
&sname, &slen);
|
||||||
|
if(!sname || !slen)
|
||||||
|
return 0; /* malformed */
|
||||||
|
if(!dname_subdomain_c(dname, sname))
|
||||||
|
return 0; /* not a subdomain */
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
||||||
struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len,
|
struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len,
|
||||||
struct alloc_cache* alloc, time_t timenow)
|
struct alloc_cache* alloc, time_t timenow)
|
||||||
@@ -270,6 +300,14 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
|||||||
uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3];
|
uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3];
|
||||||
uint8_t* new_dname;
|
uint8_t* new_dname;
|
||||||
size_t new_dname_len;
|
size_t new_dname_len;
|
||||||
|
|
||||||
|
/* See if the RRSIG signer name allows this wildcard,
|
||||||
|
* the new rrset should fall within the zone of the RRSIG signer(s). */
|
||||||
|
if(!dname_subdomain_rrsig_signers(ce, rrset)) {
|
||||||
|
verbose(VERB_ALGO, "wildcard canonical parent outside signer authority");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rrset = packed_rrset_copy_alloc(rrset, alloc, timenow);
|
rrset = packed_rrset_copy_alloc(rrset, alloc, timenow);
|
||||||
if(!rrset) {
|
if(!rrset) {
|
||||||
log_err("malloc failure in rrset_cache_update_wildcard");
|
log_err("malloc failure in rrset_cache_update_wildcard");
|
||||||
|
|||||||
+158
-75
@@ -42,7 +42,6 @@
|
|||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/time.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#ifdef USE_TCP_FASTOPEN
|
#ifdef USE_TCP_FASTOPEN
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
@@ -2168,7 +2167,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
|
|||||||
while(open) {
|
while(open) {
|
||||||
nopen = open->next;
|
nopen = open->next;
|
||||||
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp,
|
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
free(open);
|
free(open);
|
||||||
open = nopen;
|
open = nopen;
|
||||||
}
|
}
|
||||||
@@ -3400,14 +3399,13 @@ doq_table_delete(struct doq_table* table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct doq_timer*
|
struct doq_timer*
|
||||||
doq_timer_find_time(struct doq_table* table, struct timeval* tv)
|
doq_timer_find_time(struct doq_table* table, ngtcp2_tstamp ts)
|
||||||
{
|
{
|
||||||
struct doq_timer key;
|
struct doq_timer key;
|
||||||
struct rbnode_type* node;
|
struct rbnode_type* node;
|
||||||
log_assert(table != NULL);
|
log_assert(table != NULL);
|
||||||
memset(&key, 0, sizeof(key));
|
memset(&key, 0, sizeof(key));
|
||||||
key.time.tv_sec = tv->tv_sec;
|
key.time_mono = ts;
|
||||||
key.time.tv_usec = tv->tv_usec;
|
|
||||||
node = rbtree_search(table->timer_tree, &key);
|
node = rbtree_search(table->timer_tree, &key);
|
||||||
if(node)
|
if(node)
|
||||||
return (struct doq_timer*)node->key;
|
return (struct doq_timer*)node->key;
|
||||||
@@ -3455,7 +3453,7 @@ doq_timer_list_remove(struct doq_table* table, struct doq_timer* timer)
|
|||||||
if(!timer->timer_in_list)
|
if(!timer->timer_in_list)
|
||||||
return;
|
return;
|
||||||
/* The item in the rbtree has the list start and end. */
|
/* The item in the rbtree has the list start and end. */
|
||||||
rb_timer = doq_timer_find_time(table, &timer->time);
|
rb_timer = doq_timer_find_time(table, timer->time_mono);
|
||||||
if(rb_timer) {
|
if(rb_timer) {
|
||||||
if(timer->setlist_prev)
|
if(timer->setlist_prev)
|
||||||
timer->setlist_prev->setlist_next = timer->setlist_next;
|
timer->setlist_prev->setlist_next = timer->setlist_next;
|
||||||
@@ -3501,7 +3499,8 @@ doq_timer_unset(struct doq_table* table, struct doq_timer* timer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
||||||
struct doq_server_socket* worker_doq_socket, struct timeval* tv)
|
struct doq_server_socket* worker_doq_socket, struct timeval* tv,
|
||||||
|
ngtcp2_tstamp ts)
|
||||||
{
|
{
|
||||||
struct doq_timer* rb_timer;
|
struct doq_timer* rb_timer;
|
||||||
if(verbosity >= VERB_ALGO && timer->conn) {
|
if(verbosity >= VERB_ALGO && timer->conn) {
|
||||||
@@ -3515,14 +3514,14 @@ void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
|||||||
(int)rel.tv_sec, (int)rel.tv_usec);
|
(int)rel.tv_sec, (int)rel.tv_usec);
|
||||||
}
|
}
|
||||||
if(timer->timer_in_tree || timer->timer_in_list) {
|
if(timer->timer_in_tree || timer->timer_in_list) {
|
||||||
if(timer->time.tv_sec == tv->tv_sec &&
|
if(timer->time_mono == ts)
|
||||||
timer->time.tv_usec == tv->tv_usec)
|
|
||||||
return; /* already set on that time */
|
return; /* already set on that time */
|
||||||
doq_timer_unset(table, timer);
|
doq_timer_unset(table, timer);
|
||||||
}
|
}
|
||||||
timer->time.tv_sec = tv->tv_sec;
|
timer->time_real.tv_sec = tv->tv_sec;
|
||||||
timer->time.tv_usec = tv->tv_usec;
|
timer->time_real.tv_usec = tv->tv_usec;
|
||||||
rb_timer = doq_timer_find_time(table, tv);
|
timer->time_mono = ts;
|
||||||
|
rb_timer = doq_timer_find_time(table, ts);
|
||||||
if(rb_timer) {
|
if(rb_timer) {
|
||||||
/* There is a timeout already with this value. Timer is
|
/* There is a timeout already with this value. Timer is
|
||||||
* added to the setlist. */
|
* added to the setlist. */
|
||||||
@@ -3598,15 +3597,29 @@ doq_conn_create(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The arguments for doq stream tree del. */
|
||||||
|
struct doq_stream_tree_del_args {
|
||||||
|
/** The doq table. */
|
||||||
|
struct doq_table* table;
|
||||||
|
/** The doq connection for the stream. */
|
||||||
|
struct doq_conn* conn;
|
||||||
|
};
|
||||||
|
|
||||||
/** delete stream tree node */
|
/** delete stream tree node */
|
||||||
static void
|
static void
|
||||||
stream_tree_del(rbnode_type* node, void* arg)
|
stream_tree_del(rbnode_type* node, void* arg)
|
||||||
{
|
{
|
||||||
struct doq_table* table = (struct doq_table*)arg;
|
struct doq_stream_tree_del_args* args = (struct doq_stream_tree_del_args*)arg;
|
||||||
|
struct doq_table* table = args->table;
|
||||||
struct doq_stream* stream;
|
struct doq_stream* stream;
|
||||||
if(!node)
|
if(!node)
|
||||||
return;
|
return;
|
||||||
stream = (struct doq_stream*)node;
|
stream = (struct doq_stream*)node;
|
||||||
|
if(stream->mesh_state) {
|
||||||
|
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
|
||||||
|
args->conn->doq_socket->cp, NULL, stream);
|
||||||
|
stream->mesh_state = NULL;
|
||||||
|
}
|
||||||
if(stream->in)
|
if(stream->in)
|
||||||
doq_table_quic_size_subtract(table, stream->inlen);
|
doq_table_quic_size_subtract(table, stream->inlen);
|
||||||
if(stream->out)
|
if(stream->out)
|
||||||
@@ -3629,7 +3642,11 @@ doq_conn_delete(struct doq_conn* conn, struct doq_table* table)
|
|||||||
if(conn->ssl)
|
if(conn->ssl)
|
||||||
SSL_set_app_data(conn->ssl, NULL);
|
SSL_set_app_data(conn->ssl, NULL);
|
||||||
if(conn->stream_tree.count != 0) {
|
if(conn->stream_tree.count != 0) {
|
||||||
traverse_postorder(&conn->stream_tree, stream_tree_del, table);
|
struct doq_stream_tree_del_args args;
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
args.table = table;
|
||||||
|
args.conn = conn;
|
||||||
|
traverse_postorder(&conn->stream_tree, stream_tree_del, &args);
|
||||||
}
|
}
|
||||||
free(conn->key.dcid);
|
free(conn->key.dcid);
|
||||||
SSL_free(conn->ssl);
|
SSL_free(conn->ssl);
|
||||||
@@ -3702,13 +3719,9 @@ int doq_timer_cmp(const void* key1, const void* key2)
|
|||||||
{
|
{
|
||||||
struct doq_timer* e = (struct doq_timer*)key1;
|
struct doq_timer* e = (struct doq_timer*)key1;
|
||||||
struct doq_timer* f = (struct doq_timer*)key2;
|
struct doq_timer* f = (struct doq_timer*)key2;
|
||||||
if(e->time.tv_sec < f->time.tv_sec)
|
if(e->time_mono < f->time_mono)
|
||||||
return -1;
|
return -1;
|
||||||
if(e->time.tv_sec > f->time.tv_sec)
|
if(e->time_mono > f->time_mono)
|
||||||
return 1;
|
|
||||||
if(e->time.tv_usec < f->time.tv_usec)
|
|
||||||
return -1;
|
|
||||||
if(e->time.tv_usec > f->time.tv_usec)
|
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3942,6 +3955,11 @@ doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
|
|||||||
if(stream->is_closed)
|
if(stream->is_closed)
|
||||||
return 1;
|
return 1;
|
||||||
stream->is_closed = 1;
|
stream->is_closed = 1;
|
||||||
|
if(stream->mesh_state) {
|
||||||
|
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
|
||||||
|
conn->doq_socket->cp, NULL, stream);
|
||||||
|
stream->mesh_state = NULL;
|
||||||
|
}
|
||||||
doq_stream_off_write_list(conn, stream);
|
doq_stream_off_write_list(conn, stream);
|
||||||
if(send_shutdown) {
|
if(send_shutdown) {
|
||||||
verbose(VERB_ALGO, "doq: shutdown stream_id %d with app_error_code %d",
|
verbose(VERB_ALGO, "doq: shutdown stream_id %d with app_error_code %d",
|
||||||
@@ -3971,7 +3989,8 @@ doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
|
|||||||
|
|
||||||
/** doq stream pick up answer data from buffer */
|
/** doq stream pick up answer data from buffer */
|
||||||
static int
|
static int
|
||||||
doq_stream_pickup_answer(struct doq_stream* stream, struct sldns_buffer* buf)
|
doq_stream_pickup_answer(struct doq_conn* conn, struct doq_stream* stream,
|
||||||
|
struct sldns_buffer* buf)
|
||||||
{
|
{
|
||||||
stream->is_answer_available = 1;
|
stream->is_answer_available = 1;
|
||||||
if(stream->out) {
|
if(stream->out) {
|
||||||
@@ -3981,6 +4000,11 @@ doq_stream_pickup_answer(struct doq_stream* stream, struct sldns_buffer* buf)
|
|||||||
}
|
}
|
||||||
stream->nwrite = 0;
|
stream->nwrite = 0;
|
||||||
stream->outlen = sldns_buffer_limit(buf);
|
stream->outlen = sldns_buffer_limit(buf);
|
||||||
|
if(!doq_table_quic_size_available(conn->doq_socket->table,
|
||||||
|
conn->doq_socket->cfg, stream->outlen)) {
|
||||||
|
verbose(VERB_ALGO, "doq stream: no space for reply length");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* For quic the output bytes have to stay allocated and available,
|
/* For quic the output bytes have to stay allocated and available,
|
||||||
* for potential resends, until the remote end has acknowledged them.
|
* for potential resends, until the remote end has acknowledged them.
|
||||||
* This includes the tcplen start uint16_t, in outlen_wire. */
|
* This includes the tcplen start uint16_t, in outlen_wire. */
|
||||||
@@ -4007,24 +4031,56 @@ doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
|
|||||||
if(stream->out)
|
if(stream->out)
|
||||||
doq_table_quic_size_subtract(conn->doq_socket->table,
|
doq_table_quic_size_subtract(conn->doq_socket->table,
|
||||||
stream->outlen);
|
stream->outlen);
|
||||||
if(!doq_stream_pickup_answer(stream, buf))
|
if(!doq_stream_pickup_answer(conn, stream, buf))
|
||||||
return 0;
|
return 0;
|
||||||
doq_table_quic_size_add(conn->doq_socket->table, stream->outlen);
|
doq_table_quic_size_add(conn->doq_socket->table, stream->outlen);
|
||||||
doq_stream_on_write_list(conn, stream);
|
doq_stream_on_write_list(conn, stream);
|
||||||
doq_conn_write_enable(conn);
|
doq_conn_write_enable(conn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_NGTCP2 */
|
||||||
|
|
||||||
|
void
|
||||||
|
doq_stream_add_meshstate(struct doq_stream* stream,
|
||||||
|
struct mesh_area* mesh, struct mesh_state* m)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
|
stream->mesh = mesh;
|
||||||
|
stream->mesh_state = m;
|
||||||
|
#else
|
||||||
|
(void)stream; (void)mesh; (void)m;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
doq_stream_remove_mesh_state(struct doq_stream* stream)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
|
if(!stream)
|
||||||
|
return;
|
||||||
|
stream->mesh_state = NULL;
|
||||||
|
#else
|
||||||
|
(void)stream;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
/** doq stream data length has completed, allocations can be done. False on
|
/** doq stream data length has completed, allocations can be done. False on
|
||||||
* allocation failure. */
|
* allocation failure. */
|
||||||
static int
|
static int
|
||||||
doq_stream_datalen_complete(struct doq_stream* stream, struct doq_table* table)
|
doq_stream_datalen_complete(struct doq_conn* conn, struct doq_stream* stream,
|
||||||
|
struct doq_table* table)
|
||||||
{
|
{
|
||||||
if(stream->inlen > 1024*1024) {
|
if(stream->inlen > 1024*1024) {
|
||||||
log_err("doq stream in length too large %d",
|
log_err("doq stream in length too large %d",
|
||||||
(int)stream->inlen);
|
(int)stream->inlen);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(!doq_table_quic_size_available(table, conn->doq_socket->cfg,
|
||||||
|
stream->inlen)) {
|
||||||
|
verbose(VERB_ALGO, "doq stream: no space for query length");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
stream->in = calloc(1, stream->inlen);
|
stream->in = calloc(1, stream->inlen);
|
||||||
if(!stream->in) {
|
if(!stream->in) {
|
||||||
log_err("doq could not read stream, calloc failed: "
|
log_err("doq could not read stream, calloc failed: "
|
||||||
@@ -4069,6 +4125,7 @@ doq_stream_data_complete(struct doq_conn* conn, struct doq_stream* stream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
c->repinfo.doq_streamid = stream->stream_id;
|
c->repinfo.doq_streamid = stream->stream_id;
|
||||||
|
c->repinfo.doq_stream = stream;
|
||||||
conn->doq_socket->current_conn = conn;
|
conn->doq_socket->current_conn = conn;
|
||||||
fptr_ok(fptr_whitelist_comm_point(c->callback));
|
fptr_ok(fptr_whitelist_comm_point(c->callback));
|
||||||
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo)) {
|
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo)) {
|
||||||
@@ -4085,8 +4142,9 @@ doq_stream_data_complete(struct doq_conn* conn, struct doq_stream* stream)
|
|||||||
|
|
||||||
/** doq receive data for a stream, more bytes of the incoming data */
|
/** doq receive data for a stream, more bytes of the incoming data */
|
||||||
static int
|
static int
|
||||||
doq_stream_recv_data(struct doq_stream* stream, const uint8_t* data,
|
doq_stream_recv_data(struct doq_conn* conn, struct doq_stream* stream,
|
||||||
size_t datalen, int* recv_done, struct doq_table* table)
|
const uint8_t* data, size_t datalen, int* recv_done,
|
||||||
|
struct doq_table* table)
|
||||||
{
|
{
|
||||||
int got_data = 0;
|
int got_data = 0;
|
||||||
/* read the tcplength uint16_t at the start */
|
/* read the tcplength uint16_t at the start */
|
||||||
@@ -4107,7 +4165,7 @@ doq_stream_recv_data(struct doq_stream* stream, const uint8_t* data,
|
|||||||
if(stream->nread == 2) {
|
if(stream->nread == 2) {
|
||||||
/* the initial length value is completed */
|
/* the initial length value is completed */
|
||||||
stream->inlen = ntohs(tcplen);
|
stream->inlen = ntohs(tcplen);
|
||||||
if(!doq_stream_datalen_complete(stream, table))
|
if(!doq_stream_datalen_complete(conn, stream, table))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
/* store for later */
|
/* store for later */
|
||||||
@@ -4256,12 +4314,11 @@ doq_submit_new_token(struct doq_conn* conn)
|
|||||||
ngtcp2_ssize tokenlen;
|
ngtcp2_ssize tokenlen;
|
||||||
int ret;
|
int ret;
|
||||||
const ngtcp2_path* path = ngtcp2_conn_get_path(conn->conn);
|
const ngtcp2_path* path = ngtcp2_conn_get_path(conn->conn);
|
||||||
ngtcp2_tstamp ts = doq_get_timestamp_nanosec();
|
|
||||||
|
|
||||||
tokenlen = ngtcp2_crypto_generate_regular_token(token,
|
tokenlen = ngtcp2_crypto_generate_regular_token(token,
|
||||||
conn->doq_socket->static_secret,
|
conn->doq_socket->static_secret,
|
||||||
conn->doq_socket->static_secret_len, path->remote.addr,
|
conn->doq_socket->static_secret_len, path->remote.addr,
|
||||||
path->remote.addrlen, ts);
|
path->remote.addrlen, doq_get_timestamp_nanosec());
|
||||||
if(tokenlen < 0) {
|
if(tokenlen < 0) {
|
||||||
log_err("doq ngtcp2_crypto_generate_regular_token failed");
|
log_err("doq ngtcp2_crypto_generate_regular_token failed");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -4324,8 +4381,7 @@ doq_stream_open_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
|
|||||||
verbose(VERB_ALGO, "doq: stream with this id already exists");
|
verbose(VERB_ALGO, "doq: stream with this id already exists");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(stream_id != 0 && stream_id != 4 && /* allow one stream on a new connection */
|
if(!doq_table_quic_size_available(doq_conn->doq_socket->table,
|
||||||
!doq_table_quic_size_available(doq_conn->doq_socket->table,
|
|
||||||
doq_conn->doq_socket->cfg, sizeof(*stream)
|
doq_conn->doq_socket->cfg, sizeof(*stream)
|
||||||
+ 100 /* estimated query in */
|
+ 100 /* estimated query in */
|
||||||
+ 512 /* estimated response out */
|
+ 512 /* estimated response out */
|
||||||
@@ -4383,8 +4439,8 @@ doq_recv_stream_data_cb(ngtcp2_conn* ATTR_UNUSED(conn), uint32_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(datalen != 0) {
|
if(datalen != 0) {
|
||||||
if(!doq_stream_recv_data(stream, data, datalen, &recv_done,
|
if(!doq_stream_recv_data(doq_conn, stream, data, datalen,
|
||||||
doq_conn->doq_socket->table))
|
&recv_done, doq_conn->doq_socket->table))
|
||||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
if((flags&NGTCP2_STREAM_DATA_FLAG_FIN)!=0) {
|
if((flags&NGTCP2_STREAM_DATA_FLAG_FIN)!=0) {
|
||||||
@@ -4453,6 +4509,29 @@ doq_stream_reset_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** ngtcp2 extend_max_stream_data function */
|
||||||
|
int doq_extend_max_stream_data_cb(ngtcp2_conn* ATTR_UNUSED(conn),
|
||||||
|
int64_t stream_id, uint64_t max_data, void* user_data,
|
||||||
|
void* ATTR_UNUSED(stream_user_data))
|
||||||
|
{
|
||||||
|
struct doq_conn* doq_conn = (struct doq_conn*)user_data;
|
||||||
|
struct doq_stream* stream;
|
||||||
|
verbose(VERB_ALGO, "doq extend_max_stream_data stream id %d "
|
||||||
|
"max_data %d ", (int)stream_id, (int)max_data);
|
||||||
|
if(max_data == 0)
|
||||||
|
return 0;
|
||||||
|
stream = doq_stream_find(doq_conn, stream_id);
|
||||||
|
if(!stream) {
|
||||||
|
verbose(VERB_ALGO, "doq: unknown stream %d", (int)stream_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!stream->is_answer_available)
|
||||||
|
return 0;
|
||||||
|
doq_stream_on_write_list(doq_conn, stream);
|
||||||
|
doq_conn_write_enable(doq_conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** ngtcp2 acked_stream_data_offset callback function */
|
/** ngtcp2 acked_stream_data_offset callback function */
|
||||||
static int
|
static int
|
||||||
doq_acked_stream_data_offset_cb(ngtcp2_conn* ATTR_UNUSED(conn),
|
doq_acked_stream_data_offset_cb(ngtcp2_conn* ATTR_UNUSED(conn),
|
||||||
@@ -4827,6 +4906,7 @@ doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
|
|||||||
callbacks.stream_open = doq_stream_open_cb;
|
callbacks.stream_open = doq_stream_open_cb;
|
||||||
callbacks.stream_close = doq_stream_close_cb;
|
callbacks.stream_close = doq_stream_close_cb;
|
||||||
callbacks.stream_reset = doq_stream_reset_cb;
|
callbacks.stream_reset = doq_stream_reset_cb;
|
||||||
|
callbacks.extend_max_stream_data = doq_extend_max_stream_data_cb;
|
||||||
callbacks.acked_stream_data_offset = doq_acked_stream_data_offset_cb;
|
callbacks.acked_stream_data_offset = doq_acked_stream_data_offset_cb;
|
||||||
callbacks.recv_stream_data = doq_recv_stream_data_cb;
|
callbacks.recv_stream_data = doq_recv_stream_data_cb;
|
||||||
|
|
||||||
@@ -5104,23 +5184,30 @@ doq_conn_clear_conids(struct doq_conn* conn)
|
|||||||
|
|
||||||
ngtcp2_tstamp doq_get_timestamp_nanosec(void)
|
ngtcp2_tstamp doq_get_timestamp_nanosec(void)
|
||||||
{
|
{
|
||||||
#ifdef CLOCK_REALTIME
|
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
memset(&tp, 0, sizeof(tp));
|
memset(&tp, 0, sizeof(tp));
|
||||||
/* Get a nanosecond time, that can be compared with the event base. */
|
#ifdef CLOCK_BOOTTIME
|
||||||
if(clock_gettime(CLOCK_REALTIME, &tp) == -1) {
|
if(clock_gettime(CLOCK_BOOTTIME, &tp) == -1) {
|
||||||
log_err("clock_gettime failed: %s", strerror(errno));
|
#endif
|
||||||
|
if(clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||||
|
log_err("clock_gettime failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
#ifdef CLOCK_BOOTTIME
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return ((uint64_t)tp.tv_sec)*((uint64_t)1000000000) +
|
return ((uint64_t)tp.tv_sec)*((uint64_t)1000000000) +
|
||||||
((uint64_t)tp.tv_nsec);
|
((uint64_t)tp.tv_nsec);
|
||||||
#else
|
}
|
||||||
|
|
||||||
|
static struct timeval doq_get_timevalue(void)
|
||||||
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
memset(&tv, 0, sizeof(tv));
|
||||||
if(gettimeofday(&tv, NULL) < 0) {
|
if(gettimeofday(&tv, NULL) < 0) {
|
||||||
log_err("gettimeofday failed: %s", strerror(errno));
|
log_err("gettimeofday failed: %s", strerror(errno));
|
||||||
|
memset(&tv, 0, sizeof(tv));
|
||||||
}
|
}
|
||||||
return ((uint64_t)tv.tv_sec)*((uint64_t)1000000000) +
|
return tv;
|
||||||
((uint64_t)tv.tv_usec)*((uint64_t)1000);
|
|
||||||
#endif /* CLOCK_REALTIME */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** doq start the closing period for the connection. */
|
/** doq start the closing period for the connection. */
|
||||||
@@ -5243,18 +5330,17 @@ doq_conn_recv(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
int* err_drop)
|
int* err_drop)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
ngtcp2_tstamp ts;
|
|
||||||
struct ngtcp2_path path;
|
struct ngtcp2_path path;
|
||||||
memset(&path, 0, sizeof(path));
|
memset(&path, 0, sizeof(path));
|
||||||
path.remote.addr = (struct sockaddr*)&paddr->addr;
|
path.remote.addr = (struct sockaddr*)&paddr->addr;
|
||||||
path.remote.addrlen = paddr->addrlen;
|
path.remote.addrlen = paddr->addrlen;
|
||||||
path.local.addr = (struct sockaddr*)&paddr->localaddr;
|
path.local.addr = (struct sockaddr*)&paddr->localaddr;
|
||||||
path.local.addrlen = paddr->localaddrlen;
|
path.local.addrlen = paddr->localaddrlen;
|
||||||
ts = doq_get_timestamp_nanosec();
|
|
||||||
|
|
||||||
ret = ngtcp2_conn_read_pkt(conn->conn, &path, pi,
|
ret = ngtcp2_conn_read_pkt(conn->conn, &path, pi,
|
||||||
sldns_buffer_begin(c->doq_socket->pkt_buf),
|
sldns_buffer_begin(c->doq_socket->pkt_buf),
|
||||||
sldns_buffer_limit(c->doq_socket->pkt_buf), ts);
|
sldns_buffer_limit(c->doq_socket->pkt_buf),
|
||||||
|
doq_get_timestamp_nanosec());
|
||||||
if(ret != 0) {
|
if(ret != 0) {
|
||||||
if(err_retry)
|
if(err_retry)
|
||||||
*err_retry = 0;
|
*err_retry = 0;
|
||||||
@@ -5342,7 +5428,6 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
|||||||
{
|
{
|
||||||
struct doq_stream* stream = conn->stream_write_first;
|
struct doq_stream* stream = conn->stream_write_first;
|
||||||
ngtcp2_path_storage ps;
|
ngtcp2_path_storage ps;
|
||||||
ngtcp2_tstamp ts = doq_get_timestamp_nanosec();
|
|
||||||
size_t num_packets = 0, max_packets = 65535;
|
size_t num_packets = 0, max_packets = 65535;
|
||||||
ngtcp2_path_storage_zero(&ps);
|
ngtcp2_path_storage_zero(&ps);
|
||||||
|
|
||||||
@@ -5395,7 +5480,8 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
|||||||
ret = ngtcp2_conn_writev_stream(conn->conn, &ps.path, &pi,
|
ret = ngtcp2_conn_writev_stream(conn->conn, &ps.path, &pi,
|
||||||
sldns_buffer_begin(c->doq_socket->pkt_buf),
|
sldns_buffer_begin(c->doq_socket->pkt_buf),
|
||||||
sldns_buffer_remaining(c->doq_socket->pkt_buf),
|
sldns_buffer_remaining(c->doq_socket->pkt_buf),
|
||||||
&ndatalen, flags, stream_id, datav, datav_count, ts);
|
&ndatalen, flags, stream_id, datav, datav_count,
|
||||||
|
doq_get_timestamp_nanosec());
|
||||||
if(ret < 0) {
|
if(ret < 0) {
|
||||||
if(ret == NGTCP2_ERR_WRITE_MORE) {
|
if(ret == NGTCP2_ERR_WRITE_MORE) {
|
||||||
verbose(VERB_ALGO, "doq: write more, ndatalen %d", (int)ndatalen);
|
verbose(VERB_ALGO, "doq: write more, ndatalen %d", (int)ndatalen);
|
||||||
@@ -5410,26 +5496,20 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
|||||||
continue;
|
continue;
|
||||||
} else if(ret == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
|
} else if(ret == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
|
||||||
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_DATA_BLOCKED");
|
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_DATA_BLOCKED");
|
||||||
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
if(stream) {
|
||||||
ngtcp2_ccerr_set_application_error(
|
doq_stream_off_write_list(conn, stream);
|
||||||
&conn->ccerr, -1, NULL, 0);
|
stream = stream->write_next;
|
||||||
#else
|
continue;
|
||||||
ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
|
} else {
|
||||||
#endif
|
break;
|
||||||
if(err_drop)
|
|
||||||
*err_drop = 0;
|
|
||||||
if(!doq_conn_close_error(c, conn)) {
|
|
||||||
if(err_drop)
|
|
||||||
*err_drop = 1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
} else if(ret == NGTCP2_ERR_STREAM_SHUT_WR) {
|
} else if(ret == NGTCP2_ERR_STREAM_SHUT_WR) {
|
||||||
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_SHUT_WR");
|
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_SHUT_WR");
|
||||||
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
||||||
ngtcp2_ccerr_set_application_error(
|
ngtcp2_ccerr_set_application_error(
|
||||||
&conn->ccerr, -1, NULL, 0);
|
&conn->ccerr, DOQ_APP_ERROR_CODE, NULL, 0);
|
||||||
#else
|
#else
|
||||||
ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
|
ngtcp2_connection_close_error_set_application_error(&conn->last_error, DOQ_APP_ERROR_CODE, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
if(err_drop)
|
if(err_drop)
|
||||||
*err_drop = 0;
|
*err_drop = 0;
|
||||||
@@ -5467,7 +5547,8 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
|||||||
if(ret == 0) {
|
if(ret == 0) {
|
||||||
/* congestion limited */
|
/* congestion limited */
|
||||||
doq_conn_write_disable(conn);
|
doq_conn_write_disable(conn);
|
||||||
ngtcp2_conn_update_pkt_tx_time(conn->conn, ts);
|
ngtcp2_conn_update_pkt_tx_time(conn->conn,
|
||||||
|
doq_get_timestamp_nanosec());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sldns_buffer_set_position(c->doq_socket->pkt_buf, ret);
|
sldns_buffer_set_position(c->doq_socket->pkt_buf, ret);
|
||||||
@@ -5481,7 +5562,7 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
|||||||
if(stream)
|
if(stream)
|
||||||
stream = stream->write_next;
|
stream = stream->write_next;
|
||||||
}
|
}
|
||||||
ngtcp2_conn_update_pkt_tx_time(conn->conn, ts);
|
ngtcp2_conn_update_pkt_tx_time(conn->conn, doq_get_timestamp_nanosec());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5558,32 +5639,35 @@ doq_table_pop_first(struct doq_table* table)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv)
|
doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv, ngtcp2_tstamp* ts)
|
||||||
{
|
{
|
||||||
ngtcp2_tstamp expiry = ngtcp2_conn_get_expiry(conn->conn);
|
ngtcp2_tstamp doq_expiry = ngtcp2_conn_get_expiry(conn->conn);
|
||||||
ngtcp2_tstamp now = doq_get_timestamp_nanosec();
|
ngtcp2_tstamp doq_now = doq_get_timestamp_nanosec();
|
||||||
ngtcp2_tstamp t;
|
ngtcp2_tstamp t;
|
||||||
|
struct timeval now = doq_get_timevalue();
|
||||||
|
|
||||||
if(expiry <= now) {
|
if(doq_expiry <= doq_now || doq_expiry == UINT64_MAX) {
|
||||||
|
/* UINT64_MAX means there is no next expiry. */
|
||||||
/* The timer has already expired, add with zero timeout.
|
/* The timer has already expired, add with zero timeout.
|
||||||
* This should call the callback straight away. Calling it
|
* This should call the callback straight away. Calling it
|
||||||
* from the event callbacks is cleaner than calling it here,
|
* from the event callbacks is cleaner than calling it here,
|
||||||
* because then it is always called with the same locks and
|
* because then it is always called with the same locks and
|
||||||
* so on. This routine only has the conn.lock. */
|
* so on. This routine only has the conn.lock. */
|
||||||
t = now;
|
t = doq_now;
|
||||||
|
memcpy(tv, &now, sizeof(*tv));
|
||||||
} else {
|
} else {
|
||||||
t = expiry;
|
t = doq_expiry;
|
||||||
|
memset(tv, 0, sizeof(*tv));
|
||||||
|
tv->tv_sec = (doq_expiry - doq_now) / NGTCP2_SECONDS;
|
||||||
|
tv->tv_usec = ((doq_expiry - doq_now) / NGTCP2_MICROSECONDS)%1000000;
|
||||||
|
timeval_add(tv, &now);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert to timeval */
|
*ts = t;
|
||||||
memset(tv, 0, sizeof(*tv));
|
|
||||||
tv->tv_sec = t / NGTCP2_SECONDS;
|
|
||||||
tv->tv_usec = (t / NGTCP2_MICROSECONDS)%1000000;
|
|
||||||
|
|
||||||
/* If we already have a timer, is it the right value? */
|
/* If we already have a timer, is it the right value? */
|
||||||
if(conn->timer.timer_in_tree || conn->timer.timer_in_list) {
|
if(conn->timer.timer_in_tree || conn->timer.timer_in_list) {
|
||||||
if(conn->timer.time.tv_sec == tv->tv_sec &&
|
if(conn->timer.time_mono == *ts)
|
||||||
conn->timer.time.tv_usec == tv->tv_usec)
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -5604,13 +5688,12 @@ doq_conn_log_line(struct doq_conn* conn, char* s)
|
|||||||
int
|
int
|
||||||
doq_conn_handle_timeout(struct doq_conn* conn)
|
doq_conn_handle_timeout(struct doq_conn* conn)
|
||||||
{
|
{
|
||||||
ngtcp2_tstamp now = doq_get_timestamp_nanosec();
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if(verbosity >= VERB_ALGO)
|
if(verbosity >= VERB_ALGO)
|
||||||
doq_conn_log_line(conn, "timeout");
|
doq_conn_log_line(conn, "timeout");
|
||||||
|
|
||||||
rv = ngtcp2_conn_handle_expiry(conn->conn, now);
|
rv = ngtcp2_conn_handle_expiry(conn->conn, doq_get_timestamp_nanosec());
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
verbose(VERB_ALGO, "ngtcp2_conn_handle_expiry failed: %s",
|
verbose(VERB_ALGO, "ngtcp2_conn_handle_expiry failed: %s",
|
||||||
ngtcp2_strerror(rv));
|
ngtcp2_strerror(rv));
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ struct config_file;
|
|||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct sldns_buffer;
|
struct sldns_buffer;
|
||||||
struct tcl_list;
|
struct tcl_list;
|
||||||
|
struct mesh_area;
|
||||||
|
struct mesh_state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listening for queries structure.
|
* Listening for queries structure.
|
||||||
@@ -538,8 +540,11 @@ void doq_table_delete(struct doq_table* table);
|
|||||||
struct doq_timer {
|
struct doq_timer {
|
||||||
/** The rbnode in the tree sorted by timeout value. Key this struct. */
|
/** The rbnode in the tree sorted by timeout value. Key this struct. */
|
||||||
struct rbnode_type node;
|
struct rbnode_type node;
|
||||||
|
/** The timeout value. Monotonic value used with ngtcp2.
|
||||||
|
* This time value is used for the tree operations. */
|
||||||
|
ngtcp2_tstamp time_mono;
|
||||||
/** The timeout value. Absolute time value. */
|
/** The timeout value. Absolute time value. */
|
||||||
struct timeval time;
|
struct timeval time_real;
|
||||||
/** If the timer is in the time tree, with the node. */
|
/** If the timer is in the time tree, with the node. */
|
||||||
int timer_in_tree;
|
int timer_in_tree;
|
||||||
/** If there are more timers with the exact same timeout value,
|
/** If there are more timers with the exact same timeout value,
|
||||||
@@ -689,6 +694,11 @@ struct doq_stream {
|
|||||||
uint8_t* out;
|
uint8_t* out;
|
||||||
/** if the stream is on the write list */
|
/** if the stream is on the write list */
|
||||||
uint8_t on_write_list;
|
uint8_t on_write_list;
|
||||||
|
/** The mesh area and mesh state, set when this stream's query was
|
||||||
|
* dispatched into the mesh; used to detach the reply on stream close */
|
||||||
|
struct mesh_area* mesh;
|
||||||
|
/** the mesh state for the query, is nonNULL when there is one. */
|
||||||
|
struct mesh_state* mesh_state;
|
||||||
/** the prev and next on the write list, if on the list */
|
/** the prev and next on the write list, if on the list */
|
||||||
struct doq_stream* write_prev, *write_next;
|
struct doq_stream* write_prev, *write_next;
|
||||||
};
|
};
|
||||||
@@ -791,7 +801,16 @@ int doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
|
|||||||
/** send reply for a connection */
|
/** send reply for a connection */
|
||||||
int doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
|
int doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
|
||||||
struct sldns_buffer* buf);
|
struct sldns_buffer* buf);
|
||||||
|
#endif /* HAVE_NGTCP2 */
|
||||||
|
|
||||||
|
/** add mesh state to doq stream */
|
||||||
|
void doq_stream_add_meshstate(struct doq_stream* stream,
|
||||||
|
struct mesh_area* mesh, struct mesh_state* m);
|
||||||
|
|
||||||
|
/** remove mesh state from doq stream */
|
||||||
|
void doq_stream_remove_mesh_state(struct doq_stream* stream);
|
||||||
|
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
/** the connection has write interest, wants to write packets */
|
/** the connection has write interest, wants to write packets */
|
||||||
void doq_conn_write_enable(struct doq_conn* conn);
|
void doq_conn_write_enable(struct doq_conn* conn);
|
||||||
|
|
||||||
@@ -813,10 +832,12 @@ struct doq_conn* doq_table_pop_first(struct doq_table* table);
|
|||||||
* doq check if the timer for the conn needs to be changed.
|
* doq check if the timer for the conn needs to be changed.
|
||||||
* @param conn: connection, caller must hold lock on it.
|
* @param conn: connection, caller must hold lock on it.
|
||||||
* @param tv: time value, absolute time, returned.
|
* @param tv: time value, absolute time, returned.
|
||||||
|
* @param ts: time stamp, absolute time, returned.
|
||||||
* @return true if timer needs to be set to tv, false if no change is needed
|
* @return true if timer needs to be set to tv, false if no change is needed
|
||||||
* to the timer. The timer is already set to the right time in that case.
|
* to the timer. The timer is already set to the right time in that case.
|
||||||
*/
|
*/
|
||||||
int doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv);
|
int doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv,
|
||||||
|
ngtcp2_tstamp* ts);
|
||||||
|
|
||||||
/** doq remove timer from tree */
|
/** doq remove timer from tree */
|
||||||
void doq_timer_tree_remove(struct doq_table* table, struct doq_timer* timer);
|
void doq_timer_tree_remove(struct doq_table* table, struct doq_timer* timer);
|
||||||
@@ -829,11 +850,12 @@ void doq_timer_unset(struct doq_table* table, struct doq_timer* timer);
|
|||||||
|
|
||||||
/** doq set the timer and add it. */
|
/** doq set the timer and add it. */
|
||||||
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
||||||
struct doq_server_socket* worker_doq_socket, struct timeval* tv);
|
struct doq_server_socket* worker_doq_socket, struct timeval* tv,
|
||||||
|
ngtcp2_tstamp ts);
|
||||||
|
|
||||||
/** doq find a timeout in the timer tree */
|
/** doq find a timeout in the timer tree */
|
||||||
struct doq_timer* doq_timer_find_time(struct doq_table* table,
|
struct doq_timer* doq_timer_find_time(struct doq_table* table,
|
||||||
struct timeval* tv);
|
ngtcp2_tstamp ts);
|
||||||
|
|
||||||
/** doq handle timeout for a connection. Pass conn locked. Returns false for
|
/** doq handle timeout for a connection. Pass conn locked. Returns false for
|
||||||
* deletion. */
|
* deletion. */
|
||||||
@@ -851,6 +873,9 @@ int doq_table_quic_size_available(struct doq_table* table,
|
|||||||
|
|
||||||
/** doq get the quic size value */
|
/** doq get the quic size value */
|
||||||
size_t doq_table_quic_size_get(struct doq_table* table);
|
size_t doq_table_quic_size_get(struct doq_table* table);
|
||||||
|
|
||||||
|
/** get a timestamp in nanoseconds */
|
||||||
|
ngtcp2_tstamp doq_get_timestamp_nanosec(void);
|
||||||
#endif /* HAVE_NGTCP2 */
|
#endif /* HAVE_NGTCP2 */
|
||||||
|
|
||||||
char* set_ip_dscp(int socket, int addrfamily, int ds);
|
char* set_ip_dscp(int socket, int addrfamily, int ds);
|
||||||
@@ -866,8 +891,4 @@ void doq_client_event_cb(int fd, short event, void* arg);
|
|||||||
/** timer event callback for testcode/doqclient */
|
/** timer event callback for testcode/doqclient */
|
||||||
void doq_client_timer_cb(int fd, short event, void* arg);
|
void doq_client_timer_cb(int fd, short event, void* arg);
|
||||||
|
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
/** get a timestamp in nanoseconds */
|
|
||||||
ngtcp2_tstamp doq_get_timestamp_nanosec(void);
|
|
||||||
#endif
|
|
||||||
#endif /* LISTEN_DNSPORT_H */
|
#endif /* LISTEN_DNSPORT_H */
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ enum respip_action {
|
|||||||
respip_always_nxdomain = local_zone_always_nxdomain,
|
respip_always_nxdomain = local_zone_always_nxdomain,
|
||||||
/** answer with nodata response */
|
/** answer with nodata response */
|
||||||
respip_always_nodata = local_zone_always_nodata,
|
respip_always_nodata = local_zone_always_nodata,
|
||||||
/** answer with nodata response */
|
/** drop query */
|
||||||
respip_always_deny = local_zone_always_deny,
|
respip_always_deny = local_zone_always_deny,
|
||||||
/** RPZ: truncate answer in order to force switch to tcp */
|
/** RPZ: truncate answer in order to force switch to tcp */
|
||||||
respip_truncate = local_zone_truncate,
|
respip_truncate = local_zone_truncate,
|
||||||
|
|||||||
+54
-14
@@ -506,6 +506,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||||||
"incoming query.");
|
"incoming query.");
|
||||||
if(rep->c->use_h2)
|
if(rep->c->use_h2)
|
||||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||||
|
else if(rep->c->type == comm_doq && rep->doq_stream)
|
||||||
|
doq_stream_remove_mesh_state(rep->doq_stream);
|
||||||
comm_point_drop_reply(rep);
|
comm_point_drop_reply(rep);
|
||||||
mesh->stats_dropped++;
|
mesh->stats_dropped++;
|
||||||
return;
|
return;
|
||||||
@@ -519,6 +521,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||||||
"dropping incoming query.");
|
"dropping incoming query.");
|
||||||
if(rep->c->use_h2)
|
if(rep->c->use_h2)
|
||||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||||
|
else if(rep->c->type == comm_doq && rep->doq_stream)
|
||||||
|
doq_stream_remove_mesh_state(rep->doq_stream);
|
||||||
comm_point_drop_reply(rep);
|
comm_point_drop_reply(rep);
|
||||||
mesh->num_queries_replyaddr_limit++;
|
mesh->num_queries_replyaddr_limit++;
|
||||||
return;
|
return;
|
||||||
@@ -593,6 +597,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||||||
added_tcp = 1;
|
added_tcp = 1;
|
||||||
if(rep->c->use_h2) {
|
if(rep->c->use_h2) {
|
||||||
http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
|
http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
|
||||||
|
} else if(rep->c->type == comm_doq && rep->doq_stream) {
|
||||||
|
doq_stream_add_meshstate(rep->doq_stream, mesh, s);
|
||||||
}
|
}
|
||||||
/* add serve expired timer if required and not already there */
|
/* add serve expired timer if required and not already there */
|
||||||
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
||||||
@@ -648,6 +654,8 @@ servfail_mem:
|
|||||||
qinfo, qid, qflags, edns);
|
qinfo, qid, qflags, edns);
|
||||||
if(rep->c->use_h2)
|
if(rep->c->use_h2)
|
||||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||||
|
else if(rep->c->type == comm_doq && rep->doq_stream)
|
||||||
|
doq_stream_remove_mesh_state(rep->doq_stream);
|
||||||
comm_point_send_reply(rep);
|
comm_point_send_reply(rep);
|
||||||
if(added_reply_without_accounting) {
|
if(added_reply_without_accounting) {
|
||||||
mesh_remove_reply_without_accounting(s, repadded);
|
mesh_remove_reply_without_accounting(s, repadded);
|
||||||
@@ -979,8 +987,7 @@ cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Copy the client info to the query region. */
|
struct respip_client_info*
|
||||||
static struct respip_client_info*
|
|
||||||
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@@ -1025,6 +1032,11 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
|||||||
cinfo->view->name);
|
cinfo->view->name);
|
||||||
if(!client_info->view_name)
|
if(!client_info->view_name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
} else if(cinfo->view_name) {
|
||||||
|
client_info->view_name = regional_strdup(region,
|
||||||
|
cinfo->view_name);
|
||||||
|
if(!client_info->view_name)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
return client_info;
|
return client_info;
|
||||||
}
|
}
|
||||||
@@ -1533,6 +1545,10 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
|||||||
* for HTTP/2 stream to refer to mesh state, in case
|
* for HTTP/2 stream to refer to mesh state, in case
|
||||||
* connection gets cleanup before HTTP/2 stream close. */
|
* connection gets cleanup before HTTP/2 stream close. */
|
||||||
r->h2_stream->mesh_state = NULL;
|
r->h2_stream->mesh_state = NULL;
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
|
} else if(r->query_reply.doq_stream) {
|
||||||
|
r->query_reply.doq_stream->mesh_state = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
/* send the reply */
|
/* send the reply */
|
||||||
/* We don't reuse the encoded answer if:
|
/* We don't reuse the encoded answer if:
|
||||||
@@ -1687,9 +1703,9 @@ static void dns_error_reporting(struct module_qstate* qstate,
|
|||||||
opt = edns_opt_list_find(qstate->edns_opts_back_in,
|
opt = edns_opt_list_find(qstate->edns_opts_back_in,
|
||||||
LDNS_EDNS_REPORT_CHANNEL);
|
LDNS_EDNS_REPORT_CHANNEL);
|
||||||
if(!opt) return;
|
if(!opt) return;
|
||||||
agent_domain_len = opt->opt_len;
|
|
||||||
agent_domain = opt->opt_data;
|
agent_domain = opt->opt_data;
|
||||||
if(dname_valid(agent_domain, agent_domain_len) < 3) {
|
agent_domain_len = dname_valid(agent_domain, opt->opt_len);
|
||||||
|
if(agent_domain_len < 3) {
|
||||||
/* The agent domain needs to be a valid dname that is not the
|
/* The agent domain needs to be a valid dname that is not the
|
||||||
* root; from RFC9567. */
|
* root; from RFC9567. */
|
||||||
return;
|
return;
|
||||||
@@ -1827,6 +1843,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
|||||||
mstate->reply_list = NULL;
|
mstate->reply_list = NULL;
|
||||||
if(r->query_reply.c->use_h2)
|
if(r->query_reply.c->use_h2)
|
||||||
http2_stream_remove_mesh_state(r->h2_stream);
|
http2_stream_remove_mesh_state(r->h2_stream);
|
||||||
|
else if(r->query_reply.doq_stream)
|
||||||
|
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||||
comm_point_drop_reply(&r->query_reply);
|
comm_point_drop_reply(&r->query_reply);
|
||||||
mstate->reply_list = reply_list;
|
mstate->reply_list = reply_list;
|
||||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||||
@@ -1864,6 +1882,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
|||||||
mstate->reply_list = NULL;
|
mstate->reply_list = NULL;
|
||||||
if(r->query_reply.c->use_h2) {
|
if(r->query_reply.c->use_h2) {
|
||||||
http2_stream_remove_mesh_state(r->h2_stream);
|
http2_stream_remove_mesh_state(r->h2_stream);
|
||||||
|
} else if(r->query_reply.doq_stream) {
|
||||||
|
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||||
}
|
}
|
||||||
comm_point_drop_reply(&r->query_reply);
|
comm_point_drop_reply(&r->query_reply);
|
||||||
mstate->reply_list = reply_list;
|
mstate->reply_list = reply_list;
|
||||||
@@ -2079,6 +2099,8 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
|||||||
if(rep->c->use_h2)
|
if(rep->c->use_h2)
|
||||||
r->h2_stream = rep->c->h2_stream;
|
r->h2_stream = rep->c->h2_stream;
|
||||||
else r->h2_stream = NULL;
|
else r->h2_stream = NULL;
|
||||||
|
if(rep->c->type != comm_doq)
|
||||||
|
r->query_reply.doq_stream = NULL;
|
||||||
|
|
||||||
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
|
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
|
||||||
* and can be different for different original queries (even if the
|
* and can be different for different original queries (even if the
|
||||||
@@ -2437,7 +2459,8 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||||
struct comm_point* cp, struct http2_stream* h2_stream)
|
struct comm_point* cp, struct http2_stream* h2_stream,
|
||||||
|
struct doq_stream* doq_stream)
|
||||||
{
|
{
|
||||||
struct mesh_reply* n, *prev = NULL;
|
struct mesh_reply* n, *prev = NULL;
|
||||||
n = m->reply_list;
|
n = m->reply_list;
|
||||||
@@ -2446,7 +2469,9 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
|||||||
if(!n) return; /* nothing to remove, also no accounting needed */
|
if(!n) return; /* nothing to remove, also no accounting needed */
|
||||||
while(n) {
|
while(n) {
|
||||||
if(n->query_reply.c == cp
|
if(n->query_reply.c == cp
|
||||||
&& (!h2_stream || n->h2_stream == h2_stream)) {
|
&& (!h2_stream || n->h2_stream == h2_stream)
|
||||||
|
&& (!doq_stream || n->query_reply.doq_stream == doq_stre
|
||||||
|
am)) {
|
||||||
/* unlink it */
|
/* unlink it */
|
||||||
if(prev) prev->next = n->next;
|
if(prev) prev->next = n->next;
|
||||||
else m->reply_list = n->next;
|
else m->reply_list = n->next;
|
||||||
@@ -2459,6 +2484,10 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
|||||||
* share the same comm_point); make sure the streams
|
* share the same comm_point); make sure the streams
|
||||||
* don't point back. */
|
* don't point back. */
|
||||||
if(n->h2_stream) n->h2_stream->mesh_state = NULL;
|
if(n->h2_stream) n->h2_stream->mesh_state = NULL;
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
|
if(n->query_reply.doq_stream)
|
||||||
|
n->query_reply.doq_stream->mesh_state = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* prev = prev; */
|
/* prev = prev; */
|
||||||
n = n->next;
|
n = n->next;
|
||||||
@@ -2499,9 +2528,10 @@ apply_respip_action(struct module_qstate* qstate,
|
|||||||
|
|
||||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||||
* was redirected to response-ip data. */
|
* was redirected to response-ip data. */
|
||||||
if((actinfo->action == respip_deny ||
|
if(actinfo->action == respip_always_deny ||
|
||||||
|
((actinfo->action == respip_deny ||
|
||||||
actinfo->action == respip_inform_deny) &&
|
actinfo->action == respip_inform_deny) &&
|
||||||
*encode_repp == rep)
|
*encode_repp == rep))
|
||||||
*encode_repp = NULL;
|
*encode_repp = NULL;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -2566,12 +2596,15 @@ mesh_serve_expired_callback(void* arg)
|
|||||||
qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep,
|
qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep,
|
||||||
qstate->env->auth_zones)) {
|
qstate->env->auth_zones)) {
|
||||||
return;
|
return;
|
||||||
} else if(partial_rep &&
|
} else if(partial_rep) {
|
||||||
!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
|
if(!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
|
||||||
qstate->client_info, must_validate, &encode_rep, qstate->region,
|
qstate->client_info, must_validate, &encode_rep, qstate->region,
|
||||||
qstate->env->auth_zones, qstate->env->views,
|
qstate->env->auth_zones, qstate->env->views,
|
||||||
qstate->env->respip_set)) {
|
qstate->env->respip_set)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
/* merge succeeded; final reply, no further alias pass */
|
||||||
|
partial_rep = NULL;
|
||||||
}
|
}
|
||||||
if(!encode_rep || alias_rrset) {
|
if(!encode_rep || alias_rrset) {
|
||||||
if(!encode_rep) {
|
if(!encode_rep) {
|
||||||
@@ -2582,6 +2615,7 @@ mesh_serve_expired_callback(void* arg)
|
|||||||
partial_rep = encode_rep;
|
partial_rep = encode_rep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
msg->rep = encode_rep;
|
||||||
/* We've found a partial reply ending with an
|
/* We've found a partial reply ending with an
|
||||||
* alias. Replace the lookup qinfo for the
|
* alias. Replace the lookup qinfo for the
|
||||||
* alias target and lookup the cache again to
|
* alias target and lookup the cache again to
|
||||||
@@ -2608,9 +2642,10 @@ mesh_serve_expired_callback(void* arg)
|
|||||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||||
|
|
||||||
for(r = mstate->reply_list; r; r = r->next) {
|
for(r = mstate->reply_list; r; r = r->next) {
|
||||||
struct timeval old;
|
if(mesh_is_udp(r)) {
|
||||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
struct timeval old;
|
||||||
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||||
|
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
||||||
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
||||||
mstate->s.env->cfg->discard_timeout) {
|
mstate->s.env->cfg->discard_timeout) {
|
||||||
/* Drop the reply, it is too old */
|
/* Drop the reply, it is too old */
|
||||||
@@ -2626,10 +2661,15 @@ mesh_serve_expired_callback(void* arg)
|
|||||||
mstate->reply_list = NULL;
|
mstate->reply_list = NULL;
|
||||||
if(r->query_reply.c->use_h2)
|
if(r->query_reply.c->use_h2)
|
||||||
http2_stream_remove_mesh_state(r->h2_stream);
|
http2_stream_remove_mesh_state(r->h2_stream);
|
||||||
|
else if(r->query_reply.doq_stream)
|
||||||
|
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||||
comm_point_drop_reply(&r->query_reply);
|
comm_point_drop_reply(&r->query_reply);
|
||||||
mstate->reply_list = reply_list;
|
mstate->reply_list = reply_list;
|
||||||
|
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||||
|
mstate->s.env->mesh->num_reply_addrs--;
|
||||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|||||||
+8
-1
@@ -707,9 +707,12 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
|||||||
* @param cp: the comm_point to remove from the list.
|
* @param cp: the comm_point to remove from the list.
|
||||||
* @param h2_stream: if not NULL, it specifies the h2_stream to match
|
* @param h2_stream: if not NULL, it specifies the h2_stream to match
|
||||||
* for the delete.
|
* for the delete.
|
||||||
|
* @param doq_stream: if not NULL, it specifies the doq_stream to match
|
||||||
|
* for the delete.
|
||||||
*/
|
*/
|
||||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||||
struct comm_point* cp, struct http2_stream* h2_stream);
|
struct comm_point* cp, struct http2_stream* h2_stream,
|
||||||
|
struct doq_stream* doq_stream);
|
||||||
|
|
||||||
/** Callback for when the serve expired client timer has run out. Tries to
|
/** Callback for when the serve expired client timer has run out. Tries to
|
||||||
* find an expired answer in the cache and reply that to the client.
|
* find an expired answer in the cache and reply that to the client.
|
||||||
@@ -761,4 +764,8 @@ void mesh_respond_serve_expired(struct mesh_state* mstate);
|
|||||||
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info);
|
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info);
|
||||||
|
|
||||||
|
/** Copy the client info to the query region. */
|
||||||
|
struct respip_client_info* mesh_copy_client_info(struct regional* region,
|
||||||
|
struct respip_client_info* cinfo);
|
||||||
|
|
||||||
#endif /* SERVICES_MESH_H */
|
#endif /* SERVICES_MESH_H */
|
||||||
|
|||||||
+321
-67
@@ -208,6 +208,7 @@ static void
|
|||||||
waiting_tcp_delete(struct waiting_tcp* w)
|
waiting_tcp_delete(struct waiting_tcp* w)
|
||||||
{
|
{
|
||||||
if(!w) return;
|
if(!w) return;
|
||||||
|
free(w->tls_auth_name);
|
||||||
if(w->timer)
|
if(w->timer)
|
||||||
comm_timer_delete(w->timer);
|
comm_timer_delete(w->timer);
|
||||||
free(w);
|
free(w);
|
||||||
@@ -1480,7 +1481,7 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc)
|
|||||||
pif = pc->pif;
|
pif = pc->pif;
|
||||||
log_assert(pif->inuse > 0);
|
log_assert(pif->inuse > 0);
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
|
shared_ports_return_port(outnet->shared_ports, pif->shpif, pc->number);
|
||||||
#endif
|
#endif
|
||||||
pif->inuse--;
|
pif->inuse--;
|
||||||
pif->out[pc->index] = pif->out[pif->inuse];
|
pif->out[pc->index] = pif->out[pif->inuse];
|
||||||
@@ -1694,15 +1695,9 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** setup an outgoing interface, ready address */
|
/** setup an outgoing interface, ready address */
|
||||||
static int setup_if(struct port_if* pif, const char* addrstr,
|
static int setup_if(struct port_if* pif, const char* addrstr, size_t numfd,
|
||||||
int* avail, int numavail, size_t numfd)
|
struct shared_ports* shp)
|
||||||
{
|
{
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
|
||||||
pif->avail_total = numavail;
|
|
||||||
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
|
|
||||||
if(!pif->avail_ports)
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
|
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
|
||||||
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
||||||
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
||||||
@@ -1712,6 +1707,12 @@ static int setup_if(struct port_if* pif, const char* addrstr,
|
|||||||
log_err("num_ports exceeds INT_MAX");
|
log_err("num_ports exceeds INT_MAX");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
pif->shpif = shared_ports_find_if(shp, &pif->addr, pif->addrlen,
|
||||||
|
pif->pfxlen);
|
||||||
|
#else
|
||||||
|
(void)shp;
|
||||||
#endif
|
#endif
|
||||||
pif->maxout = (int)numfd;
|
pif->maxout = (int)numfd;
|
||||||
pif->inuse = 0;
|
pif->inuse = 0;
|
||||||
@@ -1726,12 +1727,12 @@ struct outside_network*
|
|||||||
outside_network_create(struct comm_base *base, size_t bufsize,
|
outside_network_create(struct comm_base *base, size_t bufsize,
|
||||||
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
|
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
|
||||||
int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
|
int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
|
||||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
struct ub_randstate* rnd, int use_caps_for_id,
|
||||||
int numavailports, size_t unwanted_threshold, int tcp_mss,
|
size_t unwanted_threshold, int tcp_mss,
|
||||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||||
void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv,
|
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 udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
|
||||||
int tcp_auth_query_timeout)
|
int tcp_auth_query_timeout, struct shared_ports* shared_ports)
|
||||||
{
|
{
|
||||||
struct outside_network* outnet = (struct outside_network*)
|
struct outside_network* outnet = (struct outside_network*)
|
||||||
calloc(1, sizeof(struct outside_network));
|
calloc(1, sizeof(struct outside_network));
|
||||||
@@ -1766,6 +1767,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||||||
outnet->do_udp = do_udp;
|
outnet->do_udp = do_udp;
|
||||||
outnet->tcp_mss = tcp_mss;
|
outnet->tcp_mss = tcp_mss;
|
||||||
outnet->ip_dscp = dscp;
|
outnet->ip_dscp = dscp;
|
||||||
|
outnet->shared_ports = shared_ports;
|
||||||
#ifndef S_SPLINT_S
|
#ifndef S_SPLINT_S
|
||||||
if(delayclose) {
|
if(delayclose) {
|
||||||
outnet->delayclose = 1;
|
outnet->delayclose = 1;
|
||||||
@@ -1776,7 +1778,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||||||
if(udp_connect) {
|
if(udp_connect) {
|
||||||
outnet->udp_connect = 1;
|
outnet->udp_connect = 1;
|
||||||
}
|
}
|
||||||
if(numavailports == 0 || num_ports == 0) {
|
if(num_ports == 0) {
|
||||||
log_err("no outgoing ports available");
|
log_err("no outgoing ports available");
|
||||||
outside_network_delete(outnet);
|
outside_network_delete(outnet);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1844,13 +1846,13 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||||||
/* allocate interfaces */
|
/* allocate interfaces */
|
||||||
if(num_ifs == 0) {
|
if(num_ifs == 0) {
|
||||||
if(do_ip4 && !setup_if(&outnet->ip4_ifs[0], "0.0.0.0",
|
if(do_ip4 && !setup_if(&outnet->ip4_ifs[0], "0.0.0.0",
|
||||||
availports, numavailports, num_ports)) {
|
num_ports, outnet->shared_ports)) {
|
||||||
log_err("malloc failed");
|
log_err("malloc failed");
|
||||||
outside_network_delete(outnet);
|
outside_network_delete(outnet);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(do_ip6 && !setup_if(&outnet->ip6_ifs[0], "::",
|
if(do_ip6 && !setup_if(&outnet->ip6_ifs[0], "::",
|
||||||
availports, numavailports, num_ports)) {
|
num_ports, outnet->shared_ports)) {
|
||||||
log_err("malloc failed");
|
log_err("malloc failed");
|
||||||
outside_network_delete(outnet);
|
outside_network_delete(outnet);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1861,7 +1863,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||||||
for(i=0; i<num_ifs; i++) {
|
for(i=0; i<num_ifs; i++) {
|
||||||
if(str_is_ip6(ifs[i]) && do_ip6) {
|
if(str_is_ip6(ifs[i]) && do_ip6) {
|
||||||
if(!setup_if(&outnet->ip6_ifs[done_6], ifs[i],
|
if(!setup_if(&outnet->ip6_ifs[done_6], ifs[i],
|
||||||
availports, numavailports, num_ports)){
|
num_ports, outnet->shared_ports)){
|
||||||
log_err("malloc failed");
|
log_err("malloc failed");
|
||||||
outside_network_delete(outnet);
|
outside_network_delete(outnet);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1870,7 +1872,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
|||||||
}
|
}
|
||||||
if(!str_is_ip6(ifs[i]) && do_ip4) {
|
if(!str_is_ip6(ifs[i]) && do_ip4) {
|
||||||
if(!setup_if(&outnet->ip4_ifs[done_4], ifs[i],
|
if(!setup_if(&outnet->ip4_ifs[done_4], ifs[i],
|
||||||
availports, numavailports, num_ports)){
|
num_ports, outnet->shared_ports)){
|
||||||
log_err("malloc failed");
|
log_err("malloc failed");
|
||||||
outside_network_delete(outnet);
|
outside_network_delete(outnet);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1948,9 +1950,6 @@ outside_network_delete(struct outside_network* outnet)
|
|||||||
comm_point_delete(pc->cp);
|
comm_point_delete(pc->cp);
|
||||||
free(pc);
|
free(pc);
|
||||||
}
|
}
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
|
||||||
free(outnet->ip4_ifs[i].avail_ports);
|
|
||||||
#endif
|
|
||||||
free(outnet->ip4_ifs[i].out);
|
free(outnet->ip4_ifs[i].out);
|
||||||
}
|
}
|
||||||
free(outnet->ip4_ifs);
|
free(outnet->ip4_ifs);
|
||||||
@@ -1964,9 +1963,6 @@ outside_network_delete(struct outside_network* outnet)
|
|||||||
comm_point_delete(pc->cp);
|
comm_point_delete(pc->cp);
|
||||||
free(pc);
|
free(pc);
|
||||||
}
|
}
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
|
||||||
free(outnet->ip6_ifs[i].avail_ports);
|
|
||||||
#endif
|
|
||||||
free(outnet->ip6_ifs[i].out);
|
free(outnet->ip6_ifs[i].out);
|
||||||
}
|
}
|
||||||
free(outnet->ip6_ifs);
|
free(outnet->ip6_ifs);
|
||||||
@@ -2176,7 +2172,10 @@ static int
|
|||||||
select_ifport(struct outside_network* outnet, struct pending* pend,
|
select_ifport(struct outside_network* outnet, struct pending* pend,
|
||||||
int num_if, struct port_if* ifs)
|
int num_if, struct port_if* ifs)
|
||||||
{
|
{
|
||||||
int my_if, my_port, fd, portno, inuse, tries=0;
|
int my_if, fd, portno, inuse, tries=0;
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
int reused;
|
||||||
|
#endif
|
||||||
struct port_if* pif;
|
struct port_if* pif;
|
||||||
/* randomly select interface and port */
|
/* randomly select interface and port */
|
||||||
if(num_if == 0) {
|
if(num_if == 0) {
|
||||||
@@ -2190,37 +2189,35 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||||||
my_if = ub_random_max(outnet->rnd, num_if);
|
my_if = ub_random_max(outnet->rnd, num_if);
|
||||||
pif = &ifs[my_if];
|
pif = &ifs[my_if];
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
if(outnet->udp_connect) {
|
if(!shared_ports_fetch_random(outnet->shared_ports,
|
||||||
/* if we connect() we cannot reuse fds for a port */
|
pif->shpif, outnet->rnd, outnet->udp_connect,
|
||||||
if(pif->inuse >= pif->avail_total) {
|
pif->inuse, &portno, &reused)) {
|
||||||
tries++;
|
tries++;
|
||||||
if(tries < MAX_PORT_RETRY)
|
if(tries < MAX_PORT_RETRY)
|
||||||
continue;
|
continue;
|
||||||
log_err("failed to find an open port, drop msg");
|
log_err("failed to find an open port, drop msg");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
my_port = pif->inuse + ub_random_max(outnet->rnd,
|
if(reused) {
|
||||||
pif->avail_total - pif->inuse);
|
/* port already open */
|
||||||
} else {
|
log_assert(portno < pif->inuse);
|
||||||
my_port = ub_random_max(outnet->rnd, pif->avail_total);
|
pend->pc = pif->out[portno];
|
||||||
if(my_port < pif->inuse) {
|
verbose(VERB_ALGO, "using UDP if=%d port=%d",
|
||||||
/* port already open */
|
my_if, pend->pc->number);
|
||||||
pend->pc = pif->out[my_port];
|
break;
|
||||||
verbose(VERB_ALGO, "using UDP if=%d port=%d",
|
|
||||||
my_if, pend->pc->number);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* try to open new port, if fails, loop to try again */
|
|
||||||
log_assert(pif->inuse < pif->maxout);
|
|
||||||
portno = pif->avail_ports[my_port - pif->inuse];
|
|
||||||
#else
|
#else
|
||||||
my_port = portno = 0;
|
portno = 0;
|
||||||
#endif
|
#endif
|
||||||
|
/* try to open new port, if fails, loop to try again */
|
||||||
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
|
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
|
||||||
portno, &inuse, outnet->rnd, outnet->ip_dscp);
|
portno, &inuse, outnet->rnd, outnet->ip_dscp);
|
||||||
if(fd == -1 && !inuse) {
|
if(fd == -1 && !inuse) {
|
||||||
/* nonrecoverable error making socket */
|
/* nonrecoverable error making socket */
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
shared_ports_return_port(outnet->shared_ports,
|
||||||
|
pif->shpif, portno);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(fd != -1) {
|
if(fd != -1) {
|
||||||
@@ -2237,6 +2234,11 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||||||
pend->addrlen);
|
pend->addrlen);
|
||||||
}
|
}
|
||||||
sock_close(fd);
|
sock_close(fd);
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
shared_ports_return_port(
|
||||||
|
outnet->shared_ports,
|
||||||
|
pif->shpif, portno);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2254,14 +2256,14 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||||||
|
|
||||||
/* grab port in interface */
|
/* grab port in interface */
|
||||||
pif->out[pif->inuse] = pend->pc;
|
pif->out[pif->inuse] = pend->pc;
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
|
||||||
pif->avail_ports[my_port - pif->inuse] =
|
|
||||||
pif->avail_ports[pif->avail_total-pif->inuse-1];
|
|
||||||
#endif
|
|
||||||
pif->inuse++;
|
pif->inuse++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* failed, already in use */
|
/* failed, already in use */
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
shared_ports_return_port(outnet->shared_ports, pif->shpif,
|
||||||
|
portno);
|
||||||
|
#endif
|
||||||
verbose(VERB_QUERY, "port %d in use, trying another", portno);
|
verbose(VERB_QUERY, "port %d in use, trying another", portno);
|
||||||
tries++;
|
tries++;
|
||||||
if(tries == MAX_PORT_RETRY) {
|
if(tries == MAX_PORT_RETRY) {
|
||||||
@@ -2553,7 +2555,16 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
|||||||
w->cb = callback;
|
w->cb = callback;
|
||||||
w->cb_arg = callback_arg;
|
w->cb_arg = callback_arg;
|
||||||
w->ssl_upstream = sq->ssl_upstream;
|
w->ssl_upstream = sq->ssl_upstream;
|
||||||
w->tls_auth_name = sq->tls_auth_name;
|
if(sq->tls_auth_name) {
|
||||||
|
w->tls_auth_name = strdup(sq->tls_auth_name);
|
||||||
|
if(!w->tls_auth_name) {
|
||||||
|
comm_timer_delete(w->timer);
|
||||||
|
free(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
w->tls_auth_name = NULL;
|
||||||
|
}
|
||||||
w->timeout = timeout;
|
w->timeout = timeout;
|
||||||
w->id_node.key = NULL;
|
w->id_node.key = NULL;
|
||||||
w->write_wait_prev = NULL;
|
w->write_wait_prev = NULL;
|
||||||
@@ -3645,13 +3656,16 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
|||||||
{
|
{
|
||||||
struct sockaddr_storage* addr;
|
struct sockaddr_storage* addr;
|
||||||
socklen_t addrlen;
|
socklen_t addrlen;
|
||||||
int i, try, pnum, dscp;
|
int i, try, dscp;
|
||||||
struct port_if* pif;
|
struct port_if* pif;
|
||||||
|
|
||||||
/* create fd */
|
/* create fd */
|
||||||
dscp = outnet->ip_dscp;
|
dscp = outnet->ip_dscp;
|
||||||
for(try = 0; try<1000; try++) {
|
for(try = 0; try<1000; try++) {
|
||||||
int port = 0;
|
int port = 0;
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
int reused = 0;
|
||||||
|
#endif
|
||||||
int freebind = 0;
|
int freebind = 0;
|
||||||
int noproto = 0;
|
int noproto = 0;
|
||||||
int inuse = 0;
|
int inuse = 0;
|
||||||
@@ -3680,16 +3694,18 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
|||||||
addr = &pif->addr;
|
addr = &pif->addr;
|
||||||
addrlen = pif->addrlen;
|
addrlen = pif->addrlen;
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pnum = ub_random_max(outnet->rnd, pif->avail_total);
|
if(!shared_ports_fetch_random(outnet->shared_ports,
|
||||||
if(pnum < pif->inuse) {
|
pif->shpif, outnet->rnd, 0, pif->inuse,
|
||||||
/* port already open */
|
&port, &reused)) {
|
||||||
port = pif->out[pnum]->number;
|
/* try again, perhaps another interface. */
|
||||||
} else {
|
continue;
|
||||||
/* unused ports in start part of array */
|
}
|
||||||
port = pif->avail_ports[pnum - pif->inuse];
|
if(reused) {
|
||||||
|
log_assert(port < pif->inuse);
|
||||||
|
port = pif->out[port]->number;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
pnum = port = 0;
|
port = 0;
|
||||||
#endif
|
#endif
|
||||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||||
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
||||||
@@ -3704,6 +3720,14 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
|||||||
(struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
|
(struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
|
||||||
0, 0, 0, NULL, 0, freebind, 0, dscp);
|
0, 0, 0, NULL, 0, freebind, 0, dscp);
|
||||||
}
|
}
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
if(!reused) {
|
||||||
|
/* Return the port to the pool, since the caller does
|
||||||
|
* not keep track of it, also have done fd, and bind. */
|
||||||
|
shared_ports_return_port(outnet->shared_ports,
|
||||||
|
pif->shpif, port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(fd != -1) {
|
if(fd != -1) {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
@@ -3961,11 +3985,7 @@ if_get_mem(struct port_if* pif)
|
|||||||
{
|
{
|
||||||
size_t s;
|
size_t s;
|
||||||
int i;
|
int i;
|
||||||
s = sizeof(*pif) +
|
s = sizeof(*pif) + sizeof(struct port_comm*)*pif->maxout;
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
|
||||||
sizeof(int)*pif->avail_total +
|
|
||||||
#endif
|
|
||||||
sizeof(struct port_comm*)*pif->maxout;
|
|
||||||
for(i=0; i<pif->inuse; i++)
|
for(i=0; i<pif->inuse; i++)
|
||||||
s += sizeof(*pif->out[i]) +
|
s += sizeof(*pif->out[i]) +
|
||||||
comm_point_get_mem(pif->out[i]->cp);
|
comm_point_get_mem(pif->out[i]->cp);
|
||||||
@@ -4053,3 +4073,237 @@ serviced_get_mem(struct serviced_query* sq)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
/** Setup shared port interface */
|
||||||
|
static int shared_ports_setup_if(struct shared_ports_if* shpif, char* str,
|
||||||
|
int* availports, int numavailports)
|
||||||
|
{
|
||||||
|
shpif->avail_ports = (int*)memdup(availports,
|
||||||
|
(size_t)numavailports*sizeof(int));
|
||||||
|
if(!shpif->avail_ports)
|
||||||
|
return 0;
|
||||||
|
shpif->avail_total = numavailports;
|
||||||
|
shpif->inuse = 0;
|
||||||
|
shpif->pfxlen = 0;
|
||||||
|
if(!ipstrtoaddr(str, UNBOUND_DNS_PORT, &shpif->addr, &shpif->addrlen) &&
|
||||||
|
!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &shpif->addr,
|
||||||
|
&shpif->addrlen, &shpif->pfxlen))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
/** Allocate shared ports interfaces */
|
||||||
|
static int shared_ports_alloc_ifs(struct shared_ports* shp, char** ifs,
|
||||||
|
int num_ifs, int do_ip4, int do_ip6, int* availports,
|
||||||
|
int numavailports)
|
||||||
|
{
|
||||||
|
#ifndef INET6
|
||||||
|
do_ip6 = 0;
|
||||||
|
#endif
|
||||||
|
calc_num46(ifs, num_ifs, do_ip4, do_ip6,
|
||||||
|
&shp->num_ip4, &shp->num_ip6);
|
||||||
|
if(shp->num_ip4 != 0) {
|
||||||
|
if(!(shp->ip4_ifs = (struct shared_ports_if*)calloc(
|
||||||
|
(size_t)shp->num_ip4,
|
||||||
|
sizeof(struct shared_ports_if))))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(shp->num_ip6 != 0) {
|
||||||
|
if(!(shp->ip6_ifs = (struct shared_ports_if*)calloc(
|
||||||
|
(size_t)shp->num_ip6,
|
||||||
|
sizeof(struct shared_ports_if))))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(num_ifs == 0) {
|
||||||
|
if(do_ip4 && !shared_ports_setup_if(&shp->ip4_ifs[0],
|
||||||
|
"0.0.0.0", availports, numavailports))
|
||||||
|
return 0;
|
||||||
|
if(do_ip6 && !shared_ports_setup_if(&shp->ip6_ifs[0],
|
||||||
|
"::", availports, numavailports))
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
size_t done_4 = 0, done_6 = 0;
|
||||||
|
int i;
|
||||||
|
for(i=0; i<num_ifs; i++) {
|
||||||
|
if(str_is_ip6(ifs[i]) && do_ip6) {
|
||||||
|
if(!shared_ports_setup_if(&shp->ip6_ifs[done_6],
|
||||||
|
ifs[i], availports, numavailports))
|
||||||
|
return 0;
|
||||||
|
done_6++;
|
||||||
|
}
|
||||||
|
if(!str_is_ip6(ifs[i]) && do_ip4) {
|
||||||
|
if(!shared_ports_setup_if(&shp->ip4_ifs[done_4],
|
||||||
|
ifs[i], availports, numavailports))
|
||||||
|
return 0;
|
||||||
|
done_4++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct shared_ports* shared_ports_create(char** ifs, int num_ifs, int do_ip4,
|
||||||
|
int do_ip6, int* availports, int numavailports)
|
||||||
|
{
|
||||||
|
struct shared_ports* shp = calloc(1, sizeof(*shp));
|
||||||
|
if(!shp) {
|
||||||
|
log_err("malloc failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
lock_basic_init(&shp->lock);
|
||||||
|
lock_protect(&shp->lock, shp, sizeof(*shp));
|
||||||
|
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
/* Allocate interfaces */
|
||||||
|
if(!shared_ports_alloc_ifs(shp, ifs, num_ifs, do_ip4, do_ip6,
|
||||||
|
availports, numavailports)) {
|
||||||
|
log_err("malloc failed");
|
||||||
|
shared_ports_delete(shp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)ifs; (void)num_ifs; (void)do_ip4; (void)do_ip6;
|
||||||
|
(void)availports; (void)numavailports;
|
||||||
|
#endif
|
||||||
|
return shp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
/** Delete shared ports interface structure */
|
||||||
|
static void shared_ports_if_delete(struct shared_ports_if* shpif)
|
||||||
|
{
|
||||||
|
if(!shpif)
|
||||||
|
return;
|
||||||
|
free(shpif->avail_ports);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void shared_ports_delete(struct shared_ports* shp)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
if(!shp)
|
||||||
|
return;
|
||||||
|
lock_basic_destroy(&shp->lock);
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
for(i=0; i<shp->num_ip4; i++) {
|
||||||
|
shared_ports_if_delete(&shp->ip4_ifs[i]);
|
||||||
|
}
|
||||||
|
free(shp->ip4_ifs);
|
||||||
|
for(i=0; i<shp->num_ip6; i++) {
|
||||||
|
shared_ports_if_delete(&shp->ip6_ifs[i]);
|
||||||
|
}
|
||||||
|
free(shp->ip6_ifs);
|
||||||
|
#endif
|
||||||
|
free(shp);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct shared_ports_if* shared_ports_find_if(struct shared_ports* shp,
|
||||||
|
struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
struct shared_ports_if* ret, *ifs = NULL;
|
||||||
|
int i, num_ifs = 0;
|
||||||
|
lock_basic_lock(&shp->lock);
|
||||||
|
if(addr_is_ip6(addr, addrlen)) {
|
||||||
|
ifs = shp->ip6_ifs;
|
||||||
|
num_ifs = shp->num_ip6;
|
||||||
|
} else {
|
||||||
|
ifs = shp->ip4_ifs;
|
||||||
|
num_ifs = shp->num_ip4;
|
||||||
|
}
|
||||||
|
for(i=0; i<num_ifs; i++) {
|
||||||
|
if(sockaddr_cmp(addr, addrlen, &ifs[i].addr,
|
||||||
|
ifs[i].addrlen) == 0
|
||||||
|
&& pfxlen == ifs[i].pfxlen) {
|
||||||
|
ret = &ifs[i];
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
(void)shp; (void)addr; (void)addrlen; (void)pfxlen;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int shared_ports_fetch_random(struct shared_ports* shp,
|
||||||
|
struct shared_ports_if* shpif, struct ub_randstate* rnd,
|
||||||
|
int udp_connect, int reusenum, int* port, int* reused)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
int portno = 0, my_port = 0;
|
||||||
|
if(!shpif)
|
||||||
|
return 0;
|
||||||
|
lock_basic_lock(&shp->lock);
|
||||||
|
if(udp_connect) {
|
||||||
|
/* if we connect() we cannot reuse fds for a port. */
|
||||||
|
if(shpif->inuse >= shpif->avail_total) {
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
my_port = ub_random_max(rnd,
|
||||||
|
shpif->avail_total - shpif->inuse);
|
||||||
|
} else {
|
||||||
|
/* select from free ports and open ports on this thread. */
|
||||||
|
if(shpif->inuse >= shpif->avail_total) {
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
if(reusenum == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
my_port = ub_random_max(rnd, reusenum);
|
||||||
|
*port = my_port;
|
||||||
|
*reused = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
my_port = ub_random_max(rnd, shpif->avail_total - shpif->inuse
|
||||||
|
+ reusenum);
|
||||||
|
if(my_port < reusenum) {
|
||||||
|
/* port already open */
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
*port = my_port;
|
||||||
|
*reused = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
my_port -= reusenum;
|
||||||
|
}
|
||||||
|
log_assert(shpif->inuse < shpif->avail_total);
|
||||||
|
log_assert(my_port >= 0 && my_port < shpif->avail_total);
|
||||||
|
portno = shpif->avail_ports[my_port];
|
||||||
|
shpif->avail_ports[my_port] =
|
||||||
|
shpif->avail_ports[shpif->avail_total-shpif->inuse-1];
|
||||||
|
shpif->inuse++;
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
*port = portno;
|
||||||
|
*reused = 0;
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
(void)shp; (void)shpif; (void)rnd; (void)udp_connect;
|
||||||
|
(void)reusenum;
|
||||||
|
*port = 0;
|
||||||
|
*reused = 0;
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_ports_return_port(struct shared_ports* shp,
|
||||||
|
struct shared_ports_if* shpif, int port)
|
||||||
|
{
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
|
if(!shpif)
|
||||||
|
return;
|
||||||
|
lock_basic_lock(&shp->lock);
|
||||||
|
log_assert(shpif->inuse > 0);
|
||||||
|
shpif->avail_ports[shpif->avail_total - shpif->inuse] = port;
|
||||||
|
shpif->inuse--;
|
||||||
|
lock_basic_unlock(&shp->lock);
|
||||||
|
#else
|
||||||
|
(void)shp; (void)shpif; (void)port;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|||||||
+96
-11
@@ -70,6 +70,8 @@ struct module_env;
|
|||||||
struct module_qstate;
|
struct module_qstate;
|
||||||
struct query_info;
|
struct query_info;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
|
struct shared_ports;
|
||||||
|
struct shared_ports_if;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send queries to outside servers and wait for answers from servers.
|
* Send queries to outside servers and wait for answers from servers.
|
||||||
@@ -119,6 +121,9 @@ struct outside_network {
|
|||||||
int udp_connect;
|
int udp_connect;
|
||||||
/** number of udp packets sent. */
|
/** number of udp packets sent. */
|
||||||
size_t num_udp_outgoing;
|
size_t num_udp_outgoing;
|
||||||
|
/** the shared ports structure, with random ports numbers.
|
||||||
|
* This is a reference to the member in the daemon structure. */
|
||||||
|
struct shared_ports* shared_ports;
|
||||||
|
|
||||||
/** array of outgoing IP4 interfaces */
|
/** array of outgoing IP4 interfaces */
|
||||||
struct port_if* ip4_ifs;
|
struct port_if* ip4_ifs;
|
||||||
@@ -211,11 +216,8 @@ struct port_if {
|
|||||||
int pfxlen;
|
int pfxlen;
|
||||||
|
|
||||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
/** the available ports array. These are unused.
|
/** the shared port numbers for this interface. */
|
||||||
* Only the first total-inuse part is filled. */
|
struct shared_ports_if* shpif;
|
||||||
int* avail_ports;
|
|
||||||
/** the total number of available ports (size of the array) */
|
|
||||||
int avail_total;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** array of the commpoints currently in use.
|
/** array of the commpoints currently in use.
|
||||||
@@ -245,6 +247,42 @@ struct port_comm {
|
|||||||
struct comm_point* cp;
|
struct comm_point* cp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared ports, the list of ports shared across threads
|
||||||
|
*/
|
||||||
|
struct shared_ports {
|
||||||
|
/** mutex on the ports */
|
||||||
|
lock_basic_type lock;
|
||||||
|
/** array of IP4 interfaces */
|
||||||
|
struct shared_ports_if* ip4_ifs;
|
||||||
|
/** number of outgoing IP4 interfaces */
|
||||||
|
int num_ip4;
|
||||||
|
/** array of IP6 interfaces */
|
||||||
|
struct shared_ports_if* ip6_ifs;
|
||||||
|
/** number of outgoing IP6 interfaces */
|
||||||
|
int num_ip6;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared ports for an interface.
|
||||||
|
*/
|
||||||
|
struct shared_ports_if {
|
||||||
|
/** address ready to allocate new socket (except port no). */
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
/** length of addr field */
|
||||||
|
socklen_t addrlen;
|
||||||
|
/** if a netblock, the prefix */
|
||||||
|
int pfxlen;
|
||||||
|
|
||||||
|
/** the available ports array. These are unused.
|
||||||
|
* Only the first total-inuse part is filled. */
|
||||||
|
int* avail_ports;
|
||||||
|
/** the total number of available ports (size of the array) */
|
||||||
|
int avail_total;
|
||||||
|
/** the number in use. */
|
||||||
|
int inuse;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reuse TCP connection, still open can be used again.
|
* Reuse TCP connection, still open can be used again.
|
||||||
*/
|
*/
|
||||||
@@ -419,7 +457,7 @@ struct waiting_tcp {
|
|||||||
void* cb_arg;
|
void* cb_arg;
|
||||||
/** if it uses ssl upstream */
|
/** if it uses ssl upstream */
|
||||||
int ssl_upstream;
|
int ssl_upstream;
|
||||||
/** ref to the tls_auth_name from the serviced_query */
|
/** owned copy of the tls_auth_name (malloced) */
|
||||||
char* tls_auth_name;
|
char* tls_auth_name;
|
||||||
/** the packet was involved in an error, to stop looping errors */
|
/** the packet was involved in an error, to stop looping errors */
|
||||||
int error_count;
|
int error_count;
|
||||||
@@ -551,8 +589,6 @@ struct serviced_query {
|
|||||||
* @param infra: pointer to infra cached used for serviced queries.
|
* @param infra: pointer to infra cached used for serviced queries.
|
||||||
* @param rnd: stored to create random numbers for serviced queries.
|
* @param rnd: stored to create random numbers for serviced queries.
|
||||||
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
|
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
|
||||||
* @param availports: array of available ports.
|
|
||||||
* @param numavailports: number of available ports in array.
|
|
||||||
* @param unwanted_threshold: when to take defensive action.
|
* @param unwanted_threshold: when to take defensive action.
|
||||||
* @param unwanted_action: the action to take.
|
* @param unwanted_action: the action to take.
|
||||||
* @param unwanted_param: user parameter to action.
|
* @param unwanted_param: user parameter to action.
|
||||||
@@ -567,17 +603,18 @@ struct serviced_query {
|
|||||||
* @param max_reuse_tcp_queries: max number of queries on a reuse connection.
|
* @param max_reuse_tcp_queries: max number of queries on a reuse connection.
|
||||||
* @param tcp_reuse_timeout: timeout for REUSE entries in milliseconds.
|
* @param tcp_reuse_timeout: timeout for REUSE entries in milliseconds.
|
||||||
* @param tcp_auth_query_timeout: timeout in milliseconds for TCP queries to auth servers.
|
* @param tcp_auth_query_timeout: timeout in milliseconds for TCP queries to auth servers.
|
||||||
|
* @param shared_ports: the shared_ports structure.
|
||||||
* @return: the new structure (with no pending answers) or NULL on error.
|
* @return: the new structure (with no pending answers) or NULL on error.
|
||||||
*/
|
*/
|
||||||
struct outside_network* outside_network_create(struct comm_base* base,
|
struct outside_network* outside_network_create(struct comm_base* base,
|
||||||
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
|
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
|
||||||
int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
|
int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
|
||||||
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
|
struct ub_randstate* rnd, int use_caps_for_id,
|
||||||
int numavailports, size_t unwanted_threshold, int tcp_mss,
|
size_t unwanted_threshold, int tcp_mss,
|
||||||
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
|
||||||
void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv,
|
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 udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
|
||||||
int tcp_auth_query_timeout);
|
int tcp_auth_query_timeout, struct shared_ports* shared_ports);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete outside_network structure.
|
* Delete outside_network structure.
|
||||||
@@ -822,6 +859,54 @@ struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
|
|||||||
/** connect tcp connection to addr, 0 on failure */
|
/** connect tcp connection to addr, 0 on failure */
|
||||||
int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);
|
int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new shared ports structure.
|
||||||
|
* @param ifs: interface names (or NULL for default interface).
|
||||||
|
* These interfaces must be able to access all authoritative servers.
|
||||||
|
* @param num_ifs: number of names in array ifs.
|
||||||
|
* @param do_ip4: service IP4.
|
||||||
|
* @param do_ip6: service IP6.
|
||||||
|
* @param availports: array of available ports.
|
||||||
|
* @param numavailports: number of available ports in array.
|
||||||
|
* @return new, or NULL on failure.
|
||||||
|
*/
|
||||||
|
struct shared_ports* shared_ports_create(char** ifs, int num_ifs, int do_ip4,
|
||||||
|
int do_ip6, int* availports, int numavailports);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete shared ports structure.
|
||||||
|
* @param shp: shared ports structure.
|
||||||
|
*/
|
||||||
|
void shared_ports_delete(struct shared_ports* shp);
|
||||||
|
|
||||||
|
/** Find interface in shared ports. */
|
||||||
|
struct shared_ports_if* shared_ports_find_if(struct shared_ports* shp,
|
||||||
|
struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a shared port from the list of random ports.
|
||||||
|
* @param shp: shared ports structure.
|
||||||
|
* @param shpif: the shared ports interface.
|
||||||
|
* @param rnd: used to make random numbers.
|
||||||
|
* @param udp_connect: set to true if no reuse is possible.
|
||||||
|
* @param reusenum: number of ports that can be reused (already open).
|
||||||
|
* @param port: the port number is returned.
|
||||||
|
* @param reused: if the port numer is reused, returned.
|
||||||
|
* @return false on failure. That can mean no more free ports to use.
|
||||||
|
*/
|
||||||
|
int shared_ports_fetch_random(struct shared_ports* shp,
|
||||||
|
struct shared_ports_if* shpif, struct ub_randstate* rnd,
|
||||||
|
int udp_connect, int reusenum, int* port, int* reused);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a shared port to the list of random ports.
|
||||||
|
* @param shp: shared ports structure.
|
||||||
|
* @param shpif: the shared ports interface.
|
||||||
|
* @param port: port number to return to be used again.
|
||||||
|
*/
|
||||||
|
void shared_ports_return_port(struct shared_ports* shp,
|
||||||
|
struct shared_ports_if* shpif, int port);
|
||||||
|
|
||||||
/** callback for incoming udp answers from the network */
|
/** callback for incoming udp answers from the network */
|
||||||
int outnet_udp_cb(struct comm_point* c, void* arg, int error,
|
int outnet_udp_cb(struct comm_point* c, void* arg, int error,
|
||||||
struct comm_reply *reply_info);
|
struct comm_reply *reply_info);
|
||||||
|
|||||||
@@ -129,6 +129,12 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
|||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
struct outbound_entry* libworker_send_query(
|
struct outbound_entry* libworker_send_query(
|
||||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||||
|
|||||||
@@ -1522,9 +1522,9 @@ doq_client_send_pkt(struct doq_client_data* data, uint32_t ecn, uint8_t* buf,
|
|||||||
}
|
}
|
||||||
log_err("doq sendmsg: %s", strerror(errno));
|
log_err("doq sendmsg: %s", strerror(errno));
|
||||||
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
||||||
ngtcp2_ccerr_set_application_error(&data->ccerr, -1, NULL, 0);
|
ngtcp2_ccerr_set_application_error(&data->ccerr, 1, NULL, 0);
|
||||||
#else
|
#else
|
||||||
ngtcp2_connection_close_error_set_application_error(&data->last_error, -1, NULL, 0);
|
ngtcp2_connection_close_error_set_application_error(&data->last_error, 1, NULL, 0);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -2676,6 +2676,11 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
|||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||||
|
{
|
||||||
|
log_assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
|
|||||||
+27
-3
@@ -1126,15 +1126,16 @@ outside_network_create(struct comm_base* base, size_t bufsize,
|
|||||||
int ATTR_UNUSED(dscp),
|
int ATTR_UNUSED(dscp),
|
||||||
struct infra_cache* infra,
|
struct infra_cache* infra,
|
||||||
struct ub_randstate* ATTR_UNUSED(rnd),
|
struct ub_randstate* ATTR_UNUSED(rnd),
|
||||||
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
|
int ATTR_UNUSED(use_caps_for_id),
|
||||||
int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
|
size_t ATTR_UNUSED(unwanted_threshold),
|
||||||
int ATTR_UNUSED(outgoing_tcp_mss),
|
int ATTR_UNUSED(outgoing_tcp_mss),
|
||||||
void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
|
void (*unwanted_action)(void*), void* ATTR_UNUSED(unwanted_param),
|
||||||
int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx),
|
int ATTR_UNUSED(do_udp), void* ATTR_UNUSED(sslctx),
|
||||||
int ATTR_UNUSED(delayclose), int ATTR_UNUSED(tls_use_sni),
|
int ATTR_UNUSED(delayclose), int ATTR_UNUSED(tls_use_sni),
|
||||||
struct dt_env* ATTR_UNUSED(dtenv), int ATTR_UNUSED(udp_connect),
|
struct dt_env* ATTR_UNUSED(dtenv), int ATTR_UNUSED(udp_connect),
|
||||||
int ATTR_UNUSED(max_reuse_tcp_queries), int ATTR_UNUSED(tcp_reuse_timeout),
|
int ATTR_UNUSED(max_reuse_tcp_queries), int ATTR_UNUSED(tcp_reuse_timeout),
|
||||||
int ATTR_UNUSED(tcp_auth_query_timeout))
|
int ATTR_UNUSED(tcp_auth_query_timeout),
|
||||||
|
struct shared_ports* ATTR_UNUSED(shared_ports))
|
||||||
{
|
{
|
||||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||||
struct outside_network* outnet = calloc(1,
|
struct outside_network* outnet = calloc(1,
|
||||||
@@ -1981,6 +1982,20 @@ int outnet_tcp_connect(int ATTR_UNUSED(s), struct sockaddr_storage* ATTR_UNUSED(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct shared_ports* shared_ports_create(char** ATTR_UNUSED(ifs),
|
||||||
|
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
|
||||||
|
int ATTR_UNUSED(do_ip6), int* ATTR_UNUSED(availports),
|
||||||
|
int ATTR_UNUSED(numavailports))
|
||||||
|
{
|
||||||
|
return calloc(1, sizeof(struct shared_ports));
|
||||||
|
}
|
||||||
|
|
||||||
|
void shared_ports_delete(struct shared_ports* shp)
|
||||||
|
{
|
||||||
|
if(!shp) return;
|
||||||
|
free(shp);
|
||||||
|
}
|
||||||
|
|
||||||
int tcp_req_info_add_meshstate(struct tcp_req_info* ATTR_UNUSED(req),
|
int tcp_req_info_add_meshstate(struct tcp_req_info* ATTR_UNUSED(req),
|
||||||
struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m))
|
struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m))
|
||||||
{
|
{
|
||||||
@@ -2022,6 +2037,15 @@ void http2_stream_remove_mesh_state(struct http2_stream* ATTR_UNUSED(h2_stream))
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doq_stream_add_meshstate(struct doq_stream* ATTR_UNUSED(stream),
|
||||||
|
struct mesh_area* ATTR_UNUSED(mesh), struct mesh_state* ATTR_UNUSED(m))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void doq_stream_remove_mesh_state(struct doq_stream* ATTR_UNUSED(stream))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||||
void* ATTR_UNUSED(arg))
|
void* ATTR_UNUSED(arg))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1282,6 +1282,61 @@ static void localzone_test(void)
|
|||||||
localzone_parents_test();
|
localzone_parents_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "services/mesh.h"
|
||||||
|
/** mesh unit tests */
|
||||||
|
static void mesh_test(void)
|
||||||
|
{
|
||||||
|
struct regional* r2, *r3;
|
||||||
|
struct respip_client_info* c1, *c2, *c3;
|
||||||
|
unit_show_func("services/mesh.c", "mesh_copy_client_info");
|
||||||
|
r2 = regional_create();
|
||||||
|
r3 = regional_create();
|
||||||
|
if(!r2 || !r3) fatal_exit("out of memory");
|
||||||
|
|
||||||
|
c1 = calloc(1, sizeof(*c1));
|
||||||
|
if(!c1) fatal_exit("out of memory");
|
||||||
|
c1->view = calloc(1, sizeof(*c1->view));
|
||||||
|
if(!c1->view) fatal_exit("out of memory");
|
||||||
|
c1->view->name = strdup("view1");
|
||||||
|
if(!c1->view->name) fatal_exit("out of memory");
|
||||||
|
|
||||||
|
c2 = mesh_copy_client_info(r2, c1);
|
||||||
|
if(!c2) fatal_exit("out of memory");
|
||||||
|
c3 = mesh_copy_client_info(r3, c2);
|
||||||
|
if(!c3) fatal_exit("out of memory");
|
||||||
|
|
||||||
|
unit_assert(strcmp(c1->view->name, c2->view_name) == 0);
|
||||||
|
unit_assert(strcmp(c1->view->name, c3->view_name) == 0);
|
||||||
|
|
||||||
|
/* make sure that the c3 view_name is in the r3 region. */
|
||||||
|
unit_assert(r3->next == NULL); /* only the first chunk present atm */
|
||||||
|
if(strlen(c3->view_name) >= r3->large_object_size) {
|
||||||
|
char* a = r3->large_list;
|
||||||
|
int found = 0;
|
||||||
|
while(a) {
|
||||||
|
if(strcmp(c3->view_name,
|
||||||
|
a + /* ALIGNEMENT */ sizeof(uint64_t)) == 0) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
a = *(char**)a;
|
||||||
|
}
|
||||||
|
unit_assert(found == 1);
|
||||||
|
} else {
|
||||||
|
/* The allocation is expected in the r3 region first chunk */
|
||||||
|
unit_assert((uint8_t*)c3->view_name < ((uint8_t*)r3)+r3->first_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
regional_destroy(r2);
|
||||||
|
/* ASAN should complain for the freed access below */
|
||||||
|
unit_assert(strcmp(c1->view->name, c3->view_name) == 0);
|
||||||
|
|
||||||
|
regional_destroy(r3);
|
||||||
|
free(c1->view->name);
|
||||||
|
free(c1->view);
|
||||||
|
free(c1);
|
||||||
|
}
|
||||||
|
|
||||||
void unit_show_func(const char* file, const char* func)
|
void unit_show_func(const char* file, const char* func)
|
||||||
{
|
{
|
||||||
printf("test %s:%s\n", file, func);
|
printf("test %s:%s\n", file, func);
|
||||||
@@ -1356,6 +1411,7 @@ main(int argc, char* argv[])
|
|||||||
msgparse_test();
|
msgparse_test();
|
||||||
edns_ede_answer_encode_test();
|
edns_ede_answer_encode_test();
|
||||||
localzone_test();
|
localzone_test();
|
||||||
|
mesh_test();
|
||||||
#ifdef CLIENT_SUBNET
|
#ifdef CLIENT_SUBNET
|
||||||
ecs_test();
|
ecs_test();
|
||||||
#endif /* CLIENT_SUBNET */
|
#endif /* CLIENT_SUBNET */
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "testcode/unitmain.h"
|
#include "testcode/unitmain.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
#include "util/net_help.h"
|
||||||
#include "util/random.h"
|
#include "util/random.h"
|
||||||
#include "services/outside_network.h"
|
#include "services/outside_network.h"
|
||||||
|
|
||||||
@@ -479,6 +480,278 @@ static void reuse_write_wait_test(void)
|
|||||||
check_reuse_write_wait_removal(1, &reuse, store, 0, 1);
|
check_reuse_write_wait_removal(1, &reuse, store, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void shared_port_test_ifs(void)
|
||||||
|
{
|
||||||
|
struct shared_ports* shp;
|
||||||
|
struct shared_ports_if* shpif;
|
||||||
|
char* ifs[] = {"1.2.3.4", "1.2.3.5", "::1:2", "::1:3"};
|
||||||
|
int availports[] = {1, 2, 3, 4};
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
|
||||||
|
shp = shared_ports_create(ifs, 4, 1, 1, availports, 4);
|
||||||
|
unit_assert(shp);
|
||||||
|
|
||||||
|
if(!ipstrtoaddr("1.2.3.4", UNBOUND_DNS_PORT, &addr, &addrlen))
|
||||||
|
log_err("could not parse");
|
||||||
|
shpif = shared_ports_find_if(shp, &addr, addrlen, 0);
|
||||||
|
unit_assert(shpif);
|
||||||
|
|
||||||
|
if(!ipstrtoaddr("1.2.3.5", UNBOUND_DNS_PORT, &addr, &addrlen))
|
||||||
|
log_err("could not parse");
|
||||||
|
shpif = shared_ports_find_if(shp, &addr, addrlen, 0);
|
||||||
|
unit_assert(shpif);
|
||||||
|
|
||||||
|
if(!ipstrtoaddr("::1:2", UNBOUND_DNS_PORT, &addr, &addrlen))
|
||||||
|
log_err("could not parse");
|
||||||
|
shpif = shared_ports_find_if(shp, &addr, addrlen, 0);
|
||||||
|
unit_assert(shpif);
|
||||||
|
|
||||||
|
if(!ipstrtoaddr("::1:3", UNBOUND_DNS_PORT, &addr, &addrlen))
|
||||||
|
log_err("could not parse");
|
||||||
|
shpif = shared_ports_find_if(shp, &addr, addrlen, 0);
|
||||||
|
unit_assert(shpif);
|
||||||
|
|
||||||
|
shared_ports_delete(shp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** See if a port is on the shared_ports ports list */
|
||||||
|
static int
|
||||||
|
pif_list_contains(struct shared_ports_if* shpif, int item)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unit_assert(shpif->inuse >= 0 && shpif->inuse <= shpif->avail_total);
|
||||||
|
for(i=0; i< shpif->avail_total - shpif->inuse; i++) {
|
||||||
|
if(shpif->avail_ports[i] == item)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** See if a number of ports are on the shared_ports list */
|
||||||
|
static int
|
||||||
|
pif_list_contains_items(struct shared_ports_if* shpif, int item1,
|
||||||
|
int item2, int item3, int item4)
|
||||||
|
{
|
||||||
|
if(item1 != -1 && !pif_list_contains(shpif, item1))
|
||||||
|
return 0;
|
||||||
|
if(item2 != -1 && !pif_list_contains(shpif, item2))
|
||||||
|
return 0;
|
||||||
|
if(item3 != -1 && !pif_list_contains(shpif, item3))
|
||||||
|
return 0;
|
||||||
|
if(item4 != -1 && !pif_list_contains(shpif, item4))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shared_port_test_port(void)
|
||||||
|
{
|
||||||
|
struct shared_ports* shp;
|
||||||
|
struct shared_ports_if* shpif;
|
||||||
|
char* ifs[] = {"1.2.3.4", "1.2.3.5"};
|
||||||
|
int availports[] = {1, 2, 3, 4};
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
int p1, p2, p3, reused;
|
||||||
|
struct ub_randstate* rnd;
|
||||||
|
|
||||||
|
rnd = ub_initstate(NULL);
|
||||||
|
unit_assert(rnd);
|
||||||
|
|
||||||
|
shp = shared_ports_create(ifs, 2, 1, 1, availports, 4);
|
||||||
|
unit_assert(shp);
|
||||||
|
|
||||||
|
if(!ipstrtoaddr("1.2.3.4", UNBOUND_DNS_PORT, &addr, &addrlen))
|
||||||
|
log_err("could not parse");
|
||||||
|
shpif = shared_ports_find_if(shp, &addr, addrlen, 0);
|
||||||
|
unit_assert(shpif);
|
||||||
|
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 0);
|
||||||
|
unit_assert(pif_list_contains_items(shpif, 1, 2, 3, 4));
|
||||||
|
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
unit_assert(!pif_list_contains(shpif, p1));
|
||||||
|
if(p1 != 1) unit_assert(pif_list_contains(shpif, 1));
|
||||||
|
if(p1 != 2) unit_assert(pif_list_contains(shpif, 2));
|
||||||
|
if(p1 != 3) unit_assert(pif_list_contains(shpif, 3));
|
||||||
|
if(p1 != 4) unit_assert(pif_list_contains(shpif, 4));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 1);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p1);
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 0);
|
||||||
|
unit_assert(pif_list_contains_items(shpif, 1, 2, 3, 4));
|
||||||
|
|
||||||
|
/* pick up two items */
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p2, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p2 != 0);
|
||||||
|
unit_assert(!pif_list_contains(shpif, p1));
|
||||||
|
unit_assert(!pif_list_contains(shpif, p2));
|
||||||
|
if(p1 != 1 && p2 != 1) unit_assert(pif_list_contains(shpif, 1));
|
||||||
|
if(p1 != 2 && p2 != 2) unit_assert(pif_list_contains(shpif, 2));
|
||||||
|
if(p1 != 3 && p2 != 3) unit_assert(pif_list_contains(shpif, 3));
|
||||||
|
if(p1 != 4 && p2 != 4) unit_assert(pif_list_contains(shpif, 4));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 2);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p1);
|
||||||
|
unit_assert(pif_list_contains(shpif, p1));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 1);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p2);
|
||||||
|
unit_assert(pif_list_contains(shpif, p2));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 0);
|
||||||
|
unit_assert(pif_list_contains_items(shpif, 1, 2, 3, 4));
|
||||||
|
|
||||||
|
/* pick up three items */
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p2, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p2 != 0);
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p3, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p3 != 0);
|
||||||
|
unit_assert(!pif_list_contains(shpif, p1));
|
||||||
|
unit_assert(!pif_list_contains(shpif, p2));
|
||||||
|
unit_assert(!pif_list_contains(shpif, p3));
|
||||||
|
if(p1 != 1 && p2 != 1 && p3 != 1)
|
||||||
|
unit_assert(pif_list_contains(shpif, 1));
|
||||||
|
if(p1 != 2 && p2 != 2 && p3 != 2)
|
||||||
|
unit_assert(pif_list_contains(shpif, 2));
|
||||||
|
if(p1 != 3 && p2 != 3 && p3 != 3)
|
||||||
|
unit_assert(pif_list_contains(shpif, 3));
|
||||||
|
if(p1 != 4 && p2 != 4 && p3 != 4)
|
||||||
|
unit_assert(pif_list_contains(shpif, 4));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 3);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p1);
|
||||||
|
unit_assert(pif_list_contains(shpif, p1));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 2);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p2);
|
||||||
|
unit_assert(pif_list_contains(shpif, p2));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 1);
|
||||||
|
|
||||||
|
shared_ports_return_port(shp, shpif, p3);
|
||||||
|
unit_assert(pif_list_contains(shpif, p3));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 0);
|
||||||
|
unit_assert(pif_list_contains_items(shpif, 1, 2, 3, 4));
|
||||||
|
|
||||||
|
/* pick up all four items */
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0, 0, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 0);
|
||||||
|
unit_assert(p1 != 0);
|
||||||
|
unit_assert(!pif_list_contains(shpif, 1));
|
||||||
|
unit_assert(!pif_list_contains(shpif, 2));
|
||||||
|
unit_assert(!pif_list_contains(shpif, 3));
|
||||||
|
unit_assert(!pif_list_contains(shpif, 4));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 4);
|
||||||
|
|
||||||
|
/* more fetches fail, it is fully inuse. */
|
||||||
|
unit_assert(!shared_ports_fetch_random(shp, shpif, rnd, 0, 0, &p2,
|
||||||
|
&reused));
|
||||||
|
unit_assert(!shared_ports_fetch_random(shp, shpif, rnd, 0, 0, &p3,
|
||||||
|
&reused));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 4);
|
||||||
|
|
||||||
|
/* reuse is then always the case */
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0 /* can reuse */, 4 /* reusenum */, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 1);
|
||||||
|
unit_assert(p1 >= 0 && p1 < 4 /* reusenum */);
|
||||||
|
|
||||||
|
if(!shared_ports_fetch_random(shp, shpif, rnd,
|
||||||
|
0 /* can reuse */, 4 /* reusenum */, &p1, &reused)) {
|
||||||
|
unit_assert(0); /* should succeed */
|
||||||
|
}
|
||||||
|
unit_assert(reused == 1);
|
||||||
|
unit_assert(p1 >= 0 && p1 < 4 /* reusenum */);
|
||||||
|
|
||||||
|
/* return all the ports */
|
||||||
|
shared_ports_return_port(shp, shpif, 1);
|
||||||
|
unit_assert(pif_list_contains(shpif, 1));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 3);
|
||||||
|
shared_ports_return_port(shp, shpif, 2);
|
||||||
|
unit_assert(pif_list_contains(shpif, 2));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 2);
|
||||||
|
shared_ports_return_port(shp, shpif, 3);
|
||||||
|
unit_assert(pif_list_contains(shpif, 3));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 1);
|
||||||
|
shared_ports_return_port(shp, shpif, 4);
|
||||||
|
unit_assert(pif_list_contains(shpif, 4));
|
||||||
|
unit_assert(shpif->avail_total == 4);
|
||||||
|
unit_assert(shpif->inuse == 0);
|
||||||
|
unit_assert(pif_list_contains_items(shpif, 1, 2, 3, 4));
|
||||||
|
|
||||||
|
shared_ports_delete(shp);
|
||||||
|
ub_randfree(rnd);
|
||||||
|
}
|
||||||
|
|
||||||
void tcpreuse_test(void)
|
void tcpreuse_test(void)
|
||||||
{
|
{
|
||||||
unit_show_feature("tcp_reuse");
|
unit_show_feature("tcp_reuse");
|
||||||
@@ -486,4 +759,7 @@ void tcpreuse_test(void)
|
|||||||
tcp_reuse_tree_list_test();
|
tcp_reuse_tree_list_test();
|
||||||
waiting_tcp_list_test();
|
waiting_tcp_list_test();
|
||||||
reuse_write_wait_test();
|
reuse_write_wait_test();
|
||||||
|
unit_show_feature("shared_ports");
|
||||||
|
shared_port_test_ifs();
|
||||||
|
shared_port_test_port();
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -12,6 +12,7 @@ server:
|
|||||||
ede: no # It is not needed for dns-error-reporting; only for clients to receive EDEs
|
ede: no # It is not needed for dns-error-reporting; only for clients to receive EDEs
|
||||||
dns-error-reporting: yes
|
dns-error-reporting: yes
|
||||||
do-ip6: no
|
do-ip6: no
|
||||||
|
do-not-query-localhost: no
|
||||||
|
|
||||||
stub-zone:
|
stub-zone:
|
||||||
name: domain
|
name: domain
|
||||||
|
|||||||
+9
-8
@@ -9,20 +9,21 @@ PRE="../.."
|
|||||||
|
|
||||||
# do the test
|
# do the test
|
||||||
|
|
||||||
# Query plain request over DNSCrypt channel get closed
|
# Query plain request over DNSCrypt.
|
||||||
# We use TCP to avoid hanging on waiting for UDP.
|
# This used to close the channel; now it returns SERVFAIL.
|
||||||
# We expect `outfile` to contain no DNS payload
|
# Old: We use TCP to avoid hanging on waiting for UDP.
|
||||||
echo "> dig TCP www.example.com. DNSCrypt port"
|
# We expect `outfile` to contain no DNS payload
|
||||||
dig +tcp @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
|
echo "> dig www.example.com. DNSCrypt port"
|
||||||
|
dig @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
|
||||||
echo "> cat logfiles"
|
echo "> cat logfiles"
|
||||||
cat fwd.log
|
cat fwd.log
|
||||||
cat unbound.log
|
cat unbound.log
|
||||||
echo "> check answer"
|
echo "> check answer"
|
||||||
if grep "QUESTION SECTION" outfile; then
|
if grep "SERVFAIL" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
echo "NOK"
|
echo "NOK"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
echo "OK"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,20 +9,21 @@ PRE="../.."
|
|||||||
|
|
||||||
# do the test
|
# do the test
|
||||||
|
|
||||||
# Query plain request over DNSCrypt channel get closed
|
# Query plain request over DNSCrypt.
|
||||||
# We use TCP to avoid hanging on waiting for UDP.
|
# This used to close the channel; now it returns SERVFAIL.
|
||||||
# We expect `outfile` to contain no DNS payload
|
# Old: We use TCP to avoid hanging on waiting for UDP.
|
||||||
echo "> dig TCP www.example.com. DNSCrypt port"
|
# We expect `outfile` to contain no DNS payload
|
||||||
dig +tcp @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
|
echo "> dig www.example.com. DNSCrypt port"
|
||||||
|
dig @127.0.0.1 -p $DNSCRYPT_PORT www.example.com. A | tee outfile
|
||||||
echo "> cat logfiles"
|
echo "> cat logfiles"
|
||||||
cat fwd.log
|
cat fwd.log
|
||||||
cat unbound.log
|
cat unbound.log
|
||||||
echo "> check answer"
|
echo "> check answer"
|
||||||
if grep "QUESTION SECTION" outfile; then
|
if grep "SERVFAIL" outfile; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
echo "NOK"
|
echo "NOK"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
echo "OK"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Vendored
+4
-4
@@ -319,7 +319,7 @@ example.com. 360 IN NS ns.example.com.
|
|||||||
SECTION ADDITIONAL
|
SECTION ADDITIONAL
|
||||||
; this is picked up from the parent (because this simulation has the
|
; this is picked up from the parent (because this simulation has the
|
||||||
; parent respond with servfail, not actually timeout)
|
; parent respond with servfail, not actually timeout)
|
||||||
ns.example.com. 3600 IN A 1.2.3.4
|
ns.example.com. 360 IN A 1.2.3.4
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
|
|
||||||
; another query to see if there is another lookup towards the authority
|
; another query to see if there is another lookup towards the authority
|
||||||
@@ -342,7 +342,7 @@ www.example.com. 360 IN A 10.20.30.40
|
|||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
example.com. 360 IN NS ns.example.com.
|
example.com. 360 IN NS ns.example.com.
|
||||||
SECTION ADDITIONAL
|
SECTION ADDITIONAL
|
||||||
ns.example.com. 3600 IN A 1.2.3.4
|
ns.example.com. 360 IN A 1.2.3.4
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
|
|
||||||
; some time later another query, and now it is fine to bother the authority
|
; some time later another query, and now it is fine to bother the authority
|
||||||
@@ -367,7 +367,7 @@ www.example.com. 330 IN A 10.20.30.40
|
|||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
example.com. 330 IN NS ns.example.com.
|
example.com. 330 IN NS ns.example.com.
|
||||||
SECTION ADDITIONAL
|
SECTION ADDITIONAL
|
||||||
ns.example.com. 3570 IN A 1.2.3.4
|
ns.example.com. 330 IN A 1.2.3.4
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
; now the just-looked-up entry
|
; now the just-looked-up entry
|
||||||
STEP 190 QUERY
|
STEP 190 QUERY
|
||||||
@@ -388,7 +388,7 @@ www.example.com. 3600 IN A 10.20.30.40
|
|||||||
SECTION AUTHORITY
|
SECTION AUTHORITY
|
||||||
example.com. 3600 IN NS ns.example.com.
|
example.com. 3600 IN NS ns.example.com.
|
||||||
SECTION ADDITIONAL
|
SECTION ADDITIONAL
|
||||||
ns.example.com. 3570 IN A 1.2.3.4
|
ns.example.com. 3600 IN A 1.2.3.4
|
||||||
ENTRY_END
|
ENTRY_END
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -687,6 +687,9 @@ calc_size(sldns_buffer* pkt, uint16_t type, struct rr_parse* rr)
|
|||||||
}
|
}
|
||||||
rdf++;
|
rdf++;
|
||||||
}
|
}
|
||||||
|
/* rdata ended before all _dname_count names were seen */
|
||||||
|
if(count != 0)
|
||||||
|
return 0; /* the rdata is too short. */
|
||||||
}
|
}
|
||||||
/* remaining rdata */
|
/* remaining rdata */
|
||||||
rr->size += pkt_len;
|
rr->size += pkt_len;
|
||||||
@@ -1071,13 +1074,13 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
|
|||||||
* purposes. It will be overwritten if (re)creation
|
* purposes. It will be overwritten if (re)creation
|
||||||
* is needed.
|
* is needed.
|
||||||
*/
|
*/
|
||||||
if(repinfo->remote_addr.ss_family == AF_INET) {
|
if(repinfo->client_addr.ss_family == AF_INET) {
|
||||||
memcpy(server_cookie + 16,
|
memcpy(server_cookie + 16,
|
||||||
&((struct sockaddr_in*)&repinfo->remote_addr)->sin_addr, 4);
|
&((struct sockaddr_in*)&repinfo->client_addr)->sin_addr, 4);
|
||||||
} else {
|
} else {
|
||||||
cookie_is_v4 = 0;
|
cookie_is_v4 = 0;
|
||||||
memcpy(server_cookie + 16,
|
memcpy(server_cookie + 16,
|
||||||
&((struct sockaddr_in6*)&repinfo->remote_addr)->sin6_addr, 16);
|
&((struct sockaddr_in6*)&repinfo->client_addr)->sin6_addr, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfg->cookie_secret_file &&
|
if(cfg->cookie_secret_file &&
|
||||||
|
|||||||
@@ -198,6 +198,7 @@ get_cname_target(struct ub_packed_rrset_key* rrset, uint8_t** dname,
|
|||||||
{
|
{
|
||||||
struct packed_rrset_data* d;
|
struct packed_rrset_data* d;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
if(!rrset) return;
|
||||||
if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
|
if(ntohs(rrset->rk.type) != LDNS_RR_TYPE_CNAME &&
|
||||||
ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
|
ntohs(rrset->rk.type) != LDNS_RR_TYPE_DNAME)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -610,6 +610,7 @@ int
|
|||||||
fptr_whitelist_alloc_cleanup(void (*fptr)(void*))
|
fptr_whitelist_alloc_cleanup(void (*fptr)(void*))
|
||||||
{
|
{
|
||||||
if(fptr == &worker_alloc_cleanup) return 1;
|
if(fptr == &worker_alloc_cleanup) return 1;
|
||||||
|
else if(fptr == &libworker_alloc_cleanup) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -730,6 +730,12 @@ struct module_qstate {
|
|||||||
|
|
||||||
/** whether the reply should be dropped */
|
/** whether the reply should be dropped */
|
||||||
int is_drop;
|
int is_drop;
|
||||||
|
/** the global quota that was reached, by one of the modules.
|
||||||
|
* So that continued counting can go on from that point. */
|
||||||
|
int global_quota_reached;
|
||||||
|
/** the global quota that a query started with, it is a subquery,
|
||||||
|
* so that calling mesh states can see the increase. */
|
||||||
|
int global_quota_started;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+19
-25
@@ -1835,7 +1835,6 @@ doq_send_retry(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
char host[256], port[32];
|
char host[256], port[32];
|
||||||
struct ngtcp2_cid scid;
|
struct ngtcp2_cid scid;
|
||||||
uint8_t token[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN];
|
uint8_t token[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN];
|
||||||
ngtcp2_tstamp ts;
|
|
||||||
ngtcp2_ssize tokenlen, ret;
|
ngtcp2_ssize tokenlen, ret;
|
||||||
|
|
||||||
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
||||||
@@ -1849,12 +1848,10 @@ doq_send_retry(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
scid.datalen = c->doq_socket->sv_scidlen;
|
scid.datalen = c->doq_socket->sv_scidlen;
|
||||||
doq_cid_randfill(&scid, scid.datalen, c->doq_socket->rnd);
|
doq_cid_randfill(&scid, scid.datalen, c->doq_socket->rnd);
|
||||||
|
|
||||||
ts = doq_get_timestamp_nanosec();
|
|
||||||
|
|
||||||
tokenlen = ngtcp2_crypto_generate_retry_token(token,
|
tokenlen = ngtcp2_crypto_generate_retry_token(token,
|
||||||
c->doq_socket->static_secret, c->doq_socket->static_secret_len,
|
c->doq_socket->static_secret, c->doq_socket->static_secret_len,
|
||||||
hd->version, (void*)&paddr->addr, paddr->addrlen, &scid,
|
hd->version, (void*)&paddr->addr, paddr->addrlen, &scid,
|
||||||
&hd->dcid, ts);
|
&hd->dcid, doq_get_timestamp_nanosec());
|
||||||
if(tokenlen < 0) {
|
if(tokenlen < 0) {
|
||||||
log_err("ngtcp2_crypto_generate_retry_token failed: %s",
|
log_err("ngtcp2_crypto_generate_retry_token failed: %s",
|
||||||
ngtcp2_strerror(tokenlen));
|
ngtcp2_strerror(tokenlen));
|
||||||
@@ -1903,13 +1900,11 @@ doq_verify_retry_token(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
struct ngtcp2_cid* ocid, struct ngtcp2_pkt_hd* hd)
|
struct ngtcp2_cid* ocid, struct ngtcp2_pkt_hd* hd)
|
||||||
{
|
{
|
||||||
char host[256], port[32];
|
char host[256], port[32];
|
||||||
ngtcp2_tstamp ts;
|
|
||||||
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
||||||
sizeof(host), port, sizeof(port))) {
|
sizeof(host), port, sizeof(port))) {
|
||||||
log_err("doq_verify_retry_token failed");
|
log_err("doq_verify_retry_token failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ts = doq_get_timestamp_nanosec();
|
|
||||||
verbose(VERB_ALGO, "doq: verifying retry token from %s %s", host,
|
verbose(VERB_ALGO, "doq: verifying retry token from %s %s", host,
|
||||||
port);
|
port);
|
||||||
if(ngtcp2_crypto_verify_retry_token(ocid,
|
if(ngtcp2_crypto_verify_retry_token(ocid,
|
||||||
@@ -1921,7 +1916,7 @@ doq_verify_retry_token(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
c->doq_socket->static_secret,
|
c->doq_socket->static_secret,
|
||||||
c->doq_socket->static_secret_len, hd->version,
|
c->doq_socket->static_secret_len, hd->version,
|
||||||
(void*)&paddr->addr, paddr->addrlen, &hd->dcid,
|
(void*)&paddr->addr, paddr->addrlen, &hd->dcid,
|
||||||
10*NGTCP2_SECONDS, ts) != 0) {
|
10*NGTCP2_SECONDS, doq_get_timestamp_nanosec()) != 0) {
|
||||||
verbose(VERB_ALGO, "doq: could not verify retry token "
|
verbose(VERB_ALGO, "doq: could not verify retry token "
|
||||||
"from %s %s", host, port);
|
"from %s %s", host, port);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1936,13 +1931,11 @@ doq_verify_token(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
struct ngtcp2_pkt_hd* hd)
|
struct ngtcp2_pkt_hd* hd)
|
||||||
{
|
{
|
||||||
char host[256], port[32];
|
char host[256], port[32];
|
||||||
ngtcp2_tstamp ts;
|
|
||||||
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
if(!doq_print_addr_port(&paddr->addr, paddr->addrlen, host,
|
||||||
sizeof(host), port, sizeof(port))) {
|
sizeof(host), port, sizeof(port))) {
|
||||||
log_err("doq_verify_token failed");
|
log_err("doq_verify_token failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ts = doq_get_timestamp_nanosec();
|
|
||||||
verbose(VERB_ALGO, "doq: verifying token from %s %s", host, port);
|
verbose(VERB_ALGO, "doq: verifying token from %s %s", host, port);
|
||||||
if(ngtcp2_crypto_verify_regular_token(
|
if(ngtcp2_crypto_verify_regular_token(
|
||||||
#ifdef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
|
#ifdef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
|
||||||
@@ -1952,7 +1945,7 @@ doq_verify_token(struct comm_point* c, struct doq_pkt_addr* paddr,
|
|||||||
#endif
|
#endif
|
||||||
c->doq_socket->static_secret, c->doq_socket->static_secret_len,
|
c->doq_socket->static_secret, c->doq_socket->static_secret_len,
|
||||||
(void*)&paddr->addr, paddr->addrlen, 3600*NGTCP2_SECONDS,
|
(void*)&paddr->addr, paddr->addrlen, 3600*NGTCP2_SECONDS,
|
||||||
ts) != 0) {
|
doq_get_timestamp_nanosec()) != 0) {
|
||||||
verbose(VERB_ALGO, "doq: could not verify token from %s %s",
|
verbose(VERB_ALGO, "doq: could not verify token from %s %s",
|
||||||
host, port);
|
host, port);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2179,6 +2172,7 @@ doq_pickup_timer(struct comm_point* c)
|
|||||||
{
|
{
|
||||||
struct doq_timer* t;
|
struct doq_timer* t;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
ngtcp2_tstamp ts = 0;
|
||||||
int have_time = 0;
|
int have_time = 0;
|
||||||
memset(&tv, 0, sizeof(tv));
|
memset(&tv, 0, sizeof(tv));
|
||||||
|
|
||||||
@@ -2188,27 +2182,24 @@ doq_pickup_timer(struct comm_point* c)
|
|||||||
t->worker_doq_socket == c->doq_socket) {
|
t->worker_doq_socket == c->doq_socket) {
|
||||||
/* pick up this element */
|
/* pick up this element */
|
||||||
t->worker_doq_socket = c->doq_socket;
|
t->worker_doq_socket = c->doq_socket;
|
||||||
|
memcpy(&tv, &t->time_real, sizeof(tv));
|
||||||
|
ts = t->time_mono;
|
||||||
have_time = 1;
|
have_time = 1;
|
||||||
memcpy(&tv, &t->time, sizeof(tv));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&c->doq_socket->table->lock);
|
lock_rw_unlock(&c->doq_socket->table->lock);
|
||||||
|
c->doq_socket->marked_time = ts;
|
||||||
if(have_time) {
|
if(have_time) {
|
||||||
struct timeval rel;
|
struct timeval rel;
|
||||||
timeval_subtract(&rel, &tv, c->doq_socket->now_tv);
|
timeval_subtract(&rel, &tv, c->doq_socket->now_tv);
|
||||||
comm_timer_set(c->doq_socket->timer, &rel);
|
comm_timer_set(c->doq_socket->timer, &rel);
|
||||||
memcpy(&c->doq_socket->marked_time, &tv,
|
|
||||||
sizeof(c->doq_socket->marked_time));
|
|
||||||
verbose(VERB_ALGO, "doq pickup timer at %d.%6.6d in %d.%6.6d",
|
verbose(VERB_ALGO, "doq pickup timer at %d.%6.6d in %d.%6.6d",
|
||||||
(int)tv.tv_sec, (int)tv.tv_usec, (int)rel.tv_sec,
|
(int)tv.tv_sec, (int)tv.tv_usec, (int)rel.tv_sec,
|
||||||
(int)rel.tv_usec);
|
(int)rel.tv_usec);
|
||||||
} else {
|
} else {
|
||||||
if(comm_timer_is_set(c->doq_socket->timer))
|
if(comm_timer_is_set(c->doq_socket->timer))
|
||||||
comm_timer_disable(c->doq_socket->timer);
|
comm_timer_disable(c->doq_socket->timer);
|
||||||
memset(&c->doq_socket->marked_time, 0,
|
|
||||||
sizeof(c->doq_socket->marked_time));
|
|
||||||
verbose(VERB_ALGO, "doq timer disabled");
|
verbose(VERB_ALGO, "doq timer disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2221,13 +2212,14 @@ doq_done_setup_timer_and_write(struct comm_point* c, struct doq_conn* conn)
|
|||||||
uint8_t cid[NGTCP2_MAX_CIDLEN];
|
uint8_t cid[NGTCP2_MAX_CIDLEN];
|
||||||
rbnode_type* node;
|
rbnode_type* node;
|
||||||
struct timeval new_tv;
|
struct timeval new_tv;
|
||||||
|
ngtcp2_tstamp new_ts;
|
||||||
int write_change = 0, timer_change = 0;
|
int write_change = 0, timer_change = 0;
|
||||||
|
|
||||||
/* No longer in callbacks, so the pointer to doq_socket is back
|
/* No longer in callbacks, so the pointer to doq_socket is back
|
||||||
* to NULL. */
|
* to NULL. */
|
||||||
conn->doq_socket = NULL;
|
conn->doq_socket = NULL;
|
||||||
|
|
||||||
if(doq_conn_check_timer(conn, &new_tv))
|
if(doq_conn_check_timer(conn, &new_tv, &new_ts))
|
||||||
timer_change = 1;
|
timer_change = 1;
|
||||||
if( (conn->write_interest && !conn->on_write_list) ||
|
if( (conn->write_interest && !conn->on_write_list) ||
|
||||||
(!conn->write_interest && conn->on_write_list))
|
(!conn->write_interest && conn->on_write_list))
|
||||||
@@ -2273,7 +2265,7 @@ doq_done_setup_timer_and_write(struct comm_point* c, struct doq_conn* conn)
|
|||||||
}
|
}
|
||||||
if(timer_change) {
|
if(timer_change) {
|
||||||
doq_timer_set(c->doq_socket->table, &conn->timer,
|
doq_timer_set(c->doq_socket->table, &conn->timer,
|
||||||
c->doq_socket, &new_tv);
|
c->doq_socket, &new_tv, new_ts);
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&c->doq_socket->table->lock);
|
lock_rw_unlock(&c->doq_socket->table->lock);
|
||||||
lock_basic_unlock(&conn->lock);
|
lock_basic_unlock(&conn->lock);
|
||||||
@@ -2437,7 +2429,7 @@ doq_write_blocked_pkt(struct comm_point* c)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** doq find a timer that timeouted and return the conn, locked. */
|
/** doq find a timer that timed out and return the conn, locked. */
|
||||||
static struct doq_conn*
|
static struct doq_conn*
|
||||||
doq_timer_timeout_conn(struct doq_server_socket* doq_socket)
|
doq_timer_timeout_conn(struct doq_server_socket* doq_socket)
|
||||||
{
|
{
|
||||||
@@ -2450,7 +2442,7 @@ doq_timer_timeout_conn(struct doq_server_socket* doq_socket)
|
|||||||
conn = t->conn;
|
conn = t->conn;
|
||||||
|
|
||||||
/* If now < timer then no further timeouts in tree. */
|
/* If now < timer then no further timeouts in tree. */
|
||||||
if(timeval_smaller(doq_socket->now_tv, &t->time)) {
|
if(timeval_smaller(doq_socket->now_tv, &t->time_real)) {
|
||||||
lock_rw_unlock(&doq_socket->table->lock);
|
lock_rw_unlock(&doq_socket->table->lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -2473,11 +2465,11 @@ doq_timer_erase_marker(struct doq_server_socket* doq_socket)
|
|||||||
{
|
{
|
||||||
struct doq_timer* t;
|
struct doq_timer* t;
|
||||||
lock_rw_wrlock(&doq_socket->table->lock);
|
lock_rw_wrlock(&doq_socket->table->lock);
|
||||||
t = doq_timer_find_time(doq_socket->table, &doq_socket->marked_time);
|
t = doq_timer_find_time(doq_socket->table, doq_socket->marked_time);
|
||||||
if(t && t->worker_doq_socket == doq_socket)
|
if(t && t->worker_doq_socket == doq_socket)
|
||||||
t->worker_doq_socket = NULL;
|
t->worker_doq_socket = NULL;
|
||||||
lock_rw_unlock(&doq_socket->table->lock);
|
lock_rw_unlock(&doq_socket->table->lock);
|
||||||
memset(&doq_socket->marked_time, 0, sizeof(doq_socket->marked_time));
|
doq_socket->marked_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2784,7 +2776,7 @@ doq_server_socket_create(struct doq_table* table, struct ub_randstate* rnd,
|
|||||||
free(doq_socket);
|
free(doq_socket);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(&doq_socket->marked_time, 0, sizeof(doq_socket->marked_time));
|
doq_socket->marked_time = 0;
|
||||||
comm_base_timept(base, &doq_socket->now_tt, &doq_socket->now_tv);
|
comm_base_timept(base, &doq_socket->now_tt, &doq_socket->now_tv);
|
||||||
doq_socket->cfg = cfg;
|
doq_socket->cfg = cfg;
|
||||||
return doq_socket;
|
return doq_socket;
|
||||||
@@ -3241,7 +3233,7 @@ static void http2_stream_delete(struct http2_session* h2_session,
|
|||||||
{
|
{
|
||||||
if(h2_stream->mesh_state) {
|
if(h2_stream->mesh_state) {
|
||||||
mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state,
|
mesh_state_remove_reply(h2_stream->mesh, h2_stream->mesh_state,
|
||||||
h2_session->c, h2_stream);
|
h2_session->c, h2_stream, NULL);
|
||||||
h2_stream->mesh_state = NULL;
|
h2_stream->mesh_state = NULL;
|
||||||
}
|
}
|
||||||
http2_req_stream_clear(h2_stream);
|
http2_req_stream_clear(h2_stream);
|
||||||
@@ -6784,7 +6776,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
|
|||||||
log_assert(repinfo && repinfo->c);
|
log_assert(repinfo && repinfo->c);
|
||||||
#ifdef USE_DNSCRYPT
|
#ifdef USE_DNSCRYPT
|
||||||
buffer = repinfo->c->dnscrypt_buffer;
|
buffer = repinfo->c->dnscrypt_buffer;
|
||||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
if(!dnsc_handle_uncurved_request(repinfo,
|
||||||
|
repinfo->c->tcp_req_info?
|
||||||
|
repinfo->c->tcp_req_info->spool_buffer:repinfo->c->buffer)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
+5
-1
@@ -189,6 +189,8 @@ struct comm_reply {
|
|||||||
/** port number for doq */
|
/** port number for doq */
|
||||||
int doq_srcport;
|
int doq_srcport;
|
||||||
#endif /* HAVE_NGTCP2 */
|
#endif /* HAVE_NGTCP2 */
|
||||||
|
/** The doq stream to register mesh states to. */
|
||||||
|
struct doq_stream* doq_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1095,8 +1097,10 @@ struct doq_server_socket {
|
|||||||
struct doq_pkt_addr* blocked_paddr;
|
struct doq_pkt_addr* blocked_paddr;
|
||||||
/** timer for this worker on this comm_point to wait on. */
|
/** timer for this worker on this comm_point to wait on. */
|
||||||
struct comm_timer* timer;
|
struct comm_timer* timer;
|
||||||
|
#ifdef HAVE_NGTCP2
|
||||||
/** the timer that is marked by the doq_socket as waited on. */
|
/** the timer that is marked by the doq_socket as waited on. */
|
||||||
struct timeval marked_time;
|
ngtcp2_tstamp marked_time;
|
||||||
|
#endif
|
||||||
/** the current time for use by time functions, time_t. */
|
/** the current time for use by time functions, time_t. */
|
||||||
time_t* now_tt;
|
time_t* now_tt;
|
||||||
/** the current time for use by time functions, timeval. */
|
/** the current time for use by time functions, timeval. */
|
||||||
|
|||||||
@@ -1107,6 +1107,7 @@ canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
|
|||||||
{
|
{
|
||||||
uint8_t* datstart = sldns_buffer_current(buf)-len+2;
|
uint8_t* datstart = sldns_buffer_current(buf)-len+2;
|
||||||
uint8_t* datend = sldns_buffer_current(buf);
|
uint8_t* datend = sldns_buffer_current(buf);
|
||||||
|
size_t firstlen;
|
||||||
switch(ntohs(rrset->rk.type)) {
|
switch(ntohs(rrset->rk.type)) {
|
||||||
case LDNS_RR_TYPE_NXT:
|
case LDNS_RR_TYPE_NXT:
|
||||||
case LDNS_RR_TYPE_NS:
|
case LDNS_RR_TYPE_NS:
|
||||||
@@ -1126,8 +1127,9 @@ canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
|
|||||||
case LDNS_RR_TYPE_SOA:
|
case LDNS_RR_TYPE_SOA:
|
||||||
/* two names after another */
|
/* two names after another */
|
||||||
canon_dname_tolower(datstart, datend);
|
canon_dname_tolower(datstart, datend);
|
||||||
canon_dname_tolower(datstart +
|
firstlen = dname_valid(datstart, len-2);
|
||||||
dname_valid(datstart, len-2), datend);
|
if(firstlen && firstlen < len-2)
|
||||||
|
canon_dname_tolower(datstart + firstlen, datend);
|
||||||
return;
|
return;
|
||||||
case LDNS_RR_TYPE_RT:
|
case LDNS_RR_TYPE_RT:
|
||||||
case LDNS_RR_TYPE_AFSDB:
|
case LDNS_RR_TYPE_AFSDB:
|
||||||
@@ -1154,8 +1156,9 @@ canonicalize_rdata(sldns_buffer* buf, struct ub_packed_rrset_key* rrset,
|
|||||||
return;
|
return;
|
||||||
datstart += 2;
|
datstart += 2;
|
||||||
canon_dname_tolower(datstart, datend);
|
canon_dname_tolower(datstart, datend);
|
||||||
canon_dname_tolower(datstart +
|
firstlen = dname_valid(datstart, len-2-2);
|
||||||
dname_valid(datstart, len-2-2), datend);
|
if(firstlen && firstlen < len-2-2)
|
||||||
|
canon_dname_tolower(datstart + firstlen, datend);
|
||||||
return;
|
return;
|
||||||
case LDNS_RR_TYPE_NAPTR:
|
case LDNS_RR_TYPE_NAPTR:
|
||||||
if(len < 2+4)
|
if(len < 2+4)
|
||||||
@@ -1681,6 +1684,13 @@ dnskey_verify_rrset_sig(struct regional* region, sldns_buffer* buf,
|
|||||||
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
||||||
return sec_status_bogus;
|
return sec_status_bogus;
|
||||||
}
|
}
|
||||||
|
if((int)sig[2+3] < dname_signame_label_count(signer)) {
|
||||||
|
verbose(VERB_QUERY, "verify: RRSIG label count too low for signer");
|
||||||
|
*reason = "signature labelcount lower than signature signer";
|
||||||
|
if(reason_bogus)
|
||||||
|
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
|
||||||
|
return sec_status_bogus;
|
||||||
|
}
|
||||||
|
|
||||||
/* original ttl, always ok */
|
/* original ttl, always ok */
|
||||||
|
|
||||||
|
|||||||
+13
-4
@@ -157,7 +157,7 @@ val_classify_response(uint16_t query_flags, struct query_info* origqinf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Get signer name from RRSIG */
|
/** Get signer name from RRSIG */
|
||||||
static void
|
void
|
||||||
rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname, size_t* slen)
|
rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname, size_t* slen)
|
||||||
{
|
{
|
||||||
/* RRSIG rdata is not allowed to be compressed, it is stored
|
/* RRSIG rdata is not allowed to be compressed, it is stored
|
||||||
@@ -439,10 +439,15 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||||||
* only improves security status
|
* only improves security status
|
||||||
* and bogus is set only once, even if we rechecked the status */
|
* and bogus is set only once, even if we rechecked the status */
|
||||||
if(sec > d->security) {
|
if(sec > d->security) {
|
||||||
|
int wc_expanded = 0;
|
||||||
d->security = sec;
|
d->security = sec;
|
||||||
if(sec == sec_status_secure)
|
if(sec == sec_status_secure) {
|
||||||
|
uint8_t* wc = NULL;
|
||||||
|
size_t wclen = 0;
|
||||||
d->trust = rrset_trust_validated;
|
d->trust = rrset_trust_validated;
|
||||||
else if(sec == sec_status_bogus) {
|
if(val_rrset_wildcard(rrset, &wc, &wclen) && wc)
|
||||||
|
wc_expanded = 1;
|
||||||
|
} else if(sec == sec_status_bogus) {
|
||||||
size_t i;
|
size_t i;
|
||||||
/* update ttl for rrset to fixed value. */
|
/* update ttl for rrset to fixed value. */
|
||||||
d->ttl = ve->bogus_ttl;
|
d->ttl = ve->bogus_ttl;
|
||||||
@@ -455,7 +460,11 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||||||
lock_basic_unlock(&ve->bogus_lock);
|
lock_basic_unlock(&ve->bogus_lock);
|
||||||
}
|
}
|
||||||
/* if status updated - store in cache for reuse */
|
/* if status updated - store in cache for reuse */
|
||||||
rrset_update_sec_status(env->rrset_cache, rrset, *env->now);
|
/* For a wildcard rrset, that is secure, do not store this
|
||||||
|
* into the cache, because it changes proofs around the
|
||||||
|
* item. */
|
||||||
|
if(!wc_expanded)
|
||||||
|
rrset_update_sec_status(env->rrset_cache, rrset, *env->now);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sec;
|
return sec;
|
||||||
|
|||||||
@@ -448,4 +448,8 @@ struct dns_msg* val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen,
|
|||||||
int derive_cname_from_dname(struct ub_packed_rrset_key* cname,
|
int derive_cname_from_dname(struct ub_packed_rrset_key* cname,
|
||||||
struct ub_packed_rrset_key* dname, uint8_t* out, size_t outlen);
|
struct ub_packed_rrset_key* dname, uint8_t* out, size_t outlen);
|
||||||
|
|
||||||
|
/** Get signer name from RRSIG, sname is NULL if malformed. */
|
||||||
|
void rrsig_get_signer(uint8_t* data, size_t len, uint8_t** sname,
|
||||||
|
size_t* slen);
|
||||||
|
|
||||||
#endif /* VALIDATOR_VAL_UTILS_H */
|
#endif /* VALIDATOR_VAL_UTILS_H */
|
||||||
|
|||||||
+56
-3
@@ -520,6 +520,14 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
|||||||
/* add our blacklist to the query blacklist */
|
/* add our blacklist to the query blacklist */
|
||||||
sock_list_merge(&(*newq)->blacklist, (*newq)->region,
|
sock_list_merge(&(*newq)->blacklist, (*newq)->region,
|
||||||
vq->chain_blacklist);
|
vq->chain_blacklist);
|
||||||
|
/* start its global quota counter where this one is. */
|
||||||
|
if(qstate->global_quota_reached >
|
||||||
|
(*newq)->global_quota_reached) {
|
||||||
|
(*newq)->global_quota_started =
|
||||||
|
qstate->global_quota_reached;
|
||||||
|
(*newq)->global_quota_reached =
|
||||||
|
qstate->global_quota_reached;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
qstate->ext_state[id] = module_wait_subquery;
|
qstate->ext_state[id] = module_wait_subquery;
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1069,7 +1077,14 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
|||||||
uint8_t* wc = NULL;
|
uint8_t* wc = NULL;
|
||||||
size_t wl;
|
size_t wl;
|
||||||
int wc_cached = 0;
|
int wc_cached = 0;
|
||||||
|
int wc_to_cache = 0;
|
||||||
|
uint8_t* cache_wc = NULL;
|
||||||
|
size_t cache_wl = 0;
|
||||||
|
struct ub_packed_rrset_key* cache_s = NULL;
|
||||||
int wc_NSEC_ok = 0;
|
int wc_NSEC_ok = 0;
|
||||||
|
/* This is used to update the RRset cache, with the combination
|
||||||
|
* of the dname expansion and this wildcard, for security status. */
|
||||||
|
struct ub_packed_rrset_key* wc_rrset = NULL;
|
||||||
int nsec3s_seen = 0;
|
int nsec3s_seen = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
struct ub_packed_rrset_key* s;
|
struct ub_packed_rrset_key* s;
|
||||||
@@ -1088,14 +1103,20 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
|||||||
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
||||||
chase_reply->security = sec_status_bogus;
|
chase_reply->security = sec_status_bogus;
|
||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
|
if(wc_rrset)
|
||||||
|
((struct packed_rrset_data*)wc_rrset->
|
||||||
|
entry.data)->security = sec_status_bogus;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(wc && !wc_cached && env->cfg->aggressive_nsec) {
|
if(wc && !wc_cached && env->cfg->aggressive_nsec) {
|
||||||
rrset_cache_update_wildcard(env->rrset_cache, s, wc, wl,
|
/* Postpone cache adjust until proof has succeeded. */
|
||||||
env->alloc, *env->now);
|
wc_to_cache = 1;
|
||||||
|
cache_wc = wc;
|
||||||
|
cache_wl = wl;
|
||||||
|
cache_s = s;
|
||||||
wc_cached = 1;
|
wc_cached = 1;
|
||||||
}
|
}
|
||||||
|
if(wc) wc_rrset = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate the AUTHORITY section as well - this will generally be
|
/* validate the AUTHORITY section as well - this will generally be
|
||||||
@@ -1152,8 +1173,15 @@ validate_positive_response(struct module_env* env, struct val_env* ve,
|
|||||||
"did not exist");
|
"did not exist");
|
||||||
chase_reply->security = sec_status_bogus;
|
chase_reply->security = sec_status_bogus;
|
||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
|
if(wc_rrset)
|
||||||
|
((struct packed_rrset_data*)wc_rrset->
|
||||||
|
entry.data)->security = sec_status_bogus;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(wc_to_cache) {
|
||||||
|
rrset_cache_update_wildcard(env->rrset_cache, cache_s,
|
||||||
|
cache_wc, cache_wl, env->alloc, *env->now);
|
||||||
|
}
|
||||||
|
|
||||||
verbose(VERB_ALGO, "Successfully validated positive response");
|
verbose(VERB_ALGO, "Successfully validated positive response");
|
||||||
chase_reply->security = sec_status_secure;
|
chase_reply->security = sec_status_secure;
|
||||||
@@ -1553,6 +1581,16 @@ validate_any_response(struct module_env* env, struct val_env* ve,
|
|||||||
"did not exist");
|
"did not exist");
|
||||||
chase_reply->security = sec_status_bogus;
|
chase_reply->security = sec_status_bogus;
|
||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
|
/* Make the expanded name and wildcard RRSIG rrsets bogus */
|
||||||
|
for(i=0; i<chase_reply->an_numrrsets; i++) {
|
||||||
|
uint8_t* cwc = NULL;
|
||||||
|
size_t cwl = 0;
|
||||||
|
s = chase_reply->rrsets[i];
|
||||||
|
if(val_rrset_wildcard(s, &cwc, &cwl) && cwc) {
|
||||||
|
((struct packed_rrset_data*)s->
|
||||||
|
entry.data)->security = sec_status_bogus;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1590,6 +1628,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
|||||||
uint8_t* wc = NULL;
|
uint8_t* wc = NULL;
|
||||||
size_t wl;
|
size_t wl;
|
||||||
int wc_NSEC_ok = 0;
|
int wc_NSEC_ok = 0;
|
||||||
|
/* This is used to update the RRset cache, with the combination
|
||||||
|
* of the dname expansion and this wildcard, for security status. */
|
||||||
|
struct ub_packed_rrset_key* wc_rrset = NULL;
|
||||||
int nsec3s_seen = 0;
|
int nsec3s_seen = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
struct ub_packed_rrset_key* s;
|
struct ub_packed_rrset_key* s;
|
||||||
@@ -1610,6 +1651,7 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
|||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(wc) wc_rrset = s;
|
||||||
|
|
||||||
/* Refuse wildcarded DNAMEs rfc 4597.
|
/* Refuse wildcarded DNAMEs rfc 4597.
|
||||||
* Do not follow a wildcarded DNAME because
|
* Do not follow a wildcarded DNAME because
|
||||||
@@ -1621,6 +1663,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
|||||||
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
|
||||||
chase_reply->security = sec_status_bogus;
|
chase_reply->security = sec_status_bogus;
|
||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
|
if(wc_rrset)
|
||||||
|
((struct packed_rrset_data*)wc_rrset->
|
||||||
|
entry.data)->security = sec_status_bogus;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1685,6 +1730,9 @@ validate_cname_response(struct module_env* env, struct val_env* ve,
|
|||||||
"did not exist");
|
"did not exist");
|
||||||
chase_reply->security = sec_status_bogus;
|
chase_reply->security = sec_status_bogus;
|
||||||
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
update_reason_bogus(chase_reply, LDNS_EDE_DNSSEC_BOGUS);
|
||||||
|
if(wc_rrset)
|
||||||
|
((struct packed_rrset_data*)wc_rrset->
|
||||||
|
entry.data)->security = sec_status_bogus;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3565,6 +3613,11 @@ val_inform_super(struct module_qstate* qstate, int id,
|
|||||||
verbose(VERB_ALGO, "super: has no validator state");
|
verbose(VERB_ALGO, "super: has no validator state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* Pick up the global quota limit from the subquery. */
|
||||||
|
if(qstate->global_quota_reached > qstate->global_quota_started) {
|
||||||
|
super->global_quota_reached += qstate->global_quota_reached -
|
||||||
|
qstate->global_quota_started;
|
||||||
|
}
|
||||||
if(vq->wait_prime_ta) {
|
if(vq->wait_prime_ta) {
|
||||||
vq->wait_prime_ta = 0;
|
vq->wait_prime_ta = 0;
|
||||||
process_prime_response(super, vq, id, qstate->return_rcode,
|
process_prime_response(super, vq, id, qstate->return_rcode,
|
||||||
|
|||||||
Reference in New Issue
Block a user