Blame SOURCES/unbound-1.7.3-additional-logging.patch

fdd92c
diff --git a/daemon/worker.c b/daemon/worker.c
fdd92c
index 44a989a..3acecc1 100644
fdd92c
--- a/daemon/worker.c
fdd92c
+++ b/daemon/worker.c
fdd92c
@@ -1193,7 +1193,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
fdd92c
 	if(worker->env.cfg->log_queries) {
fdd92c
 		char ip[128];
fdd92c
 		addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
fdd92c
-		log_nametypeclass(0, ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
fdd92c
+		log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
fdd92c
 	}
fdd92c
 	if(qinfo.qtype == LDNS_RR_TYPE_AXFR || 
fdd92c
 		qinfo.qtype == LDNS_RR_TYPE_IXFR) {
fdd92c
diff --git a/doc/Changelog b/doc/Changelog
fdd92c
index 3d05ae5..bb74461 100644
fdd92c
--- a/doc/Changelog
fdd92c
+++ b/doc/Changelog
fdd92c
@@ -1,3 +1,15 @@
fdd92c
+30 November 2018: Wouter
fdd92c
+	- log-tag-queryreply: yes in unbound.conf tags the log-queries and
fdd92c
+	  log-replies in the log file for easier log filter maintenance.
fdd92c
+
fdd92c
+21 August 2018: Wouter
fdd92c
+	- log-local-actions: yes option for unbound.conf that logs all the
fdd92c
+	  local zone actions, a patch from Saksham Manchanda (Secure64).
fdd92c
+
fdd92c
+17 August 2018: Wouter
fdd92c
+	- log-servfail: yes prints log lines that say why queries are
fdd92c
+	  returning SERVFAIL to clients.
fdd92c
+
fdd92c
 19 June 2018: Wouter
fdd92c
 	- Fix for unbound-control on Windows and set TCP socket parameters
fdd92c
 	  more closely.
fdd92c
diff --git a/doc/example.conf.in b/doc/example.conf.in
fdd92c
index be83bda..aa06cee 100644
fdd92c
--- a/doc/example.conf.in
fdd92c
+++ b/doc/example.conf.in
fdd92c
@@ -309,6 +309,17 @@ server:
fdd92c
 	# timetoresolve, fromcache and responsesize.
fdd92c
 	# log-replies: no
fdd92c
 
fdd92c
+	# log with tag 'query' and 'reply' instead of 'info' for
fdd92c
+	# filtering log-queries and log-replies from the log.
fdd92c
+	# log-tag-queryreply: no
fdd92c
+
fdd92c
+	# log the local-zone actions, like local-zone type inform is enabled
fdd92c
+	# also for the other local zone types.
fdd92c
+	# log-local-actions: no
fdd92c
+
fdd92c
+	# print log lines that say why queries return SERVFAIL to clients.
fdd92c
+	# log-servfail: no
fdd92c
+
fdd92c
 	# the pid file. Can be an absolute path outside of chroot/work dir.
fdd92c
 	# pidfile: "@UNBOUND_PIDFILE@"
fdd92c
 
fdd92c
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
fdd92c
index 9167a5a..b73bc70 100644
fdd92c
--- a/doc/unbound.conf.5.in
fdd92c
+++ b/doc/unbound.conf.5.in
fdd92c
@@ -618,6 +618,21 @@ Default is no.  Note that it takes time to print these
fdd92c
 lines which makes the server (significantly) slower.  Odd (nonprintable)
fdd92c
 characters in names are printed as '?'.
fdd92c
 .TP
fdd92c
+.B log\-tag\-queryreply: \fI<yes or no>
fdd92c
+Prints the word 'query' and 'reply' with log\-queries and log\-replies.
fdd92c
+This makes filtering logs easier.  The default is off (for backwards
fdd92c
+compatibility).
fdd92c
+.TP
fdd92c
+.B log\-local\-actions: \fI<yes or no>
fdd92c
+Print log lines to inform about local zone actions.  These lines are like the
fdd92c
+local\-zone type inform prints out, but they are also printed for the other
fdd92c
+types of local zones.
fdd92c
+.TP
fdd92c
+.B log\-servfail: \fI<yes or no>
fdd92c
+Print log lines that say why queries return SERVFAIL to clients.
fdd92c
+This is separate from the verbosity debug logs, much smaller, and printed
fdd92c
+at the error level, not the info level of debug info from verbosity.
fdd92c
+.TP
fdd92c
 .B pidfile: \fI<filename>
fdd92c
 The process id is written to the file. Default is "@UNBOUND_PIDFILE@".
fdd92c
 So,
fdd92c
diff --git a/services/localzone.c b/services/localzone.c
fdd92c
index 0f60817..a85619b 100644
fdd92c
--- a/services/localzone.c
fdd92c
+++ b/services/localzone.c
fdd92c
@@ -1459,7 +1459,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
fdd92c
 	uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
fdd92c
 	dname_str(z->name, zname);
fdd92c
 	addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
fdd92c
-	snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip,
fdd92c
+	snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,
fdd92c
 		(unsigned)port);
fdd92c
 	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
fdd92c
 }
fdd92c
@@ -1576,7 +1576,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
fdd92c
 			z->override_tree, &tag, tagname, num_tags);
fdd92c
 		lock_rw_unlock(&zones->lock);
fdd92c
 	}
fdd92c
-	if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
fdd92c
+	if((env->cfg->log_local_actions ||
fdd92c
+		lzt == local_zone_inform || lzt == local_zone_inform_deny)
fdd92c
 		&& repinfo)
fdd92c
 		lz_inform_print(z, qinfo, repinfo);
fdd92c
 
fdd92c
diff --git a/services/mesh.c b/services/mesh.c
fdd92c
index 41aba74..55c1947 100644
fdd92c
--- a/services/mesh.c
fdd92c
+++ b/services/mesh.c
fdd92c
@@ -977,7 +977,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
fdd92c
 		rcode = LDNS_RCODE_SERVFAIL;
fdd92c
 	if(!rcode && (rep->security == sec_status_bogus ||
fdd92c
 		rep->security == sec_status_secure_sentinel_fail)) {
fdd92c
-		if(!(reason = errinf_to_str(&m->s)))
fdd92c
+		if(!(reason = errinf_to_str_bogus(&m->s)))
fdd92c
 			rcode = LDNS_RCODE_SERVFAIL;
fdd92c
 	}
fdd92c
 	/* send the reply */
fdd92c
@@ -1148,6 +1148,15 @@ void mesh_query_done(struct mesh_state* mstate)
fdd92c
 	struct mesh_cb* c;
fdd92c
 	struct reply_info* rep = (mstate->s.return_msg?
fdd92c
 		mstate->s.return_msg->rep:NULL);
fdd92c
+	if((mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
fdd92c
+		(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL))
fdd92c
+		&& mstate->s.env->cfg->log_servfail
fdd92c
+		&& !mstate->s.env->cfg->val_log_squelch) {
fdd92c
+			char* err = errinf_to_str_servfail(&mstate->s);
fdd92c
+			if(err)
fdd92c
+				log_err("%s", err);
fdd92c
+			free(err);
fdd92c
+	}
fdd92c
 	for(r = mstate->reply_list; r; r = r->next) {
fdd92c
 		/* if a response-ip address block has been stored the
fdd92c
 		 *  information should be logged for each client. */
fdd92c
diff --git a/util/config_file.c b/util/config_file.c
fdd92c
index b061760..68a0a15 100644
fdd92c
--- a/util/config_file.c
fdd92c
+++ b/util/config_file.c
fdd92c
@@ -115,6 +115,9 @@ config_create(void)
fdd92c
 	cfg->log_time_ascii = 0;
fdd92c
 	cfg->log_queries = 0;
fdd92c
 	cfg->log_replies = 0;
fdd92c
+	cfg->log_tag_queryreply = 0;
fdd92c
+	cfg->log_local_actions = 0;
fdd92c
+	cfg->log_servfail = 0;
fdd92c
 #ifndef USE_WINSOCK
fdd92c
 #  ifdef USE_MINI_EVENT
fdd92c
 	/* select max 1024 sockets */
fdd92c
@@ -540,6 +543,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
fdd92c
 	else S_YNO("val-log-squelch:", val_log_squelch)
fdd92c
 	else S_YNO("log-queries:", log_queries)
fdd92c
 	else S_YNO("log-replies:", log_replies)
fdd92c
+	else S_YNO("log-tag-queryreply:", log_tag_queryreply)
fdd92c
+	else S_YNO("log-local-actions:", log_local_actions)
fdd92c
+	else S_YNO("log-servfail:", log_servfail)
fdd92c
 	else S_YNO("val-permissive-mode:", val_permissive_mode)
fdd92c
 	else S_YNO("aggressive-nsec:", aggressive_nsec)
fdd92c
 	else S_YNO("ignore-cd-flag:", ignore_cd)
fdd92c
@@ -893,6 +899,9 @@ config_get_option(struct config_file* cfg, const char* opt,
fdd92c
 	else O_STR(opt, "logfile", logfile)
fdd92c
 	else O_YNO(opt, "log-queries", log_queries)
fdd92c
 	else O_YNO(opt, "log-replies", log_replies)
fdd92c
+	else O_YNO(opt, "log-tag-queryreply", log_tag_queryreply)
fdd92c
+	else O_YNO(opt, "log-local-actions", log_local_actions)
fdd92c
+	else O_YNO(opt, "log-servfail", log_servfail)
fdd92c
 	else O_STR(opt, "pidfile", pidfile)
fdd92c
 	else O_YNO(opt, "hide-identity", hide_identity)
fdd92c
 	else O_YNO(opt, "hide-version", hide_version)
fdd92c
@@ -1845,6 +1854,7 @@ config_apply(struct config_file* config)
fdd92c
 	EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
fdd92c
 	MINIMAL_RESPONSES = config->minimal_responses;
fdd92c
 	RRSET_ROUNDROBIN = config->rrset_roundrobin;
fdd92c
+	LOG_TAG_QUERYREPLY = config->log_tag_queryreply;
fdd92c
 	log_set_time_asc(config->log_time_ascii);
fdd92c
 	autr_permit_small_holddown = config->permit_small_holddown;
fdd92c
 }
fdd92c
@@ -2220,7 +2230,7 @@ void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
fdd92c
 	}
fdd92c
 }
fdd92c
 
fdd92c
-char* errinf_to_str(struct module_qstate* qstate)
fdd92c
+char* errinf_to_str_bogus(struct module_qstate* qstate)
fdd92c
 {
fdd92c
 	char buf[20480];
fdd92c
 	char* p = buf;
fdd92c
@@ -2245,6 +2255,31 @@ char* errinf_to_str(struct module_qstate* qstate)
fdd92c
 	return p;
fdd92c
 }
fdd92c
 
fdd92c
+char* errinf_to_str_servfail(struct module_qstate* qstate)
fdd92c
+{
fdd92c
+    char buf[20480];
fdd92c
+    char* p = buf;
fdd92c
+    size_t left = sizeof(buf);
fdd92c
+    struct config_strlist* s;
fdd92c
+    char dname[LDNS_MAX_DOMAINLEN+1];
fdd92c
+    char t[16], c[16];
fdd92c
+    sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
fdd92c
+    sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
fdd92c
+    dname_str(qstate->qinfo.qname, dname);
fdd92c
+    snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
fdd92c
+    left -= strlen(p); p += strlen(p);
fdd92c
+    if(!qstate->errinf)
fdd92c
+        snprintf(p, left, " misc failure");
fdd92c
+    else for(s=qstate->errinf; s; s=s->next) {
fdd92c
+        snprintf(p, left, " %s", s->str);
fdd92c
+        left -= strlen(p); p += strlen(p);
fdd92c
+    }
fdd92c
+    p = strdup(buf);
fdd92c
+    if(!p)
fdd92c
+        log_err("malloc failure in errinf_to_str");
fdd92c
+    return p;
fdd92c
+}
fdd92c
+
fdd92c
 void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
fdd92c
 {
fdd92c
 	char buf[1024];
fdd92c
diff --git a/util/config_file.h b/util/config_file.h
fdd92c
index 4206eb9..1e7f402 100644
fdd92c
--- a/util/config_file.h
fdd92c
+++ b/util/config_file.h
fdd92c
@@ -268,6 +268,12 @@ struct config_file {
fdd92c
 	int log_queries;
fdd92c
 	/** log replies with one line per reply */
fdd92c
 	int log_replies;
fdd92c
+	/** tag log_queries and log_replies for filtering */
fdd92c
+	int log_tag_queryreply;
fdd92c
+	/** log every local-zone hit **/
fdd92c
+	int log_local_actions;
fdd92c
+	/** log servfails with a reason */
fdd92c
+	int log_servfail;
fdd92c
 	/** log identity to report */
fdd92c
 	char* log_identity;
fdd92c
 
fdd92c
@@ -1070,7 +1076,15 @@ void errinf_dname(struct module_qstate* qstate, const char* str,
fdd92c
  * @return string or NULL on malloc failure (already logged).
fdd92c
  *    This string is malloced and has to be freed by caller.
fdd92c
  */
fdd92c
-char* errinf_to_str(struct module_qstate* qstate);
fdd92c
+char* errinf_to_str_bogus(struct module_qstate* qstate);
fdd92c
+
fdd92c
+/**
fdd92c
+ * Create error info in string.  For other servfails.
fdd92c
+ * @param qstate: query state.
fdd92c
+ * @return string or NULL on malloc failure (already logged).
fdd92c
+ *    This string is malloced and has to be freed by caller.
fdd92c
+ */
fdd92c
+char* errinf_to_str_servfail(struct module_qstate* qstate);
fdd92c
 
fdd92c
 /**
fdd92c
  * Used during options parsing
fdd92c
diff --git a/util/configlexer.lex b/util/configlexer.lex
fdd92c
index 6124e32..9b22db1 100644
fdd92c
--- a/util/configlexer.lex
fdd92c
+++ b/util/configlexer.lex
fdd92c
@@ -366,6 +366,9 @@ log-identity{COLON}		{ YDVAR(1, VAR_LOG_IDENTITY) }
fdd92c
 log-time-ascii{COLON}		{ YDVAR(1, VAR_LOG_TIME_ASCII) }
fdd92c
 log-queries{COLON}		{ YDVAR(1, VAR_LOG_QUERIES) }
fdd92c
 log-replies{COLON}		{ YDVAR(1, VAR_LOG_REPLIES) }
fdd92c
+log-tag-queryreply{COLON}      { YDVAR(1, VAR_LOG_TAG_QUERYREPLY) }
fdd92c
+log-local-actions{COLON}       { YDVAR(1, VAR_LOG_LOCAL_ACTIONS) }
fdd92c
+log-servfail{COLON}            { YDVAR(1, VAR_LOG_SERVFAIL) }
fdd92c
 local-zone{COLON}		{ YDVAR(2, VAR_LOCAL_ZONE) }
fdd92c
 local-data{COLON}		{ YDVAR(1, VAR_LOCAL_DATA) }
fdd92c
 local-data-ptr{COLON}		{ YDVAR(1, VAR_LOCAL_DATA_PTR) }
fdd92c
diff --git a/util/configparser.y b/util/configparser.y
fdd92c
index e34665a..4b23a71 100644
fdd92c
--- a/util/configparser.y
fdd92c
+++ b/util/configparser.y
fdd92c
@@ -106,7 +106,7 @@ extern struct config_parser_state* cfg_parser;
fdd92c
 %token VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING VAR_ADD_HOLDDOWN 
fdd92c
 %token VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE VAR_PREFETCH
fdd92c
 %token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT VAR_HARDEN_BELOW_NXDOMAIN
fdd92c
-%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES
fdd92c
+%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES VAR_LOG_LOCAL_ACTIONS
fdd92c
 %token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
fdd92c
 %token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
fdd92c
 %token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE
fdd92c
@@ -158,6 +158,8 @@ extern struct config_parser_state* cfg_parser;
fdd92c
 %token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
fdd92c
 %token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
fdd92c
 %token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT
fdd92c
+%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL
fdd92c
+%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
fdd92c
 
fdd92c
 %%
fdd92c
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
fdd92c
@@ -217,6 +219,7 @@ content_server: server_num_threads | server_verbosity | server_port |
fdd92c
 	server_edns_buffer_size | server_prefetch | server_prefetch_key |
fdd92c
 	server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag |
fdd92c
 	server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream |
fdd92c
+	server_log_local_actions |
fdd92c
 	server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
fdd92c
 	server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
fdd92c
 	server_so_reuseport | server_delay_close |
fdd92c
@@ -249,7 +252,9 @@ content_server: server_num_threads | server_verbosity | server_port |
fdd92c
 	server_ipsecmod_whitelist | server_ipsecmod_strict |
fdd92c
 	server_udp_upstream_without_downstream | server_aggressive_nsec |
fdd92c
 	server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |
fdd92c
-	server_low_rtt_permil | server_tls_win_cert
fdd92c
+	server_low_rtt_permil | server_tls_win_cert |
fdd92c
+	server_tcp_connection_limit | server_log_servfail |
fdd92c
+	server_unknown_server_time_limit | server_log_tag_queryreply
fdd92c
 	;
fdd92c
 stubstart: VAR_STUB_ZONE
fdd92c
 	{
fdd92c
@@ -764,6 +769,33 @@ server_log_replies: VAR_LOG_REPLIES STRING_ARG
fdd92c
   	free($2);
fdd92c
   }
fdd92c
   ;
fdd92c
+server_log_tag_queryreply: VAR_LOG_TAG_QUERYREPLY STRING_ARG
fdd92c
+  {
fdd92c
+    OUTYY(("P(server_log_tag_queryreply:%s)\n", $2));
fdd92c
+    if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
fdd92c
+        yyerror("expected yes or no.");
fdd92c
+    else cfg_parser->cfg->log_tag_queryreply = (strcmp($2, "yes")==0);
fdd92c
+    free($2);
fdd92c
+  }
fdd92c
+  ;
fdd92c
+server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG
fdd92c
+  {
fdd92c
+	OUTYY(("P(server_log_servfail:%s)\n", $2));
fdd92c
+	if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
fdd92c
+		yyerror("expected yes or no.");
fdd92c
+	else cfg_parser->cfg->log_servfail = (strcmp($2, "yes")==0);
fdd92c
+	free($2);
fdd92c
+  }
fdd92c
+  ;
fdd92c
+server_log_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG
fdd92c
+  {
fdd92c
+	OUTYY(("P(server_log_local_actions:%s)\n", $2));
fdd92c
+	if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
fdd92c
+		yyerror("expected yes or no.");
fdd92c
+	else cfg_parser->cfg->log_local_actions = (strcmp($2, "yes")==0);
fdd92c
+	free($2);
fdd92c
+  }
fdd92c
+  ;
fdd92c
 server_chroot: VAR_CHROOT STRING_ARG
fdd92c
 	{
fdd92c
 		OUTYY(("P(server_chroot:%s)\n", $2));
fdd92c
diff --git a/util/data/msgreply.c b/util/data/msgreply.c
fdd92c
index 772f5d1..df2131c 100644
fdd92c
--- a/util/data/msgreply.c
fdd92c
+++ b/util/data/msgreply.c
fdd92c
@@ -844,7 +844,9 @@ log_reply_info(enum verbosity_value v, struct query_info *qinf,
fdd92c
 	addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));
fdd92c
 	if(rcode == LDNS_RCODE_FORMERR)
fdd92c
 	{
fdd92c
-		log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);
fdd92c
+		if(LOG_TAG_QUERYREPLY)
fdd92c
+			log_reply("%s - - - %s - - - ", clientip_buf, rcode_buf);
fdd92c
+		else log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);
fdd92c
 	} else {
fdd92c
 		if(qinf->qname)
fdd92c
 			dname_str(qinf->qname, qname_buf);
fdd92c
@@ -852,7 +854,11 @@ log_reply_info(enum verbosity_value v, struct query_info *qinf,
fdd92c
 		pktlen = sldns_buffer_limit(rmsg);
fdd92c
 		sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));
fdd92c
 		sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));
fdd92c
-		log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
fdd92c
+		if(LOG_TAG_QUERYREPLY)
fdd92c
+			log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
fdd92c
+				clientip_buf, qname_buf, type_buf, class_buf,
fdd92c
+				rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
fdd92c
+		else log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
fdd92c
 			clientip_buf, qname_buf, type_buf, class_buf,
fdd92c
 			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
fdd92c
 	}
fdd92c
diff --git a/util/log.c b/util/log.c
fdd92c
index 43dd572..fff4319 100644
fdd92c
--- a/util/log.c
fdd92c
+++ b/util/log.c
fdd92c
@@ -391,6 +391,24 @@ log_hex(const char* msg, void* data, size_t length)
fdd92c
 	log_hex_f(verbosity, msg, data, length);
fdd92c
 }
fdd92c
 
fdd92c
+void
fdd92c
+log_query(const char *format, ...)
fdd92c
+{
fdd92c
+	va_list args;
fdd92c
+	va_start(args, format);
fdd92c
+	log_vmsg(LOG_INFO, "query", format, args);
fdd92c
+	va_end(args);
fdd92c
+}
fdd92c
+
fdd92c
+void
fdd92c
+log_reply(const char *format, ...)
fdd92c
+{
fdd92c
+	va_list args;
fdd92c
+	va_start(args, format);
fdd92c
+	log_vmsg(LOG_INFO, "reply", format, args);
fdd92c
+	va_end(args);
fdd92c
+}
fdd92c
+
fdd92c
 void log_buf(enum verbosity_value level, const char* msg, sldns_buffer* buf)
fdd92c
 {
fdd92c
 	if(verbosity < level)
fdd92c
diff --git a/util/log.h b/util/log.h
fdd92c
index 7bc3d9e..172cd01 100644
fdd92c
--- a/util/log.h
fdd92c
+++ b/util/log.h
fdd92c
@@ -160,6 +160,20 @@ void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
fdd92c
  */
fdd92c
 void log_hex(const char* msg, void* data, size_t length);
fdd92c
 
fdd92c
+/**
fdd92c
+ * Log query.
fdd92c
+ * Pass printf formatted arguments. No trailing newline is needed.
fdd92c
+ * @param format: printf-style format string. Arguments follow.
fdd92c
+ */
fdd92c
+void log_query(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
fdd92c
+
fdd92c
+/**
fdd92c
+ * Log reply.
fdd92c
+ * Pass printf formatted arguments. No trailing newline is needed.
fdd92c
+ * @param format: printf-style format string. Arguments follow.
fdd92c
+ */
fdd92c
+void log_reply(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
fdd92c
+
fdd92c
 /**
fdd92c
  * Easy alternative for log_hex, takes a sldns_buffer.
fdd92c
  * @param level: verbosity level for this message, compared to global 
fdd92c
diff --git a/util/net_help.c b/util/net_help.c
fdd92c
index a193c36..617a896 100644
fdd92c
--- a/util/net_help.c
fdd92c
+++ b/util/net_help.c
fdd92c
@@ -67,6 +67,9 @@ int MINIMAL_RESPONSES = 0;
fdd92c
 /** rrset order roundrobin: default is no */
fdd92c
 int RRSET_ROUNDROBIN = 0;
fdd92c
 
fdd92c
+/** log tag queries with name instead of 'info' for filtering */
fdd92c
+int LOG_TAG_QUERYREPLY = 0;
fdd92c
+
fdd92c
 /* returns true is string addr is an ip6 specced address */
fdd92c
 int
fdd92c
 str_is_ip6(const char* str)
fdd92c
@@ -335,7 +338,7 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
fdd92c
 {
fdd92c
 	char buf[LDNS_MAX_DOMAINLEN+1];
fdd92c
 	char t[12], c[12];
fdd92c
-	const char *ts, *cs; 
fdd92c
+	const char *ts, *cs;
fdd92c
 	if(verbosity < v)
fdd92c
 		return;
fdd92c
 	dname_str(name, buf);
fdd92c
@@ -361,6 +364,37 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,
fdd92c
 	log_info("%s %s %s %s", str, buf, ts, cs);
fdd92c
 }
fdd92c
 
fdd92c
+void
fdd92c
+log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)
fdd92c
+{
fdd92c
+    char buf[LDNS_MAX_DOMAINLEN+1];
fdd92c
+    char t[12], c[12];
fdd92c
+    const char *ts, *cs;
fdd92c
+    dname_str(name, buf);
fdd92c
+    if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";
fdd92c
+    else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";
fdd92c
+    else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";
fdd92c
+    else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";
fdd92c
+    else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";
fdd92c
+    else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";
fdd92c
+    else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)
fdd92c
+        ts = sldns_rr_descript(type)->_name;
fdd92c
+    else {
fdd92c
+        snprintf(t, sizeof(t), "TYPE%d", (int)type);
fdd92c
+        ts = t;
fdd92c
+    }
fdd92c
+    if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&
fdd92c
+        sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)
fdd92c
+        cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;
fdd92c
+    else {
fdd92c
+        snprintf(c, sizeof(c), "CLASS%d", (int)dclass);
fdd92c
+        cs = c;
fdd92c
+    }
fdd92c
+    if(LOG_TAG_QUERYREPLY)
fdd92c
+            log_query("%s %s %s %s", str, buf, ts, cs);
fdd92c
+    else    log_info("%s %s %s %s", str, buf, ts, cs);
fdd92c
+}
fdd92c
+
fdd92c
 void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 
fdd92c
 	struct sockaddr_storage* addr, socklen_t addrlen)
fdd92c
 {
fdd92c
diff --git a/util/net_help.h b/util/net_help.h
fdd92c
index de2e1ac..f2e0e43 100644
fdd92c
--- a/util/net_help.h
fdd92c
+++ b/util/net_help.h
fdd92c
@@ -99,6 +99,9 @@ extern int MINIMAL_RESPONSES;
fdd92c
 /** rrset order roundrobin */
fdd92c
 extern int RRSET_ROUNDROBIN;
fdd92c
 
fdd92c
+/** log tag queries with name instead of 'info' for filtering */
fdd92c
+extern int LOG_TAG_QUERYREPLY;
fdd92c
+
fdd92c
 /**
fdd92c
  * See if string is ip4 or ip6.
fdd92c
  * @param str: IP specification.
fdd92c
@@ -235,6 +238,12 @@ void sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen,
fdd92c
 void log_nametypeclass(enum verbosity_value v, const char* str, 
fdd92c
 	uint8_t* name, uint16_t type, uint16_t dclass);
fdd92c
 
fdd92c
+/**
fdd92c
+ * Like log_nametypeclass, but logs with log_query for query logging
fdd92c
+ */
fdd92c
+void log_query_in(const char* str, uint8_t* name, uint16_t type,
fdd92c
+       uint16_t dclass);
fdd92c
+
fdd92c
 /**
fdd92c
  * Compare two sockaddrs. Imposes an ordering on the addresses.
fdd92c
  * Compares address and port.
fdd92c
diff --git a/validator/val_kcache.c b/validator/val_kcache.c
fdd92c
index 22070cc..e0b88b6 100644
fdd92c
--- a/validator/val_kcache.c
fdd92c
+++ b/validator/val_kcache.c
fdd92c
@@ -89,7 +89,7 @@ key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey,
fdd92c
 	if(key_entry_isbad(k) && qstate->errinf &&
fdd92c
 		qstate->env->cfg->val_log_level >= 2) {
fdd92c
 		/* on malloc failure there is simply no reason string */
fdd92c
-		key_entry_set_reason(k, errinf_to_str(qstate));
fdd92c
+		key_entry_set_reason(k, errinf_to_str_bogus(qstate));
fdd92c
 	}
fdd92c
 	key_entry_hash(k);
fdd92c
 	slabhash_insert(kcache->slab, k->entry.hash, &k->entry, 
fdd92c
diff --git a/validator/validator.c b/validator/validator.c
fdd92c
index 5777b29..2d9cc17 100644
fdd92c
--- a/validator/validator.c
fdd92c
+++ b/validator/validator.c
fdd92c
@@ -2227,13 +2227,15 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
fdd92c
 		vq->orig_msg->rep->ttl = ve->bogus_ttl;
fdd92c
 		vq->orig_msg->rep->prefetch_ttl = 
fdd92c
 			PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl);
fdd92c
-		if(qstate->env->cfg->val_log_level >= 1 &&
fdd92c
+		if((qstate->env->cfg->val_log_level >= 1 ||
fdd92c
+			qstate->env->cfg->log_servfail) &&
fdd92c
 			!qstate->env->cfg->val_log_squelch) {
fdd92c
-			if(qstate->env->cfg->val_log_level < 2)
fdd92c
+            if(qstate->env->cfg->val_log_level < 2 &&
fdd92c
+				!qstate->env->cfg->log_servfail)
fdd92c
 				log_query_info(0, "validation failure",
fdd92c
 					&qstate->qinfo);
fdd92c
 			else {
fdd92c
-				char* err = errinf_to_str(qstate);
fdd92c
+				char* err = errinf_to_str_bogus(qstate);
fdd92c
 				if(err) log_info("%s", err);
fdd92c
 				free(err);
fdd92c
 			}
fdd92c
@@ -2332,6 +2334,7 @@ processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,
fdd92c
 
fdd92c
 	if(vq->dlv_status == dlv_error) {
fdd92c
 		verbose(VERB_QUERY, "failed DLV lookup");
fdd92c
+		errinf(qstate, "failed DLV lookup");
fdd92c
 		return val_error(qstate, id);
fdd92c
 	} else if(vq->dlv_status == dlv_success) {
fdd92c
 		uint8_t* nm;