summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2016-09-27 21:11:07 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2016-09-27 21:11:07 +0000
commit27c2fff0f2fef695b0599fc3931cacfc16376e88 (patch)
treeb2599c622858ea78bd8237ce2ee38b62725dabf9 /daemon
parenta6533d88996e7570cf04db0d99b6012d25a953d3 (diff)
Notes
Diffstat (limited to 'daemon')
-rw-r--r--daemon/acl_list.c250
-rw-r--r--daemon/acl_list.h29
-rw-r--r--daemon/daemon.c23
-rw-r--r--daemon/remote.c50
-rw-r--r--daemon/remote.h4
-rw-r--r--daemon/unbound.c15
-rw-r--r--daemon/worker.c12
7 files changed, 350 insertions, 33 deletions
diff --git a/daemon/acl_list.c b/daemon/acl_list.c
index 84d099ca5092..d09b46e5e046 100644
--- a/daemon/acl_list.c
+++ b/daemon/acl_list.c
@@ -45,6 +45,8 @@
#include "util/log.h"
#include "util/config_file.h"
#include "util/net_help.h"
+#include "services/localzone.h"
+#include "sldns/str2wire.h"
struct acl_list*
acl_list_create(void)
@@ -71,21 +73,21 @@ acl_list_delete(struct acl_list* acl)
}
/** insert new address into acl_list structure */
-static int
+static struct acl_addr*
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen, int net, enum acl_access control,
int complain_duplicates)
{
- struct acl_addr* node = regional_alloc(acl->region,
+ struct acl_addr* node = regional_alloc_zero(acl->region,
sizeof(struct acl_addr));
if(!node)
- return 0;
+ return NULL;
node->control = control;
if(!addr_tree_insert(&acl->tree, &node->node, addr, addrlen, net)) {
if(complain_duplicates)
verbose(VERB_QUERY, "duplicate acl address ignored.");
}
- return 1;
+ return node;
}
/** apply acl_list string */
@@ -125,6 +127,156 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
return 1;
}
+/** find or create node (NULL on parse or error) */
+static struct acl_addr*
+acl_find_or_create(struct acl_list* acl, const char* str)
+{
+ struct acl_addr* node;
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+ if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
+ log_err("cannot parse netblock: %s", str);
+ return NULL;
+ }
+ /* find or create node */
+ if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
+ addrlen, net))) {
+ /* create node, type 'allow' since otherwise tags are
+ * pointless, can override with specific access-control: cfg */
+ if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
+ addrlen, net, acl_allow, 1))) {
+ log_err("out of memory");
+ return NULL;
+ }
+ }
+ return node;
+}
+
+/** apply acl_tag string */
+static int
+acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
+ size_t bitmaplen)
+{
+ struct acl_addr* node;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ node->taglen = bitmaplen;
+ node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
+ if(!node->taglist) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
+/** apply acl_tag_action string */
+static int
+acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* action)
+{
+ struct acl_addr* node;
+ int tagid;
+ enum localzone_type t;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_actions) {
+ node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
+ sizeof(*node->tag_actions)*cfg->num_tags);
+ if(!node->tag_actions) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_actions_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_actions_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+ if(!local_zone_str2type(action, &t)) {
+ log_err("cannot parse access control action type: %s %s %s",
+ str, tag, action);
+ return 0;
+ }
+ node->tag_actions[tagid] = (uint8_t)t;
+ return 1;
+}
+
+/** check wire data parse */
+static int
+check_data(const char* data)
+{
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len = sizeof(rr);
+ int res;
+ snprintf(buf, sizeof(buf), "%s %s", "example.com.", data);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL, 0,
+ NULL, 0);
+ if(res == 0)
+ return 1;
+ log_err("rr data [char %d] parse error %s",
+ (int)LDNS_WIREPARSE_OFFSET(res)-13,
+ sldns_get_errorstr_parse(res));
+ return 0;
+}
+
+/** apply acl_tag_data string */
+static int
+acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
+ const char* str, const char* tag, const char* data)
+{
+ struct acl_addr* node;
+ int tagid;
+ char* dupdata;
+ if(!(node=acl_find_or_create(acl, str)))
+ return 0;
+ /* allocate array if not yet */
+ if(!node->tag_datas) {
+ node->tag_datas = (struct config_strlist**)regional_alloc_zero(
+ acl->region, sizeof(*node->tag_datas)*cfg->num_tags);
+ if(!node->tag_datas) {
+ log_err("out of memory");
+ return 0;
+ }
+ node->tag_datas_size = (size_t)cfg->num_tags;
+ }
+ /* parse tag */
+ if((tagid=find_tag_id(cfg, tag)) == -1) {
+ log_err("cannot parse tag (define-tag it): %s %s", str, tag);
+ return 0;
+ }
+ if((size_t)tagid >= node->tag_datas_size) {
+ log_err("tagid too large for array %s %s", str, tag);
+ return 0;
+ }
+
+ /* check data? */
+ if(!check_data(data)) {
+ log_err("cannot parse access-control-tag data: %s %s '%s'",
+ str, tag, data);
+ return 0;
+ }
+
+ dupdata = regional_strdup(acl->region, data);
+ if(!dupdata) {
+ log_err("out of memory");
+ return 0;
+ }
+ if(!cfg_region_strlist_insert(acl->region,
+ &(node->tag_datas[tagid]), dupdata)) {
+ log_err("out of memory");
+ return 0;
+ }
+ return 1;
+}
+
/** read acl_list config */
static int
read_acl_list(struct acl_list* acl, struct config_file* cfg)
@@ -138,6 +290,77 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
return 1;
}
+/** read acl tags config */
+static int
+read_acl_tags(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_strbytelist* np, *p = cfg->acl_tags;
+ cfg->acl_tags = NULL;
+ while(p) {
+ log_assert(p->str && p->str2);
+ if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) {
+ config_del_strbytelist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag actions config */
+static int
+read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_actions;
+ cfg->acl_tag_actions = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
+ p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
+/** read acl tag datas config */
+static int
+read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
+{
+ struct config_str3list* p, *np;
+ p = cfg->acl_tag_datas;
+ cfg->acl_tag_datas = NULL;
+ while(p) {
+ log_assert(p->str && p->str2 && p->str3);
+ if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) {
+ config_deltrplstrlist(p);
+ return 0;
+ }
+ /* free the items as we go to free up memory */
+ np = p->next;
+ free(p->str);
+ free(p->str2);
+ free(p->str3);
+ free(p);
+ p = np;
+ }
+ return 1;
+}
+
int
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
{
@@ -145,6 +368,12 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
addr_tree_init(&acl->tree);
if(!read_acl_list(acl, cfg))
return 0;
+ if(!read_acl_tags(acl, cfg))
+ return 0;
+ if(!read_acl_tag_actions(acl, cfg))
+ return 0;
+ if(!read_acl_tag_datas(acl, cfg))
+ return 0;
/* insert defaults, with '0' to ignore them if they are duplicates */
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
return 0;
@@ -163,13 +392,18 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
}
enum acl_access
-acl_list_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+acl_get_control(struct acl_addr* acl)
+{
+ if(acl) return acl->control;
+ return acl_deny;
+}
+
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
socklen_t addrlen)
{
- struct acl_addr* r = (struct acl_addr*)addr_tree_lookup(&acl->tree,
+ return (struct acl_addr*)addr_tree_lookup(&acl->tree,
addr, addrlen);
- if(r) return r->control;
- return acl_deny;
}
size_t
diff --git a/daemon/acl_list.h b/daemon/acl_list.h
index 2323697d5b84..fc0e9cabf3df 100644
--- a/daemon/acl_list.h
+++ b/daemon/acl_list.h
@@ -87,6 +87,19 @@ struct acl_addr {
struct addr_tree_node node;
/** access control on this netblock */
enum acl_access control;
+ /** tag bitlist */
+ uint8_t* taglist;
+ /** length of the taglist (in bytes) */
+ size_t taglen;
+ /** array per tagnumber of localzonetype(in one byte). NULL if none. */
+ uint8_t* tag_actions;
+ /** size of the tag_actions_array */
+ size_t tag_actions_size;
+ /** array per tagnumber, with per tag a list of rdata strings.
+ * NULL if none. strings are like 'A 127.0.0.1' 'AAAA ::1' */
+ struct config_strlist** tag_datas;
+ /** size of the tag_datas array */
+ size_t tag_datas_size;
};
/**
@@ -110,14 +123,22 @@ void acl_list_delete(struct acl_list* acl);
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
/**
- * Lookup address to see its access control status.
+ * Lookup access control status for acl structure.
+ * @param acl: structure for acl storage.
+ * @return: what to do with message from this address.
+ */
+enum acl_access acl_get_control(struct acl_addr* acl);
+
+/**
+ * Lookup address to see its acl structure
* @param acl: structure for address storage.
* @param addr: address to check
* @param addrlen: length of addr.
- * @return: what to do with message from this address.
+ * @return: acl structure from this address.
*/
-enum acl_access acl_list_lookup(struct acl_list* acl,
- struct sockaddr_storage* addr, socklen_t addrlen);
+struct acl_addr*
+acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
+ socklen_t addrlen);
/**
* Get memory used by acl structure.
diff --git a/daemon/daemon.c b/daemon/daemon.c
index 1036fcde2001..2ed9af8fe66f 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -204,17 +204,29 @@ daemon_init(void)
signal_handling_record();
checklock_start();
#ifdef HAVE_SSL
+# ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
ERR_load_crypto_strings();
+# endif
ERR_load_SSL_strings();
# ifdef USE_GOST
(void)sldns_key_EVP_load_gost_id();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
OpenSSL_add_all_algorithms();
+# else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
/* grab the COMP method ptr because openssl leaks it */
comp_meth = (void*)SSL_COMP_get_compression_methods();
# endif
+# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
+# else
+ (void)OPENSSL_init_ssl(0, NULL);
+# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
fatal_exit("could not init openssl locks");
@@ -404,6 +416,8 @@ daemon_create_workers(struct daemon* daemon)
}
daemon->workers = (struct worker**)calloc((size_t)daemon->num,
sizeof(struct worker*));
+ if(!daemon->workers)
+ fatal_exit("out of memory during daemon init");
if(daemon->cfg->dnstap) {
#ifdef USE_DNSTAP
daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path,
@@ -586,13 +600,12 @@ daemon_cleanup(struct daemon* daemon)
log_thread_set(NULL);
/* clean up caches because
* a) RRset IDs will be recycled after a reload, causing collisions
- * b) validation config can change, thus rrset, msg, keycache clear
- * The infra cache is kept, the timing and edns info is still valid */
+ * b) validation config can change, thus rrset, msg, keycache clear */
slabhash_clear(&daemon->env->rrset_cache->table);
slabhash_clear(daemon->env->msg_cache);
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
- /* key cache is cleared by module desetup during next daemon_init() */
+ /* key cache is cleared by module desetup during next daemon_fork() */
daemon_remote_clear(daemon->rc);
for(i=0; i<daemon->num; i++)
worker_delete(daemon->workers[i]);
@@ -656,8 +669,12 @@ daemon_delete(struct daemon* daemon)
# endif
CONF_modules_free();
# endif
+# ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
+# endif
+# ifdef HAVE_ERR_FREE_STRINGS
ERR_free_strings();
+# endif
# if OPENSSL_VERSION_NUMBER < 0x10100000
RAND_cleanup();
# endif
diff --git a/daemon/remote.c b/daemon/remote.c
index 7690ee8b1875..3fe6650b4ba6 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -46,9 +46,12 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
-#ifndef HEADER_DH_H
+#ifdef HAVE_OPENSSL_DH_H
#include <openssl/dh.h>
#endif
+#ifdef HAVE_OPENSSL_BN_H
+#include <openssl/bn.h>
+#endif
#include <ctype.h>
#include "daemon/remote.h"
@@ -144,7 +147,7 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
* (some openssl versions reject DH that is 'too small', eg. 512).
*/
#ifndef S_SPLINT_S
-DH *get_dh2048()
+static DH *get_dh2048(void)
{
static unsigned char dh2048_p[]={
0xE7,0x36,0x28,0x3B,0xE4,0xC3,0x32,0x1C,0x01,0xC3,0x67,0xD6,
@@ -173,14 +176,31 @@ DH *get_dh2048()
static unsigned char dh2048_g[]={
0x02,
};
- DH *dh;
-
- if ((dh=DH_new()) == NULL) return(NULL);
- dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
- dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
- if ((dh->p == NULL) || (dh->g == NULL))
- { DH_free(dh); return(NULL); }
- return(dh);
+ DH *dh = NULL;
+ BIGNUM *p = NULL, *g = NULL;
+
+ dh = DH_new();
+ p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
+ g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
+ if (!dh || !p || !g)
+ goto err;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
+ dh->p = p;
+ dh->g = g;
+#else
+ if (!DH_set0_pqg(dh, p, NULL, g))
+ goto err;
+#endif
+ return dh;
+err:
+ if (p)
+ BN_free(p);
+ if (g)
+ BN_free(g);
+ if (dh)
+ DH_free(dh);
+ return NULL;
}
#endif /* SPLINT */
@@ -225,6 +245,7 @@ daemon_remote_create(struct config_file* cfg)
/* No certificates are requested */
if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL")) {
log_crypto_err("Failed to set aNULL cipher list");
+ daemon_remote_delete(rc);
return NULL;
}
@@ -233,6 +254,7 @@ daemon_remote_create(struct config_file* cfg)
*/
if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh2048())) {
log_crypto_err("Wanted to set DH param, but failed");
+ daemon_remote_delete(rc);
return NULL;
}
return rc;
@@ -359,8 +381,12 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
if(fd != -1) {
#ifdef HAVE_CHOWN
if (cfg->username && cfg->username[0] &&
- cfg_uid != (uid_t)-1)
- chown(ip, cfg_uid, cfg_gid);
+ cfg_uid != (uid_t)-1) {
+ if(chown(ip, cfg_uid, cfg_gid) == -1)
+ log_err("cannot chown %u.%u %s: %s",
+ (unsigned)cfg_uid, (unsigned)cfg_gid,
+ ip, strerror(errno));
+ }
chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
#else
(void)cfg;
diff --git a/daemon/remote.h b/daemon/remote.h
index b25bfb1af611..190286d474a4 100644
--- a/daemon/remote.h
+++ b/daemon/remote.h
@@ -56,8 +56,8 @@ struct comm_reply;
struct comm_point;
struct daemon_remote;
-/** number of seconds timeout on incoming remote control handshake */
-#define REMOTE_CONTROL_TCP_TIMEOUT 120
+/** number of milliseconds timeout on incoming remote control handshake */
+#define REMOTE_CONTROL_TCP_TIMEOUT 120000
/**
* a busy control command connection, SSL state
diff --git a/daemon/unbound.c b/daemon/unbound.c
index d1de67369827..73e9fcbb6234 100644
--- a/daemon/unbound.c
+++ b/daemon/unbound.c
@@ -93,10 +93,13 @@ void* unbound_start_brk = 0;
#endif
/** print usage. */
-static void usage()
+static void usage(void)
{
const char** m;
const char *evnm="event", *evsys="", *evmethod="";
+ time_t t;
+ struct timeval now;
+ struct ub_event_base* base;
printf("usage: unbound [options]\n");
printf(" start unbound daemon DNS resolver.\n");
printf("-h this help\n");
@@ -110,11 +113,16 @@ static void usage()
printf(" service - used to start from services control panel\n");
#endif
printf("Version %s\n", PACKAGE_VERSION);
- ub_get_event_sys(NULL, &evnm, &evsys, &evmethod);
+ base = ub_default_event_base(0,&t,&now);
+ ub_get_event_sys(base, &evnm, &evsys, &evmethod);
printf("linked libs: %s %s (it uses %s), %s\n",
evnm, evsys, evmethod,
#ifdef HAVE_SSL
+# ifdef SSLEAY_VERSION
SSLeay_version(SSLEAY_VERSION)
+# else
+ OpenSSL_version(OPENSSL_VERSION)
+# endif
#elif defined(HAVE_NSS)
NSS_GetVersion()
#elif defined(HAVE_NETTLE)
@@ -127,6 +135,7 @@ static void usage()
printf("\n");
printf("BSD licensed, see LICENSE in source package for details.\n");
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+ ub_event_base_free(base);
}
#ifndef unbound_testbound
@@ -539,7 +548,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
log_warn("unable to initgroups %s: %s",
cfg->username, strerror(errno));
# endif /* HAVE_INITGROUPS */
+# ifdef HAVE_ENDPWENT
endpwent();
+# endif
#ifdef HAVE_SETRESGID
if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0)
diff --git a/daemon/worker.c b/daemon/worker.c
index 33a6883f9219..70d07ba8e8f7 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -773,6 +773,8 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
+ sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
+ sldns_buffer_flip(c->buffer);
return 1;
}
@@ -804,6 +806,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
struct query_info qinfo;
struct edns_data edns;
enum acl_access acl;
+ struct acl_addr* acladdr;
int rc = 0;
if(error != NETEVENT_NOERROR) {
@@ -816,8 +819,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type,
c->buffer);
#endif
- acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr,
+ acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
repinfo->addrlen);
+ acl = acl_get_control(acladdr);
if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1)
{
if(ret == 1)
@@ -941,7 +945,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
goto send_reply;
}
if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns,
- c->buffer, worker->scratchpad, repinfo)) {
+ c->buffer, worker->scratchpad, repinfo,
+ acladdr->taglist, acladdr->taglen, acladdr->tag_actions,
+ acladdr->tag_actions_size, acladdr->tag_datas,
+ acladdr->tag_datas_size, worker->daemon->cfg->tagname,
+ worker->daemon->cfg->num_tags)) {
regional_free_all(worker->scratchpad);
if(sldns_buffer_limit(c->buffer) == 0) {
comm_point_drop_reply(repinfo);