]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] dnstap size and versions options
authorEvan Hunt <each@isc.org>
Tue, 7 Feb 2017 00:03:37 +0000 (16:03 -0800)
committerEvan Hunt <each@isc.org>
Tue, 7 Feb 2017 00:34:58 +0000 (16:34 -0800)
4572. [func] The "dnstap-output" option can now take "size" and
"versions" parameters to indicate the maximum size
a dnstap log file can grow before rolling to a new
file, and how many old files to retain. [RT #44502]

12 files changed:
CHANGES
bin/named/server.c
bin/tests/system/dnstap/bad-size-version.conf [new file with mode: 0644]
bin/tests/system/dnstap/good-size-version.conf [new file with mode: 0644]
bin/tests/system/dnstap/ns1/named.conf
bin/tests/system/dnstap/tests.sh
doc/arm/Bv9ARM-book.xml
doc/arm/notes.xml
lib/bind9/check.c
lib/dns/dnstap.c
lib/dns/include/dns/dnstap.h
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 990b2452700d42a41822e0f4f1678abcce541bb7..404f3856f43a99a24c8fa1018f46f2daaa6ddbce 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+4572.  [func]          The "dnstap-output" option can now take "size" and
+                       "versions" parameters to indicate the maximum size
+                       a dnstap log file can grow before rolling to a new
+                       file, and how many old files to retain. [RT #44502]
+
 4571.  [bug]           Out-of-tree builds of backtrace_test failed.
 
 4570.  [cleanup]       named did not correctly fall back to the built-in
index 521f745b9ec933f362e2a808d5308f6592748916..f7c8cc19fddca4294b247f0c716c87849080676a 100644 (file)
@@ -3036,7 +3036,6 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
        const char *dpath = ns_g_defaultdnstap;
        const cfg_obj_t *dlist = NULL;
        dns_dtmsgtype_t dttypes = 0;
-       dns_dtmode_t dmode;
        unsigned int i;
        struct fstrm_iothr_options *fopt = NULL;
 
@@ -3086,6 +3085,9 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
        }
 
        if (ns_g_server->dtenv == NULL && dttypes != 0) {
+               dns_dtmode_t dmode;
+               isc_uint64_t max_size = 0;
+               isc_uint32_t rolls = 0;
                obj = NULL;
                CHECKM(ns_config_get(maps, "dnstap-output", &obj),
                       "'dnstap-output' must be set if 'dnstap' is set");
@@ -3104,6 +3106,32 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
 
                dpath = cfg_obj_asstring(obj2);
 
+               obj2 = cfg_tuple_get(obj, "size");
+               if (obj2 != NULL && cfg_obj_isuint64(obj2)) {
+                       max_size = cfg_obj_asuint64(obj2);
+                       if (max_size > SIZE_MAX) {
+                               cfg_obj_log(obj2, ns_g_lctx,
+                                   ISC_LOG_WARNING,
+                                   "'dnstap-output size "
+                                   "%" ISC_PRINT_QUADFORMAT "u' "
+                                   "is too large for this "
+                                   "system; reducing to %lu",
+                                   max_size, (unsigned long)SIZE_MAX);
+                               max_size = SIZE_MAX;
+                       }
+               }
+
+               obj2 = cfg_tuple_get(obj, "versions");
+               if (obj2 != NULL && cfg_obj_isuint32(obj2)) {
+                       rolls = cfg_obj_asuint32(obj2);
+               } else if (obj2 != NULL && cfg_obj_isstring(obj2) &&
+                        strcasecmp(cfg_obj_asstring(obj2), "unlimited") == 0)
+               {
+                       rolls = ISC_LOG_ROLLINFINITE;
+               } else {
+                       rolls = ISC_LOG_ROLLNEVER;
+               }
+
                fopt = fstrm_iothr_options_init();
                fstrm_iothr_options_set_num_input_queues(fopt, ns_g_cpus);
                fstrm_iothr_options_set_queue_model(fopt,
@@ -3168,9 +3196,12 @@ configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
                        fstrm_iothr_options_set_reopen_interval(fopt, i);
                }
 
-               CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath, &fopt,
-                                    &ns_g_server->dtenv),
+               CHECKM(dns_dt_create(ns_g_mctx, dmode, dpath,
+                                    &fopt, &ns_g_server->dtenv),
                       "unable to create dnstap environment");
+
+               CHECKM(dns_dt_setupfile(ns_g_server->dtenv, max_size, rolls),
+                      "unable to set up dnstap logfile");
        }
 
        if (ns_g_server->dtenv == NULL)
@@ -13689,7 +13720,7 @@ ns_server_dnstap(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) {
        }
 
        if (reopen || strcasecmp(ptr, "-reopen") == 0) {
-               backups = -1;
+               backups = ISC_LOG_ROLLNEVER;
        } else if ((strcasecmp(ptr, "-roll") == 0)) {
                unsigned int n;
                ptr = next_token(lex, text);
diff --git a/bin/tests/system/dnstap/bad-size-version.conf b/bin/tests/system/dnstap/bad-size-version.conf
new file mode 100644 (file)
index 0000000..3fb6bc5
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2016  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+       dnstap-output unix "/tmp/dnstap.sock" size 10k versions 3;
+};
diff --git a/bin/tests/system/dnstap/good-size-version.conf b/bin/tests/system/dnstap/good-size-version.conf
new file mode 100644 (file)
index 0000000..417f600
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2016  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+options {
+       dnstap-output file "/tmp/dnstap.log" size 10k versions 3;
+};
index cadf23e5d1019c970d10830091fe8e6e50205ddc..8d7b27cfa4d0329c4c2de94519a23fc932ced31c 100644 (file)
@@ -21,7 +21,7 @@ options {
        statistics-file "named.stats";
        dnstap-identity "ns1";
        dnstap-version "xxx";
-       dnstap-output file "dnstap.out";
+       dnstap-output file "dnstap.out" size 30k versions 10;
        dnstap { all; };
        send-cookie no;
        require-server-cookie no;
index 06fc24a9420bb189165c26d34b6f65968c6569d9..1a6ba6066c97a0b08b837f9905ec1402dbcfaba1 100644 (file)
@@ -349,7 +349,7 @@ if [ -n "$PYTHON" ] ; then
        $PYTHON -c "import yaml" && HAS_PYYAML=1
 fi
 
-if [ $HAS_PYYAML ] ; then
+if [ $HAS_PYYAML -ne 0 ] ; then
        echo "I:checking dnstap-read YAML output"
        ret=0
        $PYTHON ydump.py "$DNSTAPREAD" "ns3/dnstap.out.save" > /dev/null || ret=1
index f37b2cb9bdab02f2a7eebebda4dfaaf35966d102..0f889ba37a789159c6a4573add4f3d5cd1431526 100644 (file)
@@ -4416,7 +4416,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
   [ <command>server-id</command> <replaceable>server_id_string</replaceable> ; ]
   [ <command>directory</command> <replaceable>path_name</replaceable> ; ]
   [ <command>dnstap {</command> <replaceable>message_type</replaceable> ; ... <command>}</command> ; ]
-  [ <command>dnstap-output</command> ( <option>file</option> | <option>unix</option> ) <replaceable>path_name</replaceable> ; ]
+  [ <command>dnstap-output</command> ( <option>file</option> | <option>unix</option> ) <replaceable>path_name</replaceable> [ <command>size</command> <replaceable>size_spec</replaceable> ] [ <command>versions</command> ( <replaceable>number</replaceable> | <option>unlimited</option> ) ] ; ]
   [ <command>dnstap-identity</command> ( <replaceable>string</replaceable> | <option>hostname</option> | <option>none</option> ) ; ]
   [ <command>dnstap-version</command> ( <replaceable>string</replaceable> | <option>none</option> ) ; ]
   [ <command>fstrm-set-buffer-hint</command> <replaceable>number</replaceable> ; ]
@@ -5000,6 +5000,19 @@ badresp:1,adberr:0,findfail:0,valfail:0]
                (provided with <command>libfstrm</command>) is listening on
                the socket.)
              </para>
+             <para>
+               If the first argument is <literal>file</literal>, then
+               two additional options can be added:
+               <command>size</command> indicates the size to which a
+               <command>dnstap</command> log file can grow before being
+               rolled to a new file, and <command>versions</command>
+               specifies the number of rolled log files to retain. These
+               are similar to the <command>size</command> and
+               <command>versions</command> options in a
+               <command>logging</comamnd> channel.  The default
+               is to allow <command>dnstap</command> log files to grow to
+               any size without rolling.
+             </para>
              <para>
                <command>dnstap-output</command> can only be set globally
                in <command>options</command>. Currently, it can only be
index 4121401aa7aeb7077f409bfc1ed045e62d185b56..68357837f1d1d268a1aae193db29841a54dc794f 100644 (file)
 
   <section xml:id="relnotes_features"><info><title>New Features</title></info>
     <itemizedlist>
+      <listitem>
+       <para>
+         <command>dnstap</command> logfiles can now be configured to
+         automatically roll when they reach a specified size. If
+         <command>dnstap-output</command> is configured with mode
+         <literal>file</command>, then it can take optional
+         <command>size</command> and <command>versions</command>
+         key-value arguments to set the logfile rolling parameters.
+         (These have the same semantics as the corresponding
+         options in a <command>logging</command> channel statement.)
+         [RT #44502]
+       </para>
+      </listitem>
       <listitem>
        <para>
          <command>dig +ednsopt</command> now accepts the names
index c13b947eed9dba4c014c5e68ccf969368d9b7e90..34ce342adec18db0b220f875ddf919aba25eded9 100644 (file)
@@ -1437,6 +1437,46 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
                        }
                }
        }
+
+       /* Check that dnstap-ouput values are consistent */
+       obj = NULL;
+       (void) cfg_map_get(options, "dnstap-output", &obj);
+       if (obj != NULL) {
+               const cfg_obj_t *obj2;
+               dns_dtmode_t dmode;
+
+               obj2 = cfg_tuple_get(obj, "mode");
+               if (obj2 == NULL) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "dnstap-output mode not found");
+                       return (ISC_R_FAILURE);
+               }
+
+               if (strcasecmp(cfg_obj_asstring(obj2), "file") == 0)
+                       dmode = dns_dtmode_file;
+               else
+                       dmode = dns_dtmode_unix;
+
+               obj2 = cfg_tuple_get(obj, "size");
+               if (obj2 != NULL && !cfg_obj_isvoid(obj2) &&
+                   dmode == dns_dtmode_unix)
+               {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "dnstap-output size "
+                                   "cannot be set with mode unix");
+                       return (ISC_R_FAILURE);
+               }
+
+               obj2 = cfg_tuple_get(obj, "versions");
+               if (obj2 != NULL && !cfg_obj_isvoid(obj2) &&
+                   dmode == dns_dtmode_unix)
+               {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "dnstap-output versions "
+                                   "cannot be set with mode unix");
+                       return (ISC_R_FAILURE);
+               }
+       }
 #endif
 
        return (result);
index 11a97b80ec09a8ac6e36d5fc71c608d040d898ac..e8b4564f64fa7e26a228588e83feac662d51abdd 100644 (file)
@@ -104,6 +104,8 @@ struct dns_dtenv {
        isc_region_t version;
        char *path;
        dns_dtmode_t mode;
+       isc_uint64_t max_size;
+       isc_uint32_t rolls;
        isc_stats_t *stats;
 };
 
@@ -241,6 +243,8 @@ dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
                CHECK(ISC_R_FAILURE);
        }
        env->mode = mode;
+       env->max_size = 0;
+       env->rolls = ISC_LOG_ROLLNEVER;
        env->fopt = *foptp;
        *foptp = NULL;
 
@@ -274,6 +278,22 @@ dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
        return (result);
 }
 
+isc_result_t
+dns_dt_setupfile(dns_dtenv_t *env, isc_uint64_t max_size, int rolls) {
+       REQUIRE(VALID_DTENV(env));
+
+       if (max_size != 0 && rolls != ISC_LOG_ROLLNEVER &&
+           env->mode != dns_dtmode_file)
+       {
+               return (ISC_R_INVALIDFILE);
+       }
+
+       env->max_size = max_size;
+       env->rolls = rolls;
+
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_dt_reopen(dns_dtenv_t *env, int roll) {
        isc_result_t result = ISC_R_SUCCESS;
@@ -691,6 +711,14 @@ dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype,
 
        REQUIRE(VALID_DTENV(view->dtenv));
 
+       if (view->dtenv->max_size != 0) {
+               struct stat statbuf;
+               if (stat(view->dtenv->path, &statbuf) >= 0 &&
+                   (size_t) statbuf.st_size > view->dtenv->max_size) {
+                       dns_dt_reopen(view->dtenv, view->dtenv->rolls);
+               }
+       }
+
        TIME_NOW(&now);
        t = &now;
 
index 7f6793b22ae93c05daf910552a5f098f7a51f63a..81f270677572f022674ba8c0cd67842f178e9465 100644 (file)
@@ -152,6 +152,24 @@ dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path,
  *\li  Other errors are possible.
  */
 
+isc_result_t
+dns_dt_setupfile(dns_dtenv_t *env, isc_uint64_t max_size, int rolls);
+/*%<
+ * Sets up the dnstap logfile limits.
+ *
+ * 'max_size' is the size a log file may grow before it is rolled
+ *
+ * 'rolls' is the number of rolled files to retain.
+ *
+ * Requires:
+ *
+ *\li  'env' is a valid dnstap environment.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS on success
+ *\li  #ISC_R_INVALIDFILE if dnstap is set to use a UNIX domain socket
+ */
+
 isc_result_t
 dns_dt_reopen(dns_dtenv_t *env, int roll);
 /*%<
index af9a57e97772780ae6c997e261a173b874e93572..db37d616f2b21ffff9d65c69fc5043df54c3a49e 100644 (file)
@@ -107,6 +107,7 @@ static cfg_type_t cfg_type_key;
 static cfg_type_t cfg_type_logfile;
 static cfg_type_t cfg_type_logging;
 static cfg_type_t cfg_type_logseverity;
+static cfg_type_t cfg_type_logversions;
 static cfg_type_t cfg_type_lwres;
 static cfg_type_t cfg_type_masterselement;
 static cfg_type_t cfg_type_maxttl;
@@ -1297,6 +1298,18 @@ static cfg_type_t cfg_type_dnstap = {
 /*%
  * dnstap-output
  */
+static keyword_type_t dtsize_kw = { "size", &cfg_type_sizenodefault};
+static cfg_type_t cfg_type_dnstap_size = {
+       "dnstap_size", parse_optional_keyvalue, print_keyvalue,
+       doc_optional_keyvalue, &cfg_rep_uint64, &dtsize_kw
+};
+
+static keyword_type_t dtversions_kw = { "versions", &cfg_type_logversions};
+static cfg_type_t cfg_type_dnstap_versions = {
+       "dnstap_versions", parse_optional_keyvalue, print_keyvalue,
+       doc_optional_keyvalue, &cfg_rep_uint32, &dtversions_kw
+};
+
 static const char *dtoutmode_enums[] = { "file", "unix", NULL };
 static cfg_type_t cfg_type_dtmode = {
        "dtmode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
@@ -1306,6 +1319,8 @@ static cfg_type_t cfg_type_dtmode = {
 static cfg_tuplefielddef_t dtout_fields[] = {
        { "mode", &cfg_type_dtmode, 0 },
        { "path", &cfg_type_qstring, 0 },
+       { "size", &cfg_type_dnstap_size, 0 },
+       { "versions", &cfg_type_dnstap_versions, 0 },
        { NULL, NULL, 0 }
 };
 
@@ -2384,7 +2399,6 @@ static cfg_type_t cfg_type_sizenodefault = {
 /*%
  * A size in absolute values or percents.
  */
-
 static cfg_type_t cfg_type_sizeval_percent = {
        "sizeval_percent", parse_sizeval_percent, cfg_print_ustring,
        doc_sizeval_percent, &cfg_rep_string, NULL