From d433784affd32a879670e66bcf330b2561342f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Fri, 2 Jan 2015 17:31:36 +0000 Subject: import unbound 1.5.0 --- daemon/cachedump.c | 2 +- daemon/daemon.c | 39 +++++-- daemon/daemon.h | 11 ++ daemon/remote.c | 332 ++++++++++++++++++++++++++++++++++++++--------------- daemon/remote.h | 9 -- daemon/stats.c | 13 +++ daemon/stats.h | 11 ++ daemon/unbound.c | 27 +++-- daemon/worker.c | 102 ++++++++++------ daemon/worker.h | 75 ++---------- 10 files changed, 395 insertions(+), 226 deletions(-) (limited to 'daemon') diff --git a/daemon/cachedump.c b/daemon/cachedump.c index 52b3f2d1e011..cf5b1a12c9a7 100644 --- a/daemon/cachedump.c +++ b/daemon/cachedump.c @@ -229,7 +229,7 @@ copy_msg(struct regional* region, struct lruhash_entry* e, sizeof(struct ub_packed_rrset_key*) * rep->rrset_count); if(!*d) return 0; - (*d)->rrsets = (struct ub_packed_rrset_key**)( + (*d)->rrsets = (struct ub_packed_rrset_key**)(void *)( (uint8_t*)(&((*d)->ref[0])) + sizeof(struct rrset_ref) * rep->rrset_count); *k = (struct query_info*)regional_alloc_init(region, diff --git a/daemon/daemon.c b/daemon/daemon.c index aed22c2db7f6..f693a0285a2c 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -109,8 +109,9 @@ int ub_c_lex_destroy(void); static RETSIGTYPE record_sigh(int sig) { #ifdef LIBEVENT_SIGNAL_PROBLEM - verbose(VERB_OPS, "quit on signal, no cleanup and statistics, " - "because installed libevent version is not threadsafe"); + /* cannot log, verbose here because locks may be held */ + /* quit on signal, no cleanup and statistics, + because installed libevent version is not threadsafe */ exit(0); #endif switch(sig) @@ -135,7 +136,8 @@ static RETSIGTYPE record_sigh(int sig) break; #endif default: - log_err("ignoring signal %d", sig); + /* ignoring signal */ + break; } } @@ -256,8 +258,8 @@ daemon_open_shared_ports(struct daemon* daemon) log_assert(daemon); if(daemon->cfg->port != daemon->listening_port) { size_t i; - int reuseport = 0; struct listen_port* p0; + daemon->reuseport = 0; /* free and close old ports */ if(daemon->ports != NULL) { for(i=0; inum_ports; i++) @@ -266,17 +268,17 @@ daemon_open_shared_ports(struct daemon* daemon) daemon->ports = NULL; } /* see if we want to reuseport */ -#if defined(__linux__) && defined(SO_REUSEPORT) +#ifdef SO_REUSEPORT if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0) - reuseport = 1; + daemon->reuseport = 1; #endif /* try to use reuseport */ - p0 = listening_ports_open(daemon->cfg, &reuseport); + p0 = listening_ports_open(daemon->cfg, &daemon->reuseport); if(!p0) { listening_ports_free(p0); return 0; } - if(reuseport) { + if(daemon->reuseport) { /* reuseport was successful, allocate for it */ daemon->num_ports = (size_t)daemon->cfg->num_threads; } else { @@ -290,12 +292,13 @@ daemon_open_shared_ports(struct daemon* daemon) return 0; } daemon->ports[0] = p0; - if(reuseport) { + if(daemon->reuseport) { /* continue to use reuseport */ for(i=1; inum_ports; i++) { if(!(daemon->ports[i]= listening_ports_open(daemon->cfg, - &reuseport)) || !reuseport ) { + &daemon->reuseport)) + || !daemon->reuseport ) { for(i=0; inum_ports; i++) listening_ports_free(daemon->ports[i]); free(daemon->ports); @@ -398,6 +401,17 @@ daemon_create_workers(struct daemon* daemon) daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); daemon->workers = (struct worker**)calloc((size_t)daemon->num, sizeof(struct worker*)); + if(daemon->cfg->dnstap) { +#ifdef USE_DNSTAP + daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path, + (unsigned int)daemon->num); + if (!daemon->dtenv) + fatal_exit("dt_create failed"); + dt_apply_cfg(daemon->dtenv, daemon->cfg); +#else + fatal_exit("dnstap enabled in config but not built with dnstap support"); +#endif + } for(i=0; inum; i++) { if(!(daemon->workers[i] = worker_create(daemon, i, shufport+numport*i/daemon->num, @@ -448,7 +462,7 @@ thread_start(void* arg) tube_close_write(worker->cmd); close_other_pipes(worker->daemon, worker->thread_num); #endif -#if defined(__linux__) && defined(SO_REUSEPORT) +#ifdef SO_REUSEPORT if(worker->daemon->cfg->so_reuseport) port_num = worker->thread_num; else @@ -582,6 +596,9 @@ daemon_cleanup(struct daemon* daemon) free(daemon->workers); daemon->workers = NULL; daemon->num = 0; +#ifdef USE_DNSTAP + dt_delete(daemon->dtenv); +#endif daemon->cfg = NULL; } diff --git a/daemon/daemon.h b/daemon/daemon.h index 855b0d344086..86ddab1df739 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -59,6 +59,11 @@ struct local_zones; struct ub_randstate; struct daemon_remote; +#include "dnstap/dnstap_config.h" +#ifdef USE_DNSTAP +struct dt_env; +#endif + /** * Structure holding worker list. * Holds globally visible information. @@ -77,6 +82,8 @@ struct daemon { struct listen_port** ports; /** size of ports array */ size_t num_ports; + /** reuseport is enabled if true */ + int reuseport; /** port number for remote that has ports opened. */ int rc_port; /** listening ports for remote control */ @@ -107,6 +114,10 @@ struct daemon { struct timeval time_last_stat; /** time when daemon started */ struct timeval time_boot; +#ifdef USE_DNSTAP + /** the dnstap environment master value, copied and changed by threads*/ + struct dt_env* dtenv; +#endif }; /** diff --git a/daemon/remote.c b/daemon/remote.c index 9ff40325fd31..88ea063f21f8 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -38,8 +38,8 @@ * * This file contains the remote control functionality for the daemon. * The remote control can be performed using either the commandline - * unbound-control tool, or a SSLv3/TLS capable web browser. - * The channel is secured using SSLv3 or TLSv1, and certificates. + * unbound-control tool, or a TLS capable web browser. + * The channel is secured using TLSv1, and certificates. * Both the server and the client(control tool) have their own keys. */ #include "config.h" @@ -154,12 +154,17 @@ daemon_remote_create(struct config_file* cfg) free(rc); return NULL; } - /* no SSLv2 because has defects */ + /* no SSLv2, SSLv3 because has defects */ if(!(SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)){ log_crypto_err("could not set SSL_OP_NO_SSLv2"); daemon_remote_delete(rc); return NULL; } + if(!(SSL_CTX_set_options(rc->ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)){ + log_crypto_err("could not set SSL_OP_NO_SSLv3"); + daemon_remote_delete(rc); + return NULL; + } s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1); s_key = fname_after_chroot(cfg->server_key_file, cfg, 1); if(!s_cert || !s_key) { @@ -558,7 +563,7 @@ static char* skipwhite(char* str) { /* EOS \0 is not a space */ - while( isspace(*str) ) + while( isspace((unsigned char)*str) ) str++; return str; } @@ -605,32 +610,32 @@ static int print_stats(SSL* ssl, const char* nm, struct stats_info* s) { struct timeval avg; - if(!ssl_printf(ssl, "%s.num.queries"SQ"%u\n", nm, - (unsigned)s->svr.num_queries)) return 0; - if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%u\n", nm, - (unsigned)(s->svr.num_queries + if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm, + (unsigned long)s->svr.num_queries)) return 0; + if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm, + (unsigned long)(s->svr.num_queries - s->svr.num_queries_missed_cache))) return 0; - if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%u\n", nm, - (unsigned)s->svr.num_queries_missed_cache)) return 0; - if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%u\n", nm, - (unsigned)s->svr.num_queries_prefetch)) return 0; - if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%u\n", nm, - (unsigned)s->mesh_replies_sent)) return 0; + if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%lu\n", nm, + (unsigned long)s->svr.num_queries_missed_cache)) return 0; + if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm, + (unsigned long)s->svr.num_queries_prefetch)) return 0; + if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm, + (unsigned long)s->mesh_replies_sent)) return 0; if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm, (s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)? (double)s->svr.sum_query_list_size/ (s->svr.num_queries_missed_cache+ s->svr.num_queries_prefetch) : 0.0)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%u\n", nm, - (unsigned)s->svr.max_query_list_size)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.overwritten"SQ"%u\n", nm, - (unsigned)s->mesh_jostled)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.exceeded"SQ"%u\n", nm, - (unsigned)s->mesh_dropped)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.current.all"SQ"%u\n", nm, - (unsigned)s->mesh_num_states)) return 0; - if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%u\n", nm, - (unsigned)s->mesh_num_reply_states)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%lu\n", nm, + (unsigned long)s->svr.max_query_list_size)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.overwritten"SQ"%lu\n", nm, + (unsigned long)s->mesh_jostled)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.exceeded"SQ"%lu\n", nm, + (unsigned long)s->mesh_dropped)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.current.all"SQ"%lu\n", nm, + (unsigned long)s->mesh_num_states)) return 0; + if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%lu\n", nm, + (unsigned long)s->mesh_num_reply_states)) return 0; timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent); if(!ssl_printf(ssl, "%s.recursion.time.avg"SQ ARG_LL "d.%6.6d\n", nm, (long long)avg.tv_sec, (int)avg.tv_usec)) return 0; @@ -651,7 +656,7 @@ print_thread_stats(SSL* ssl, int i, struct stats_info* s) /** print long number */ static int -print_longnum(SSL* ssl, char* desc, size_t x) +print_longnum(SSL* ssl, const char* desc, size_t x) { if(x > 1024*1024*1024) { /* more than a Gb */ @@ -660,7 +665,7 @@ print_longnum(SSL* ssl, char* desc, size_t x) return ssl_printf(ssl, "%s%u%6.6u\n", desc, (unsigned)front, (unsigned)back); } else { - return ssl_printf(ssl, "%s%u\n", desc, (unsigned)x); + return ssl_printf(ssl, "%s%lu\n", desc, (unsigned long)x); } } @@ -739,12 +744,12 @@ print_hist(SSL* ssl, struct stats_info* s) timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST); for(i=0; inum; i++) { if(!ssl_printf(ssl, - "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%u\n", + "histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n", (int)hist->buckets[i].lower.tv_sec, (int)hist->buckets[i].lower.tv_usec, (int)hist->buckets[i].upper.tv_sec, (int)hist->buckets[i].upper.tv_usec, - (unsigned)hist->buckets[i].count)) { + (unsigned long)hist->buckets[i].count)) { timehist_delete(hist); return 0; } @@ -781,12 +786,12 @@ print_ext(SSL* ssl, struct stats_info* s) } else { snprintf(nm, sizeof(nm), "TYPE%d", i); } - if(!ssl_printf(ssl, "num.query.type.%s"SQ"%u\n", - nm, (unsigned)s->svr.qtype[i])) return 0; + if(!ssl_printf(ssl, "num.query.type.%s"SQ"%lu\n", + nm, (unsigned long)s->svr.qtype[i])) return 0; } if(!inhibit_zero || s->svr.qtype_big) { - if(!ssl_printf(ssl, "num.query.type.other"SQ"%u\n", - (unsigned)s->svr.qtype_big)) return 0; + if(!ssl_printf(ssl, "num.query.type.other"SQ"%lu\n", + (unsigned long)s->svr.qtype_big)) return 0; } /* CLASS */ for(i=0; isvr.qclass[i])) return 0; + if(!ssl_printf(ssl, "num.query.class.%s"SQ"%lu\n", + nm, (unsigned long)s->svr.qclass[i])) return 0; } if(!inhibit_zero || s->svr.qclass_big) { - if(!ssl_printf(ssl, "num.query.class.other"SQ"%u\n", - (unsigned)s->svr.qclass_big)) return 0; + if(!ssl_printf(ssl, "num.query.class.other"SQ"%lu\n", + (unsigned long)s->svr.qclass_big)) return 0; } /* OPCODE */ for(i=0; isvr.qopcode[i])) return 0; + if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%lu\n", + nm, (unsigned long)s->svr.qopcode[i])) return 0; } /* transport */ - if(!ssl_printf(ssl, "num.query.tcp"SQ"%u\n", - (unsigned)s->svr.qtcp)) return 0; - if(!ssl_printf(ssl, "num.query.ipv6"SQ"%u\n", - (unsigned)s->svr.qipv6)) return 0; + if(!ssl_printf(ssl, "num.query.tcp"SQ"%lu\n", + (unsigned long)s->svr.qtcp)) return 0; + if(!ssl_printf(ssl, "num.query.tcpout"SQ"%lu\n", + (unsigned long)s->svr.qtcp_outgoing)) return 0; + if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n", + (unsigned long)s->svr.qipv6)) return 0; /* flags */ - if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%u\n", - (unsigned)s->svr.qbit_QR)) return 0; - if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%u\n", - (unsigned)s->svr.qbit_AA)) return 0; - if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%u\n", - (unsigned)s->svr.qbit_TC)) return 0; - if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%u\n", - (unsigned)s->svr.qbit_RD)) return 0; - if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%u\n", - (unsigned)s->svr.qbit_RA)) return 0; - if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%u\n", - (unsigned)s->svr.qbit_Z)) return 0; - if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%u\n", - (unsigned)s->svr.qbit_AD)) return 0; - if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%u\n", - (unsigned)s->svr.qbit_CD)) return 0; - if(!ssl_printf(ssl, "num.query.edns.present"SQ"%u\n", - (unsigned)s->svr.qEDNS)) return 0; - if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%u\n", - (unsigned)s->svr.qEDNS_DO)) return 0; + if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%lu\n", + (unsigned long)s->svr.qbit_QR)) return 0; + if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%lu\n", + (unsigned long)s->svr.qbit_AA)) return 0; + if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%lu\n", + (unsigned long)s->svr.qbit_TC)) return 0; + if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%lu\n", + (unsigned long)s->svr.qbit_RD)) return 0; + if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%lu\n", + (unsigned long)s->svr.qbit_RA)) return 0; + if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%lu\n", + (unsigned long)s->svr.qbit_Z)) return 0; + if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%lu\n", + (unsigned long)s->svr.qbit_AD)) return 0; + if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%lu\n", + (unsigned long)s->svr.qbit_CD)) return 0; + if(!ssl_printf(ssl, "num.query.edns.present"SQ"%lu\n", + (unsigned long)s->svr.qEDNS)) return 0; + if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%lu\n", + (unsigned long)s->svr.qEDNS_DO)) return 0; /* RCODE */ for(i=0; isvr.ans_rcode[i])) return 0; + if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%lu\n", + nm, (unsigned long)s->svr.ans_rcode[i])) return 0; } if(!inhibit_zero || s->svr.ans_rcode_nodata) { - if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%u\n", - (unsigned)s->svr.ans_rcode_nodata)) return 0; + if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%lu\n", + (unsigned long)s->svr.ans_rcode_nodata)) return 0; } /* validation */ - if(!ssl_printf(ssl, "num.answer.secure"SQ"%u\n", - (unsigned)s->svr.ans_secure)) return 0; - if(!ssl_printf(ssl, "num.answer.bogus"SQ"%u\n", - (unsigned)s->svr.ans_bogus)) return 0; - if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%u\n", - (unsigned)s->svr.rrset_bogus)) return 0; + if(!ssl_printf(ssl, "num.answer.secure"SQ"%lu\n", + (unsigned long)s->svr.ans_secure)) return 0; + if(!ssl_printf(ssl, "num.answer.bogus"SQ"%lu\n", + (unsigned long)s->svr.ans_bogus)) return 0; + if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n", + (unsigned long)s->svr.rrset_bogus)) return 0; /* threat detection */ - if(!ssl_printf(ssl, "unwanted.queries"SQ"%u\n", - (unsigned)s->svr.unwanted_queries)) return 0; - if(!ssl_printf(ssl, "unwanted.replies"SQ"%u\n", - (unsigned)s->svr.unwanted_replies)) return 0; + if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n", + (unsigned long)s->svr.unwanted_queries)) return 0; + if(!ssl_printf(ssl, "unwanted.replies"SQ"%lu\n", + (unsigned long)s->svr.unwanted_replies)) return 0; + /* cache counts */ + if(!ssl_printf(ssl, "msg.cache.count"SQ"%u\n", + (unsigned)s->svr.msg_cache_count)) return 0; + if(!ssl_printf(ssl, "rrset.cache.count"SQ"%u\n", + (unsigned)s->svr.rrset_cache_count)) return 0; + if(!ssl_printf(ssl, "infra.cache.count"SQ"%u\n", + (unsigned)s->svr.infra_cache_count)) return 0; + if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n", + (unsigned)s->svr.key_cache_count)) return 0; return 1; } @@ -1286,9 +1302,9 @@ do_flush_zone(SSL* ssl, struct worker* worker, char* arg) free(nm); - (void)ssl_printf(ssl, "ok removed %u rrsets, %u messages " - "and %u key entries\n", (unsigned)inf.num_rrsets, - (unsigned)inf.num_msgs, (unsigned)inf.num_keys); + (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " + "and %lu key entries\n", (unsigned long)inf.num_rrsets, + (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); } /** callback to delete bogus rrsets */ @@ -1330,7 +1346,7 @@ bogus_del_kcache(struct lruhash_entry* e, void* arg) } } -/** remove all rrsets and keys from zone from cache */ +/** remove all bogus rrsets, msgs and keys from cache */ static void do_flush_bogus(SSL* ssl, struct worker* worker) { @@ -1354,9 +1370,85 @@ do_flush_bogus(SSL* ssl, struct worker* worker) &bogus_del_kcache, &inf); } - (void)ssl_printf(ssl, "ok removed %u rrsets, %u messages " - "and %u key entries\n", (unsigned)inf.num_rrsets, - (unsigned)inf.num_msgs, (unsigned)inf.num_keys); + (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " + "and %lu key entries\n", (unsigned long)inf.num_rrsets, + (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); +} + +/** callback to delete negative and servfail rrsets */ +static void +negative_del_rrset(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key; + struct packed_rrset_data* d = (struct packed_rrset_data*)e->data; + /* delete the parentside negative cache rrsets, + * these are namerserver rrsets that failed lookup, rdata empty */ + if((k->rk.flags & PACKED_RRSET_PARENT_SIDE) && d->count == 1 && + d->rrsig_count == 0 && d->rr_len[0] == 0) { + d->ttl = inf->expired; + inf->num_rrsets++; + } +} + +/** callback to delete negative and servfail messages */ +static void +negative_del_msg(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct reply_info* d = (struct reply_info*)e->data; + /* rcode not NOERROR: NXDOMAIN, SERVFAIL, ..: an nxdomain or error + * or NOERROR rcode with ANCOUNT==0: a NODATA answer */ + if(FLAGS_GET_RCODE(d->flags) != 0 || d->an_numrrsets == 0) { + d->ttl = inf->expired; + inf->num_msgs++; + } +} + +/** callback to delete negative key entries */ +static void +negative_del_kcache(struct lruhash_entry* e, void* arg) +{ + /* entry is locked */ + struct del_info* inf = (struct del_info*)arg; + struct key_entry_data* d = (struct key_entry_data*)e->data; + /* could be bad because of lookup failure on the DS, DNSKEY, which + * was nxdomain or servfail, and thus a result of negative lookups */ + if(d->isbad) { + d->ttl = inf->expired; + inf->num_keys++; + } +} + +/** remove all negative(NODATA,NXDOMAIN), and servfail messages from cache */ +static void +do_flush_negative(SSL* ssl, struct worker* worker) +{ + struct del_info inf; + /* what we do is to set them all expired */ + inf.worker = worker; + inf.now = *worker->env.now; + inf.expired = *worker->env.now; + inf.expired -= 3; /* handle 3 seconds skew between threads */ + inf.num_rrsets = 0; + inf.num_msgs = 0; + inf.num_keys = 0; + slabhash_traverse(&worker->env.rrset_cache->table, 1, + &negative_del_rrset, &inf); + + slabhash_traverse(worker->env.msg_cache, 1, &negative_del_msg, &inf); + + /* and validator cache */ + if(worker->env.key_cache) { + slabhash_traverse(worker->env.key_cache->slab, 1, + &negative_del_kcache, &inf); + } + + (void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages " + "and %lu key entries\n", (unsigned long)inf.num_rrsets, + (unsigned long)inf.num_msgs, (unsigned long)inf.num_keys); } /** remove name rrset from cache */ @@ -1385,7 +1477,7 @@ do_flush_name(SSL* ssl, struct worker* w, char* arg) /** printout a delegation point info */ static int -ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass, +ssl_print_name_dp(SSL* ssl, const char* str, uint8_t* nm, uint16_t dclass, struct delegpt* dp) { char buf[257]; @@ -1395,7 +1487,7 @@ ssl_print_name_dp(SSL* ssl, char* str, uint8_t* nm, uint16_t dclass, if(str) { /* print header for forward, stub */ char* c = sldns_wire2str_class(dclass); dname_str(nm, buf); - if(!ssl_printf(ssl, "%s %s %s: ", buf, (c?c:"CLASS??"), str)) { + if(!ssl_printf(ssl, "%s %s %s ", buf, (c?c:"CLASS??"), str)) { free(c); return 0; } @@ -1730,6 +1822,10 @@ do_status(SSL* ssl, struct worker* worker) uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec; if(!ssl_printf(ssl, "uptime: " ARG_LL "d seconds\n", (long long)uptime)) return; + if(!ssl_printf(ssl, "options:%s%s\n" , + (worker->daemon->reuseport?" reuseport":""), + (worker->daemon->rc->accept_list?" control(ssl)":""))) + return; if(!ssl_printf(ssl, "unbound (pid %d) is running...\n", (int)getpid())) return; @@ -1852,6 +1948,9 @@ struct infra_arg { SSL* ssl; /** the time now */ time_t now; + /** ssl failure? stop writing and skip the rest. If the tcp + * connection is broken, and writes fail, we then stop writing. */ + int ssl_failed; }; /** callback for every host element in the infra cache */ @@ -1863,27 +1962,34 @@ dump_infra_host(struct lruhash_entry* e, void* arg) struct infra_data* d = (struct infra_data*)e->data; char ip_str[1024]; char name[257]; + if(a->ssl_failed) + return; addr_to_str(&k->addr, k->addrlen, ip_str, sizeof(ip_str)); dname_str(k->zonename, name); /* skip expired stuff (only backed off) */ if(d->ttl < a->now) { if(d->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) { if(!ssl_printf(a->ssl, "%s %s expired rto %d\n", ip_str, - name, d->rtt.rto)) return; + name, d->rtt.rto)) { + a->ssl_failed = 1; + return; + } } return; } - if(!ssl_printf(a->ssl, "%s %s ttl %d ping %d var %d rtt %d rto %d " + if(!ssl_printf(a->ssl, "%s %s ttl %lu ping %d var %d rtt %d rto %d " "tA %d tAAAA %d tother %d " "ednsknown %d edns %d delay %d lame dnssec %d rec %d A %d " - "other %d\n", ip_str, name, (int)(d->ttl - a->now), + "other %d\n", ip_str, name, (unsigned long)(d->ttl - a->now), d->rtt.srtt, d->rtt.rttvar, rtt_notimeout(&d->rtt), d->rtt.rto, d->timeout_A, d->timeout_AAAA, d->timeout_other, (int)d->edns_lame_known, (int)d->edns_version, (int)(a->nowprobedelay?d->probedelay-a->now:0), (int)d->isdnsseclame, (int)d->rec_lame, (int)d->lame_type_A, - (int)d->lame_other)) + (int)d->lame_other)) { + a->ssl_failed = 1; return; + } } /** do the dump_infra command */ @@ -1894,6 +2000,7 @@ do_dump_infra(SSL* ssl, struct worker* worker) arg.infra = worker->env.infra_cache; arg.ssl = ssl; arg.now = *worker->env.now; + arg.ssl_failed = 0; slabhash_traverse(arg.infra->hosts, 0, &dump_infra_host, (void*)&arg); } @@ -1946,10 +2053,23 @@ do_list_forwards(SSL* ssl, struct worker* worker) /* since its a per-worker structure no locks needed */ struct iter_forwards* fwds = worker->env.fwds; struct iter_forward_zone* z; + struct trust_anchor* a; + int insecure; RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) { if(!z->dp) continue; /* skip empty marker for stub */ - if(!ssl_print_name_dp(ssl, "forward", z->name, z->dclass, - z->dp)) + + /* see if it is insecure */ + insecure = 0; + if(worker->env.anchors && + (a=anchor_find(worker->env.anchors, z->name, + z->namelabs, z->namelen, z->dclass))) { + if(!a->keylist && !a->numDS && !a->numDNSKEY) + insecure = 1; + lock_basic_unlock(&a->lock); + } + + if(!ssl_print_name_dp(ssl, (insecure?"forward +i":"forward"), + z->name, z->dclass, z->dp)) return; } } @@ -1959,9 +2079,24 @@ static void do_list_stubs(SSL* ssl, struct worker* worker) { struct iter_hints_stub* z; + struct trust_anchor* a; + int insecure; + char str[32]; RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) { - if(!ssl_print_name_dp(ssl, - z->noprime?"stub noprime":"stub prime", z->node.name, + + /* see if it is insecure */ + insecure = 0; + if(worker->env.anchors && + (a=anchor_find(worker->env.anchors, z->node.name, + z->node.labs, z->node.len, z->node.dclass))) { + if(!a->keylist && !a->numDS && !a->numDNSKEY) + insecure = 1; + lock_basic_unlock(&a->lock); + } + + snprintf(str, sizeof(str), "stub %sprime%s", + (z->noprime?"no":""), (insecure?" +i":"")); + if(!ssl_print_name_dp(ssl, str, z->node.name, z->node.dclass, z->dp)) return; } @@ -1978,8 +2113,13 @@ do_list_local_zones(SSL* ssl, struct worker* worker) RBTREE_FOR(z, struct local_zone*, &zones->ztree) { lock_rw_rdlock(&z->lock); dname_str(z->name, buf); - (void)ssl_printf(ssl, "%s %s\n", buf, - local_zone_type2str(z->type)); + if(!ssl_printf(ssl, "%s %s\n", buf, + local_zone_type2str(z->type))) { + /* failure to print */ + lock_rw_unlock(&z->lock); + lock_rw_unlock(&zones->lock); + return; + } lock_rw_unlock(&z->lock); } lock_rw_unlock(&zones->lock); @@ -2173,6 +2313,8 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, do_get_option(ssl, worker, skipwhite(p+10)); } else if(cmdcmp(p, "flush_bogus", 11)) { do_flush_bogus(ssl, worker); + } else if(cmdcmp(p, "flush_negative", 14)) { + do_flush_negative(ssl, worker); } else { (void)ssl_printf(ssl, "error unknown command '%s'\n", p); } diff --git a/daemon/remote.h b/daemon/remote.h index c4565414b38b..cc670b70128f 100644 --- a/daemon/remote.h +++ b/daemon/remote.h @@ -157,12 +157,6 @@ void daemon_remote_start_accept(struct daemon_remote* rc); */ void daemon_remote_exec(struct worker* worker); -/** handle remote control accept callbacks */ -int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*); - -/** handle remote control data callbacks */ -int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*); - #ifdef HAVE_SSL /** * Print fixed line of text over ssl connection in blocking mode @@ -192,7 +186,4 @@ int ssl_printf(SSL* ssl, const char* format, ...) int ssl_read_line(SSL* ssl, char* buf, size_t max); #endif /* HAVE_SSL */ -/** routine to printout option values over SSL */ -void remote_get_opt_ssl(char* line, void* arg); - #endif /* DAEMON_REMOTE_H */ diff --git a/daemon/stats.c b/daemon/stats.c index 57ad1ef6bcdd..d3f41de037b4 100644 --- a/daemon/stats.c +++ b/daemon/stats.c @@ -56,6 +56,9 @@ #include "util/net_help.h" #include "validator/validator.h" #include "ldns/sbuffer.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "validator/val_kcache.h" /** add timers and the values do not overflow or become negative */ static void @@ -158,10 +161,19 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset) NUM_BUCKETS_HIST); /* values from outside network */ s->svr.unwanted_replies = worker->back->unwanted_replies; + s->svr.qtcp_outgoing = worker->back->num_tcp_outgoing; /* get and reset validator rrset bogus number */ s->svr.rrset_bogus = get_rrset_bogus(worker); + /* get cache sizes */ + s->svr.msg_cache_count = count_slabhash_entries(worker->env.msg_cache); + s->svr.rrset_cache_count = count_slabhash_entries(&worker->env.rrset_cache->table); + s->svr.infra_cache_count = count_slabhash_entries(worker->env.infra_cache->hosts); + if(worker->env.key_cache) + s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab); + else s->svr.key_cache_count = 0; + if(reset && !worker->env.cfg->stat_cumulative) { worker_stats_clear(worker); } @@ -217,6 +229,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a) total->svr.qtype_big += a->svr.qtype_big; total->svr.qclass_big += a->svr.qclass_big; total->svr.qtcp += a->svr.qtcp; + total->svr.qtcp_outgoing += a->svr.qtcp_outgoing; total->svr.qipv6 += a->svr.qipv6; total->svr.qbit_QR += a->svr.qbit_QR; total->svr.qbit_AA += a->svr.qbit_AA; diff --git a/daemon/stats.h b/daemon/stats.h index 7c315513f369..5ea00a0da5b7 100644 --- a/daemon/stats.h +++ b/daemon/stats.h @@ -91,6 +91,8 @@ struct server_stats { size_t qopcode[STATS_OPCODE_NUM]; /** number of queries over TCP */ size_t qtcp; + /** number of outgoing queries over TCP */ + size_t qtcp_outgoing; /** number of queries over IPv6 */ size_t qipv6; /** number of queries with QR bit */ @@ -133,6 +135,15 @@ struct server_stats { * if all histograms are same size (is so by default) then * adding up works well. */ size_t hist[NUM_BUCKETS_HIST]; + + /** number of message cache entries */ + size_t msg_cache_count; + /** number of rrset cache entries */ + size_t rrset_cache_count; + /** number of infra cache entries */ + size_t infra_cache_count; + /** number of key cache entries */ + size_t key_cache_count; }; /** diff --git a/daemon/unbound.c b/daemon/unbound.c index 4e2f1cb3d605..a53fe954db26 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -53,6 +53,7 @@ #include "services/listen_dnsport.h" #include "services/cache/rrset.h" #include "services/cache/infra.h" +#include "util/fptr_wlist.h" #include "util/data/msgreply.h" #include "util/module.h" #include "util/net_help.h" @@ -83,7 +84,13 @@ # include "util/mini_event.h" # endif #else -# include +# ifdef HAVE_EVENT_H +# include +# else +# include "event2/event.h" +# include "event2/event_struct.h" +# include "event2/event_compat.h" +# endif #endif #ifdef UB_ON_WINDOWS @@ -95,8 +102,10 @@ # include "nss.h" #endif +#ifdef HAVE_SBRK /** global debug value to keep track of heap memory allocation */ void* unbound_start_brk = 0; +#endif #if !defined(HAVE_EVENT_BASE_GET_METHOD) && (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) static const char* ev_backend2str(int b) @@ -177,8 +186,6 @@ static void usage() for(m = module_list_avail(); *m; m++) printf(" %s", *m); printf("\n"); - printf("configured for %s on %s with options:%s\n", - CONFIGURE_TARGET, CONFIGURE_DATE, CONFIGURE_BUILD_WITH); printf("BSD licensed, see LICENSE in source package for details.\n"); printf("Report bugs to %s\n", PACKAGE_BUGREPORT); } @@ -262,8 +269,6 @@ checkrlimits(struct config_file* cfg) #ifdef HAVE_SETRLIMIT if(setrlimit(RLIMIT_NOFILE, &rlim) < 0) { log_warn("setrlimit: %s", strerror(errno)); -#else - if(1) { #endif log_warn("cannot increase max open fds from %u to %u", (unsigned)avail, (unsigned)total+10); @@ -279,7 +284,9 @@ checkrlimits(struct config_file* cfg) log_warn("increase ulimit or decrease threads, " "ports in config to remove this warning"); return; +#ifdef HAVE_SETRLIMIT } +#endif log_warn("increased limit(open files) from %u to %u", (unsigned)avail, (unsigned)total+10); } @@ -292,10 +299,14 @@ checkrlimits(struct config_file* cfg) /** set verbosity, check rlimits, cache settings */ static void apply_settings(struct daemon* daemon, struct config_file* cfg, - int cmdline_verbose) + int cmdline_verbose, int debug_mode) { /* apply if they have changed */ verbosity = cmdline_verbose + cfg->verbosity; + if (debug_mode > 1) { + cfg->use_syslog = 0; + cfg->logfile = NULL; + } daemon_apply_cfg(daemon, cfg); checkrlimits(cfg); } @@ -654,7 +665,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode) cfgfile); log_warn("Continuing with default config settings"); } - apply_settings(daemon, cfg, cmdline_verbose); + apply_settings(daemon, cfg, cmdline_verbose, debug_mode); /* prepare */ if(!daemon_open_shared_ports(daemon)) @@ -734,7 +745,7 @@ main(int argc, char* argv[]) verbosity++; break; case 'd': - debug_mode = 1; + debug_mode++; break; case 'w': winopt = optarg; diff --git a/daemon/worker.c b/daemon/worker.c index 67cd427b69fd..f9067621385b 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -69,6 +69,8 @@ #include "iterator/iter_hints.h" #include "validator/autotrust.h" #include "validator/val_anchor.h" +#include "libunbound/context.h" +#include "libunbound/libworker.h" #include "ldns/sbuffer.h" #ifdef HAVE_SYS_TYPES_H @@ -718,7 +720,7 @@ answer_chaos(struct worker* w, struct query_info* qinfo, return 0; } -int +static int deny_refuse(struct comm_point* c, enum acl_access acl, enum acl_access deny, enum acl_access refuse, struct worker* worker, struct comm_reply* repinfo) @@ -750,14 +752,14 @@ deny_refuse(struct comm_point* c, enum acl_access acl, return -1; } -int +static int deny_refuse_all(struct comm_point* c, enum acl_access acl, struct worker* worker, struct comm_reply* repinfo) { return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo); } -int +static int deny_refuse_non_local(struct comm_point* c, enum acl_access acl, struct worker* worker, struct comm_reply* repinfo) { @@ -775,16 +777,24 @@ worker_handle_request(struct comm_point* c, void* arg, int error, struct query_info qinfo; struct edns_data edns; enum acl_access acl; + int rc = 0; if(error != NETEVENT_NOERROR) { /* some bad tcp query DNS formats give these error calls */ verbose(VERB_ALGO, "handle request called with err=%d", error); return 0; } +#ifdef USE_DNSTAP + if(worker->dtenv.log_client_query_messages) + dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type, + c->buffer); +#endif acl = acl_list_lookup(worker->daemon->acl, &repinfo->addr, repinfo->addrlen); if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1) { + if(ret == 1) + goto send_reply; return ret; } if((ret=worker_check_request(c->buffer, worker)) != 0) { @@ -808,7 +818,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), LDNS_RCODE_FORMERR); server_stats_insrcode(&worker->stats, c->buffer); - return 1; + goto send_reply; } if(worker->env.cfg->log_queries) { char ip[128]; @@ -827,7 +837,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, worker->stats.qtype[qinfo.qtype]++; server_stats_insrcode(&worker->stats, c->buffer); } - return 1; + goto send_reply; } if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) { verbose(VERB_ALGO, "worker parse edns: formerror."); @@ -836,7 +846,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, LDNS_QR_SET(sldns_buffer_begin(c->buffer)); LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), ret); server_stats_insrcode(&worker->stats, c->buffer); - return 1; + goto send_reply; } if(edns.edns_present && edns.edns_version != 0) { edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4); @@ -846,10 +856,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error, verbose(VERB_ALGO, "query with bad edns version."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo, - *(uint16_t*)sldns_buffer_begin(c->buffer), + *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), sldns_buffer_read_u16_at(c->buffer, 2), NULL); attach_edns_record(c->buffer, &edns); - return 1; + goto send_reply; } if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE && worker->daemon->cfg->harden_short_bufsize) { @@ -877,7 +887,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, sldns_buffer_write_at(c->buffer, 4, (uint8_t*)"\0\0\0\0\0\0\0\0", 8); sldns_buffer_flip(c->buffer); - return 1; + goto send_reply; } if(worker->stats.extended) server_stats_insquery(&worker->stats, c, qinfo.qtype, @@ -887,7 +897,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo, &edns, c->buffer)) { server_stats_insrcode(&worker->stats, c->buffer); - return 1; + goto send_reply; } if(local_zones_answer(worker->daemon->local_zones, &qinfo, &edns, c->buffer, worker->scratchpad)) { @@ -897,13 +907,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error, return 0; } server_stats_insrcode(&worker->stats, c->buffer); - return 1; + goto send_reply; } /* We've looked in our local zones. If the answer isn't there, we * might need to bail out based on ACLs now. */ if((ret=deny_refuse_non_local(c, acl, worker, repinfo)) != -1) { + if(ret == 1) + goto send_reply; return ret; } @@ -921,14 +933,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error, server_stats_insrcode(&worker->stats, c->buffer); log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", &repinfo->addr, repinfo->addrlen); - return 1; + goto send_reply; } h = query_info_hash(&qinfo); if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) { /* answer from cache - we have acquired a readlock on it */ if(answer_from_cache(worker, &qinfo, (struct reply_info*)e->data, - *(uint16_t*)sldns_buffer_begin(c->buffer), + *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), sldns_buffer_read_u16_at(c->buffer, 2), repinfo, &edns)) { /* prefetch it if the prefetch TTL expired */ @@ -940,20 +952,21 @@ worker_handle_request(struct comm_point* c, void* arg, int error, reply_and_prefetch(worker, &qinfo, sldns_buffer_read_u16_at(c->buffer, 2), repinfo, leeway); - return 0; + rc = 0; + goto send_reply_rc; } lock_rw_unlock(&e->lock); - return 1; + goto send_reply; } verbose(VERB_ALGO, "answer from the cache failed"); lock_rw_unlock(&e->lock); } if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) { if(answer_norec_from_cache(worker, &qinfo, - *(uint16_t*)sldns_buffer_begin(c->buffer), + *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), sldns_buffer_read_u16_at(c->buffer, 2), repinfo, &edns)) { - return 1; + goto send_reply; } verbose(VERB_ALGO, "answer norec from cache -- " "need to validate or not primed"); @@ -972,45 +985,49 @@ worker_handle_request(struct comm_point* c, void* arg, int error, /* grab a work request structure for this new request */ mesh_new_client(worker->env.mesh, &qinfo, sldns_buffer_read_u16_at(c->buffer, 2), - &edns, repinfo, *(uint16_t*)sldns_buffer_begin(c->buffer)); + &edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer)); worker_mem_report(worker, NULL); return 0; + +send_reply: + rc = 1; +send_reply_rc: +#ifdef USE_DNSTAP + if(worker->dtenv.log_client_response_messages) + dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, + c->type, c->buffer); +#endif + return rc; } void worker_sighandler(int sig, void* arg) { - /* note that log, print, syscalls here give race conditions. */ - /* we still print DETAIL logs, because this is extensive per message - * logging anyway, and the operator may then have an interest - * in the cause for unbound to exit */ + /* note that log, print, syscalls here give race conditions. + * And cause hangups if the log-lock is held by the application. */ struct worker* worker = (struct worker*)arg; switch(sig) { #ifdef SIGHUP case SIGHUP: - verbose(VERB_QUERY, "caught signal SIGHUP"); comm_base_exit(worker->base); break; #endif case SIGINT: - verbose(VERB_QUERY, "caught signal SIGINT"); worker->need_to_exit = 1; comm_base_exit(worker->base); break; #ifdef SIGQUIT case SIGQUIT: - verbose(VERB_QUERY, "caught signal SIGQUIT"); worker->need_to_exit = 1; comm_base_exit(worker->base); break; #endif case SIGTERM: - verbose(VERB_QUERY, "caught signal SIGTERM"); worker->need_to_exit = 1; comm_base_exit(worker->base); break; default: - log_err("unknown signal: %d, ignored", sig); + /* unknown signal, ignored */ break; } } @@ -1088,6 +1105,14 @@ worker_create(struct daemon* daemon, int id, int* ports, int n) return NULL; } seed = 0; +#ifdef USE_DNSTAP + if(daemon->cfg->dnstap) { + log_assert(daemon->dtenv != NULL); + memcpy(&worker->dtenv, daemon->dtenv, sizeof(struct dt_env)); + if(!dt_init(&worker->dtenv)) + fatal_exit("dt_init failed"); + } +#endif return worker; } @@ -1095,6 +1120,11 @@ int worker_init(struct worker* worker, struct config_file *cfg, struct listen_port* ports, int do_sigs) { +#ifdef USE_DNSTAP + struct dt_env* dtenv = &worker->dtenv; +#else + void* dtenv = NULL; +#endif worker->need_to_exit = 0; worker->base = comm_base_create(do_sigs); if(!worker->base) { @@ -1143,7 +1173,8 @@ worker_init(struct worker* worker, struct config_file *cfg, } worker->front = listen_create(worker->base, ports, cfg->msg_buffer_size, (int)cfg->incoming_num_tcp, - worker->daemon->listen_sslctx, worker_handle_request, worker); + worker->daemon->listen_sslctx, dtenv, worker_handle_request, + worker); if(!worker->front) { log_err("could not create listening sockets"); worker_delete(worker); @@ -1156,7 +1187,8 @@ worker_init(struct worker* worker, struct config_file *cfg, worker->daemon->env->infra_cache, worker->rndstate, cfg->use_caps_bits_for_id, worker->ports, worker->numports, cfg->unwanted_threshold, &worker_alloc_cleanup, worker, - cfg->do_udp, worker->daemon->connect_sslctx, cfg->delay_close); + cfg->do_udp, worker->daemon->connect_sslctx, cfg->delay_close, + dtenv); if(!worker->back) { log_err("could not create outgoing sockets"); worker_delete(worker); @@ -1291,8 +1323,8 @@ worker_delete(struct worker* worker) struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec, - struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, struct module_qstate* q) + int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, + uint8_t* zone, size_t zonelen, struct module_qstate* q) { struct worker* worker = q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -1301,7 +1333,7 @@ worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype, return NULL; e->qstate = q; e->qsent = outnet_serviced_query(worker->back, qname, - qnamelen, qtype, qclass, flags, dnssec, want_dnssec, + qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps, q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr, addrlen, zone, zonelen, worker_handle_service_reply, e, worker->back->udp_buff); @@ -1324,6 +1356,7 @@ void worker_stats_clear(struct worker* worker) server_stats_init(&worker->stats, worker->env.cfg); mesh_stats_clear(worker->env.mesh); worker->back->unwanted_replies = 0; + worker->back->num_tcp_outgoing = 0; } void worker_start_accept(void* arg) @@ -1347,8 +1380,9 @@ struct outbound_entry* libworker_send_query(uint8_t* ATTR_UNUSED(qname), size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype), uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), - struct sockaddr_storage* ATTR_UNUSED(addr), - socklen_t ATTR_UNUSED(addrlen), struct module_qstate* ATTR_UNUSED(q)) + int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), + size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; diff --git a/daemon/worker.h b/daemon/worker.h index 4da4c6b6b4c3..ff69bc1acfd4 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -43,6 +43,7 @@ #ifndef DAEMON_WORKER_H #define DAEMON_WORKER_H +#include "libunbound/worker.h" #include "util/netevent.h" #include "util/locks.h" #include "util/alloc.h" @@ -50,6 +51,7 @@ #include "util/data/msgparse.h" #include "daemon/stats.h" #include "util/module.h" +#include "dnstap/dnstap.h" struct listen_dnsport; struct outside_network; struct config_file; @@ -115,6 +117,11 @@ struct worker { /** module environment passed to modules, changed for this thread */ struct module_env env; + +#ifdef USE_DNSTAP + /** dnstap environment, changed for this thread */ + struct dt_env dtenv; +#endif }; /** @@ -157,78 +164,10 @@ void worker_delete(struct worker* worker); */ void worker_send_cmd(struct worker* worker, enum worker_commands cmd); -/** - * Worker signal handler function. User argument is the worker itself. - * @param sig: signal number. - * @param arg: the worker (main worker) that handles signals. - */ -void worker_sighandler(int sig, void* arg); - -/** - * Worker service routine to send serviced queries to authoritative servers. - * @param qname: query name. (host order) - * @param qnamelen: length in bytes of qname, including trailing 0. - * @param qtype: query type. (host order) - * @param qclass: query class. (host order) - * @param flags: host order flags word, with opcode and CD bit. - * @param dnssec: if set, EDNS record will have DO bit set. - * @param want_dnssec: signatures needed. - * @param addr: where to. - * @param addrlen: length of addr. - * @param zone: wireformat dname of the zone. - * @param zonelen: length of zone name. - * @param q: wich query state to reactivate upon return. - * @return: false on failure (memory or socket related). no query was - * sent. - */ -struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* q); - -/** - * process control messages from the main thread. Frees the control - * command message. - * @param tube: tube control message came on. - * @param msg: message contents. Is freed. - * @param len: length of message. - * @param error: if error (NETEVENT_*) happened. - * @param arg: user argument - */ -void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, - int error, void* arg); - -/** handles callbacks from listening event interface */ -int worker_handle_request(struct comm_point* c, void* arg, int error, - struct comm_reply* repinfo); - -/** process incoming replies from the network */ -int worker_handle_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** process incoming serviced query replies from the network */ -int worker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** cleanup the cache to remove all rrset IDs from it, arg is worker */ -void worker_alloc_cleanup(void* arg); - /** * Init worker stats - includes server_stats_init, outside network and mesh. * @param worker: the worker to init */ void worker_stats_clear(struct worker* worker); -/** statistics timer callback handler */ -void worker_stat_timer_cb(void* arg); - -/** probe timer callback handler */ -void worker_probe_timer_cb(void* arg); - -/** start accept callback handler */ -void worker_start_accept(void* arg); - -/** stop accept callback handler */ -void worker_stop_accept(void* arg); - #endif /* DAEMON_WORKER_H */ -- cgit v1.2.3