#endif
"\
prefetch 2 9;\n\
+# querylog <boolean>;\n\
recursing-file \"named.recursing\";\n\
recursive-clients 1000;\n\
request-nsid false;\n\
resolver-query-timeout 10;\n\
+# responselog <boolean>;\n\
rrset-order { order random; };\n\
secroots-file \"named.secroots\";\n\
send-cookie true;\n\
result = named_server_refreshcommand(named_g_server, lex, text);
} else if (command_compare(command, NAMED_COMMAND_RELOAD)) {
result = named_server_reloadcommand(named_g_server, lex, text);
+ } else if (command_compare(command, NAMED_COMMAND_RESPONSELOG)) {
+ result = named_server_toggleresponselog(named_g_server, lex);
} else if (command_compare(command, NAMED_COMMAND_RETRANSFER)) {
result = named_server_retransfercommand(named_g_server, lex,
text);
#define NAMED_COMMAND_RECURSING "recursing"
#define NAMED_COMMAND_REFRESH "refresh"
#define NAMED_COMMAND_RELOAD "reload"
+#define NAMED_COMMAND_RESPONSELOG "responselog"
#define NAMED_COMMAND_RETRANSFER "retransfer"
#define NAMED_COMMAND_SCAN "scan"
#define NAMED_COMMAND_SECROOTS "secroots"
* but can also be used as a toggle for backward comptibility.)
*/
+isc_result_t
+named_server_toggleresponselog(named_server_t *server, isc_lex_t *lex);
+/*%<
+ * Enable/disable logging of responses. (Takes "yes" or "no" argument,
+ * but can also be used as a toggle for backward comptibility.)
+ */
+
/*%
* Save the current NTAs for all views to files.
*/
}
}
}
+ obj = NULL;
+ result = named_config_get(maps, "responselog", &obj);
+ if (result == ISC_R_SUCCESS) {
+ ns_server_setoption(server->sctx,
+ NS_SERVER_LOGRESPONSES,
+ cfg_obj_asboolean(obj));
+ }
}
obj = NULL;
isc_result_t
named_server_togglequerylog(named_server_t *server, isc_lex_t *lex) {
bool prev, value;
- char *ptr;
+ char *ptr = NULL;
/* Skip the command name. */
ptr = next_token(lex, NULL);
return (ISC_R_SUCCESS);
}
+isc_result_t
+named_server_toggleresponselog(named_server_t *server, isc_lex_t *lex) {
+ bool prev, value;
+ char *ptr = NULL;
+
+ /* Skip the command name. */
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ return (ISC_R_UNEXPECTEDEND);
+ }
+
+ prev = ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES);
+
+ ptr = next_token(lex, NULL);
+ if (ptr == NULL) {
+ value = !prev;
+ } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
+ !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
+ {
+ value = true;
+ } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
+ !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
+ {
+ value = false;
+ } else {
+ return (DNS_R_SYNTAX);
+ }
+
+ if (value == prev) {
+ return (ISC_R_SUCCESS);
+ }
+
+ ns_server_setoption(server->sctx, NS_SERVER_LOGRESPONSES, value);
+
+ isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "response logging is now %s",
+ value ? "on" : "off");
+ return (ISC_R_SUCCESS);
+}
+
static isc_result_t
listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family,
: "OFF");
CHECK(putstr(text, line));
+ snprintf(line, sizeof(line), "response logging is %s\n",
+ ns_server_getoption(server->sctx, NS_SERVER_LOGRESPONSES)
+ ? "ON"
+ : "OFF");
+ CHECK(putstr(text, line));
+
snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n",
isc_quota_getused(&server->sctx->recursionquota),
isc_quota_getsoft(&server->sctx->recursionquota),
.. program:: rndc
+.. option:: responselog [on | off]
+
+ This command enables or disables response logging. For backward compatibility,
+ this command can also be used without an argument to toggle response logging
+ on and off.
+
+ Unlike query logging, response logging cannot be enabled by explicitly directing
+ the ``responses`` ``category`` to a ``channel`` in the ``logging`` section
+ of :iscman:`named.conf`, but it can still be enabled by specifying
+ ``responselog yes;`` in the ``options`` section of :iscman:`named.conf`.
+
.. option:: retransfer [-force] zone [class [view]]
This command retransfers the given secondary zone from the primary server.
NSID options received from upstream servers.
``queries``
- A location where queries should be logged.
+ The locations where queries should be logged.
At startup, specifying the category ``queries`` also enables query logging unless the :any:`querylog` option has been specified.
``resolver``
DNS resolution, such as the recursive lookups performed on behalf of clients by a caching name server.
+``responses``
+ The locations where query response summaries should be logged.
+
``rpz``
Information about errors in response policy zone files, rewritten responses, and, at the highest ``debug`` levels, mere rewriting attempts.
resolver-use-dns64 <boolean>;
response-padding { <address_match_element>; ... } block-size <integer>;
response-policy { zone <string> [ add-soa <boolean> ] [ log <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ policy ( cname | disabled | drop | given | no-op | nodata | nxdomain | passthru | tcp-only <quoted_string> ) ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ ede <string> ]; ... } [ add-soa <boolean> ] [ break-dnssec <boolean> ] [ max-policy-ttl <duration> ] [ min-update-interval <duration> ] [ min-ns-dots <integer> ] [ nsip-wait-recurse <boolean> ] [ nsdname-wait-recurse <boolean> ] [ qname-wait-recurse <boolean> ] [ recursive-only <boolean> ] [ nsip-enable <boolean> ] [ nsdname-enable <boolean> ] [ dnsrps-enable <boolean> ] [ dnsrps-options { <unspecified-text> } ];
+ responselog <boolean>;
reuseport <boolean>;
root-key-sentinel <boolean>;
rrset-order { [ class <string> ] [ type <string> ] [ name <quoted_string> ] <string> <string>; ... };
NS_LOGCATEGORY_QUERY_ERRORS,
NS_LOGCATEGORY_TAT,
NS_LOGCATEGORY_SERVE_STALE,
+ NS_LOGCATEGORY_RESPONSES,
/* cfg categories */
CFG_LOGCATEGORY_CONFIG,
/* named categories */
[NS_LOGCATEGORY_QUERY_ERRORS] = "query-errors",
[NS_LOGCATEGORY_TAT] = "trust-anchor-telemetry",
[NS_LOGCATEGORY_SERVE_STALE] = "serve-stale",
+ [NS_LOGCATEGORY_RESPONSES] = "responses",
/* cfg categories */
[CFG_LOGCATEGORY_CONFIG] = "config",
/* named categories */
{ "recursive-clients", &cfg_type_uint32, 0 },
{ "reuseport", &cfg_type_boolean, 0 },
{ "reserved-sockets", &cfg_type_uint32, CFG_CLAUSEFLAG_ANCIENT },
+ { "responselog", &cfg_type_boolean, 0 },
{ "secroots-file", &cfg_type_qstring, 0 },
{ "serial-queries", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "serial-query-rate", &cfg_type_uint32, 0 },
#define NS_SERVER_TRANSFERINSECS 0x00008000U /*%< -T transferinsecs */
#define NS_SERVER_TRANSFERSLOWLY 0x00010000U /*%< -T transferslowly */
#define NS_SERVER_TRANSFERSTUCK 0x00020000U /*%< -T transferstuck */
+#define NS_SERVER_LOGRESPONSES 0x00040000U /*%< log responses */
/*%
* Type for callback function to get hostname.
#include <dns/nsec3.h>
#include <dns/order.h>
#include <dns/rbt.h>
+#include <dns/rcode.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatalist.h>
}
}
+static inline void
+log_response(ns_client_t *client, dns_rcode_t rcode) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ char rcodebuf[20];
+ isc_buffer_t b;
+ int level = ISC_LOG_INFO;
+
+ if (!isc_log_wouldlog(level))
+ return;
+
+ dns_name_format(client->query.origqname, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->message->rdclass, classbuf,
+ sizeof(classbuf));
+ dns_rdatatype_format(client->query.qtype, typebuf, sizeof(typebuf));
+ isc_buffer_init(&b, rcodebuf, sizeof(rcodebuf));
+ dns_rcode_totext(rcode, &b);
+
+ ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY, level,
+ "response: %s %s %s %.*s", namebuf, classbuf, typebuf,
+ (int)isc_buffer_usedlength(&b), rcodebuf);
+}
+
static void
query_send(ns_client_t *client) {
isc_statscounter_t counter;
counter = ns_statscounter_failure;
}
+ if ((client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0) {
+ log_response(client, client->message->rcode);
+ }
+
inc_stats(client, counter);
ns_client_send(client);
static void
query_error(ns_client_t *client, isc_result_t result, int line) {
int loglevel = ISC_LOG_DEBUG(3);
+ dns_rcode_t rcode;
- switch (dns_result_torcode(result)) {
+ rcode = dns_result_torcode(result);
+ switch (rcode) {
case dns_rcode_servfail:
loglevel = ISC_LOG_DEBUG(1);
inc_stats(client, ns_statscounter_servfail);
log_queryerror(client, result, line, loglevel);
+ if (client->query.origqname != NULL &&
+ (client->manager->sctx->options & NS_SERVER_LOGRESPONSES) != 0)
+ {
+ log_response(client, rcode);
+ }
+
ns_client_error(client, result);
if (!client->nodetach) {
fi
done
if test $ok = no; then
- echo "$i missing from documentation."
+ echo "$i missing from doc/arm/logging-categories.rst."
status=1
fi
done
fi
done
if test $ok = no; then
- echo "$i not in code."
+ echo "documented logging category '$i' not in code."
status=1
fi
done