aboutsummaryrefslogtreecommitdiff
path: root/contrib/unbound/daemon/worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/unbound/daemon/worker.c')
-rw-r--r--contrib/unbound/daemon/worker.c196
1 files changed, 147 insertions, 49 deletions
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index 176abf57d56e..ead20938e172 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -160,9 +160,11 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
+ sizeof(worker->rndstate)
+ regional_get_mem(worker->scratchpad)
+ sizeof(*worker->env.scratch_buffer)
- + sldns_buffer_capacity(worker->env.scratch_buffer)
- + forwards_get_mem(worker->env.fwds)
- + hints_get_mem(worker->env.hints);
+ + sldns_buffer_capacity(worker->env.scratch_buffer);
+ if(worker->daemon->env->fwds)
+ log_info("forwards=%u", (unsigned)forwards_get_mem(worker->env.fwds));
+ if(worker->daemon->env->hints)
+ log_info("hints=%u", (unsigned)hints_get_mem(worker->env.hints));
if(worker->thread_num == 0)
me += acl_list_get_mem(worker->daemon->acl);
if(cur_serv) {
@@ -369,6 +371,84 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
return;
}
+/**
+ * Send fast-reload acknowledgement to the mainthread in one byte.
+ * This signals that this worker has received the previous command.
+ * The worker is waiting if that is after a reload_stop command.
+ * Or the worker has briefly processed the event itself, and in doing so
+ * released data pointers to old config, after a reload_poll command.
+ */
+static void
+worker_send_reload_ack(struct worker* worker)
+{
+ /* If this is clipped to 8 bits because thread_num>255, then that
+ * is not a problem, the receiver counts the number of bytes received.
+ * The number is informative only. */
+ uint8_t c = (uint8_t)worker->thread_num;
+ ssize_t ret;
+ while(1) {
+ ret = send(worker->daemon->fast_reload_thread->commreload[1],
+ (void*)&c, 1, 0);
+ if(ret == -1) {
+ if(
+#ifndef USE_WINSOCK
+ errno == EINTR || errno == EAGAIN
+# ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+# endif
+#else
+ WSAGetLastError() == WSAEINTR ||
+ WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEWOULDBLOCK
+#endif
+ )
+ continue; /* Try again. */
+ log_err("worker reload ack reply: send failed: %s",
+ sock_strerror(errno));
+ break;
+ }
+ break;
+ }
+}
+
+/** stop and wait to resume the worker */
+static void
+worker_stop_and_wait(struct worker* worker)
+{
+ uint8_t* buf = NULL;
+ uint32_t len = 0, cmd;
+ worker_send_reload_ack(worker);
+ /* wait for reload */
+ if(!tube_read_msg(worker->cmd, &buf, &len, 0)) {
+ log_err("worker reload read reply failed");
+ return;
+ }
+ if(len != sizeof(uint32_t)) {
+ log_err("worker reload reply, bad control msg length %d",
+ (int)len);
+ free(buf);
+ return;
+ }
+ cmd = sldns_read_uint32(buf);
+ free(buf);
+ if(cmd == worker_cmd_quit) {
+ /* quit anyway */
+ verbose(VERB_ALGO, "reload reply, control cmd quit");
+ comm_base_exit(worker->base);
+ return;
+ }
+ if(cmd != worker_cmd_reload_start) {
+ log_err("worker reload reply, wrong reply command");
+ }
+ if(worker->daemon->fast_reload_drop_mesh) {
+ verbose(VERB_ALGO, "worker: drop mesh queries after reload");
+ mesh_delete_all(worker->env.mesh);
+ }
+ fast_reload_worker_pickup_changes(worker);
+ worker_send_reload_ack(worker);
+ verbose(VERB_ALGO, "worker resume after reload");
+}
+
void
worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
size_t len, int error, void* arg)
@@ -404,6 +484,15 @@ worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
verbose(VERB_ALGO, "got control cmd remote");
daemon_remote_exec(worker);
break;
+ case worker_cmd_reload_stop:
+ verbose(VERB_ALGO, "got control cmd reload_stop");
+ worker_stop_and_wait(worker);
+ break;
+ case worker_cmd_reload_poll:
+ verbose(VERB_ALGO, "got control cmd reload_poll");
+ fast_reload_worker_pickup_changes(worker);
+ worker_send_reload_ack(worker);
+ break;
default:
log_err("bad command %d", (int)cmd);
break;
@@ -598,7 +687,8 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
return 1;
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
- alias_rrset, 0, worker->scratchpad, az, NULL))
+ alias_rrset, 0, worker->scratchpad, az, NULL,
+ worker->env.views, worker->env.respip_set))
return 0;
/* xxx_deny actions mean dropping the reply, unless the original reply
@@ -659,17 +749,18 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(rep->ttl < timenow) {
/* Check if we need to serve expired now */
if(worker->env.cfg->serve_expired &&
- !worker->env.cfg->serve_expired_client_timeout) {
- if(worker->env.cfg->serve_expired_ttl &&
- rep->serve_expired_ttl < timenow)
- return 0;
- /* Ignore expired failure answers */
- if(FLAGS_GET_RCODE(rep->flags) !=
- LDNS_RCODE_NOERROR &&
- FLAGS_GET_RCODE(rep->flags) !=
- LDNS_RCODE_NXDOMAIN &&
- FLAGS_GET_RCODE(rep->flags) !=
- LDNS_RCODE_YXDOMAIN)
+ /* if serve-expired-client-timeout is set, serve
+ * an expired record without attempting recursion
+ * if the serve_expired_norec_ttl is set for the record
+ * as we know that recursion is currently failing. */
+ (!worker->env.cfg->serve_expired_client_timeout ||
+ timenow < rep->serve_expired_norec_ttl)
+#ifdef USE_CACHEDB
+ && !(worker->env.cachedb_enabled &&
+ worker->env.cfg->cachedb_check_when_serve_expired)
+#endif
+ ) {
+ if(!reply_info_can_answer_expired(rep, timenow))
return 0;
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
return 0;
@@ -758,7 +849,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
} else if(partial_rep &&
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
must_validate, &encode_rep, worker->scratchpad,
- worker->env.auth_zones)) {
+ worker->env.auth_zones, worker->env.views,
+ worker->env.respip_set)) {
goto bail_out;
}
if(encode_rep != rep) {
@@ -1079,7 +1171,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
if(verbosity >= VERB_DETAIL) {
char buf[380];
- char zname[255+1];
+ char zname[LDNS_MAX_DOMAINLEN];
char sr[25];
dname_str(qinfo->qname, zname);
sr[0]=0;
@@ -1410,7 +1502,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
return 0;
}
if(c->dnscrypt && !repinfo->is_dnscrypted) {
- char buf[LDNS_MAX_DOMAINLEN+1];
+ char buf[LDNS_MAX_DOMAINLEN];
/* Check if this is unencrypted and asking for certs */
worker_check_request(c->buffer, worker, &check_result);
if(check_result.value != 0) {
@@ -1454,8 +1546,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*/
if(worker->dtenv.log_client_query_messages) {
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
- log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
- dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer,
+ log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
+ dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer,
((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL));
}
#endif
@@ -1566,7 +1658,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
if((ret=parse_edns_from_query_pkt(
c->buffer, &edns, worker->env.cfg, c, repinfo,
(worker->env.now ? *worker->env.now : time(NULL)),
- worker->scratchpad)) != 0) {
+ worker->scratchpad,
+ worker->daemon->cookie_secrets)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
@@ -1809,7 +1902,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
cinfo_tmp.tag_datas = acladdr->tag_datas;
cinfo_tmp.tag_datas_size = acladdr->tag_datas_size;
cinfo_tmp.view = acladdr->view;
- cinfo_tmp.respip_set = worker->daemon->respip_set;
+ cinfo_tmp.view_name = NULL;
cinfo = &cinfo_tmp;
}
@@ -1841,10 +1934,10 @@ lookup_cache:
* its qname must be that used for cache
* lookup. */
if((worker->env.cfg->prefetch &&
- *worker->env.now >= rep->prefetch_ttl) ||
+ rep->prefetch_ttl <= *worker->env.now) ||
(worker->env.cfg->serve_expired &&
- *worker->env.now > rep->ttl)) {
-
+ rep->ttl < *worker->env.now &&
+ !(*worker->env.now < rep->serve_expired_norec_ttl))) {
time_t leeway = rep->ttl - *worker->env.now;
if(rep->ttl < *worker->env.now)
leeway = 0;
@@ -1943,10 +2036,10 @@ send_reply_rc:
/*
* sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.)
*/
- if(worker->dtenv.log_client_response_messages) {
- log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
+ if(worker->dtenv.log_client_response_messages && rc !=0) {
+ log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
- dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer);
+ dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer);
}
#endif
if(worker->env.cfg->log_replies)
@@ -1961,14 +2054,14 @@ send_reply_rc:
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
- (worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
- c->type);
+ (worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
+ c->type, c->ssl);
} else {
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
- (worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
- c->type);
+ (worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
+ c->type, c->ssl);
}
}
#ifdef USE_DNSCRYPT
@@ -2169,8 +2262,11 @@ worker_init(struct worker* worker, struct config_file *cfg,
: cfg->tcp_idle_timeout,
cfg->harden_large_queries, cfg->http_max_streams,
cfg->http_endpoint, cfg->http_notls_downstream,
- worker->daemon->tcl, worker->daemon->listen_sslctx,
- dtenv, worker_handle_request, worker);
+ worker->daemon->tcl, worker->daemon->listen_dot_sslctx,
+ worker->daemon->listen_doh_sslctx,
+ worker->daemon->listen_quic_sslctx,
+ dtenv, worker->daemon->doq_table, worker->env.rnd,
+ cfg, worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
@@ -2185,7 +2281,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
&worker_alloc_cleanup, worker,
cfg->do_udp || cfg->udp_upstream_without_downstream,
- worker->daemon->connect_sslctx, cfg->delay_close,
+ worker->daemon->connect_dot_sslctx, cfg->delay_close,
cfg->tls_use_sni, dtenv, cfg->udp_connect,
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
cfg->tcp_auth_query_timeout);
@@ -2261,18 +2357,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker_delete(worker);
return 0;
}
- if(!(worker->env.fwds = forwards_create()) ||
- !forwards_apply_cfg(worker->env.fwds, cfg)) {
- log_err("Could not set forward zones");
- worker_delete(worker);
- return 0;
- }
- if(!(worker->env.hints = hints_create()) ||
- !hints_apply_cfg(worker->env.hints, cfg)) {
- log_err("Could not set root or stub hints");
- worker_delete(worker);
- return 0;
- }
/* one probe timer per process -- if we have 5011 anchors */
if(autr_get_num_anchors(worker->env.anchors) > 0
#ifndef THREADS_DISABLED
@@ -2345,8 +2429,6 @@ worker_delete(struct worker* worker)
outside_network_quit_prepare(worker->back);
mesh_delete(worker->env.mesh);
sldns_buffer_free(worker->env.scratch_buffer);
- forwards_delete(worker->env.fwds);
- hints_delete(worker->env.hints);
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);
@@ -2518,3 +2600,19 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
log_assert(0);
}
#endif
+
+#ifdef HAVE_NGTCP2
+void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
+
+#ifdef HAVE_NGTCP2
+void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif