]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
unbound-checkconf.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 26 Sep 2007 13:39:49 +0000 (13:39 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 26 Sep 2007 13:39:49 +0000 (13:39 +0000)
git-svn-id: file:///svn/unbound/trunk@647 be551aaa-1e26-0410-a405-d3ace91eadb9

Makefile.in
checkconf/unbound-checkconf.c [new file with mode: 0644]
doc/Changelog
doc/unbound-checkconf.8 [new file with mode: 0644]
doc/unbound.8
doc/unbound.conf.5
iterator/iter_hints.c
util/log.c

index d34284828b9f37a393fdf57c697dff9763705838..fe457deb4eb01d951403d1c89b50906237ae9035 100644 (file)
@@ -62,6 +62,8 @@ UNITTEST_SRC=$(wildcard testcode/unit*.c) testcode/readhex.c \
 UNITTEST_OBJ=$(addprefix $(BUILD),$(UNITTEST_SRC:.c=.o)) $(COMPAT_OBJ)
 DAEMON_SRC=$(wildcard daemon/*.c) $(COMMON_SRC)
 DAEMON_OBJ=$(addprefix $(BUILD),$(DAEMON_SRC:.c=.o)) $(COMPAT_OBJ)
+CHECKCONF_SRC=checkconf/unbound-checkconf.c $(COMMON_SRC)
+CHECKCONF_OBJ=$(addprefix $(BUILD),$(CHECKCONF_SRC:.c=.o)) $(COMPAT_OBJ)
 TESTBOUND_SRC=testcode/testbound.c testcode/ldns-testpkts.c \
        daemon/worker.c daemon/daemon.c daemon/stats.c testcode/replay.c \
        testcode/fake_event.c $(filter-out util/netevent.c \
@@ -92,7 +94,7 @@ $(BUILD)%.o:    $(srcdir)/%.c
 
 .PHONY:        clean realclean doc lint all install uninstall tests test
 
-all:   $(COMMON_OBJ) unbound 
+all:   $(COMMON_OBJ) unbound unbound-checkconf
 
 tests: unittest testbound lock-verify pktview signit memstats
 
@@ -103,6 +105,10 @@ unbound:   $(DAEMON_OBJ)
        $(INFO) Link $@
        $Q$(LINK) -o $@ $^ $(LIBS)
 
+unbound-checkconf:     $(CHECKCONF_OBJ)
+       $(INFO) Link $@
+       $Q$(LINK) -o $@ $^ $(LIBS)
+
 unittest:      $(UNITTEST_OBJ)
        $(INFO) Link $@
        $Q$(LINK) -o $@ $^ $(LIBS)
@@ -181,12 +187,14 @@ install:
        $(INSTALL) -d $(mandir)/man8
        $(INSTALL) -d $(mandir)/man5
        $(LIBTOOL) --mode=install cp unbound $(bindir)/unbound
+       $(LIBTOOL) --mode=install cp unbound-checkconf $(bindir)/unbound-checkconf
        $(INSTALL) -c -m 644 $(srcdir)/doc/unbound.8 $(mandir)/man8
+       $(INSTALL) -c -m 644 $(srcdir)/doc/unbound-checkconf.8 $(mandir)/man8
        $(INSTALL) -c -m 644 $(srcdir)/doc/unbound.conf.5 $(mandir)/man5
 
 uninstall:
-       rm -f -- $(bindir)/unbound 
-       rm -f -- $(mandir)/man8/unbound.8 $(mandir)/man5/unbound.conf.5
+       rm -f -- $(bindir)/unbound $(bindir)/unbound-checkconf
+       rm -f -- $(mandir)/man8/unbound.8 $(mandir)/man8/unbound-checkconf.8 $(mandir)/man5/unbound.conf.5
 
 # Automatic dependencies.
 $(BUILD)%.d: $(srcdir)/%.c
diff --git a/checkconf/unbound-checkconf.c b/checkconf/unbound-checkconf.c
new file mode 100644 (file)
index 0000000..02480ca
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * checkconf/unbound-checkconf.c - config file checker for unbound.conf file.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * The config checker checks for syntax and other errors in the unbound.conf
+ * file, and can be used to check for errors before the server is started
+ * or sigHUPped.
+ * Exit status 1 means an error.
+ */
+
+#include "config.h"
+#include "util/log.h"
+#include "util/config_file.h"
+#include "util/module.h"
+#include "util/region-allocator.h"
+#include "iterator/iterator.h"
+#include "validator/validator.h"
+#include <pwd.h>
+
+/** Give checkconf usage, and exit (1). */
+static void
+usage()
+{
+       printf("Usage:  unbound-checkconf [options] file\n");
+       printf("        Checks unbound configuration file for errors.\n");
+       printf("-h      show this usage help.\n");
+       printf("Version %s\n", PACKAGE_VERSION);
+       printf("BSD licensed, see LICENSE in source package for details.\n");
+       printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
+       exit(1);
+}
+
+/** check if module works with config */
+static void
+check_mod(struct config_file* cfg, struct module_func_block* fb)
+{
+       struct module_env env;
+       memset(&env, 0, sizeof(env));
+       env.cfg = cfg;
+       env.scratch = region_create(malloc, free);
+       env.scratch_buffer = ldns_buffer_new(BUFSIZ);
+       if(!(*fb->init)(&env, 0)) {
+               fatal_exit("bad config for %s module", fb->name);
+       }
+       (*fb->deinit)(&env, 0);
+       ldns_buffer_free(env.scratch_buffer);
+       region_destroy(env.scratch);
+}
+
+/** check configuration for errors */
+static void
+morechecks(struct config_file* cfg)
+{
+       if(cfg->verbosity < 0)
+               fatal_exit("verbosity value < 0");
+       if(cfg->num_threads < 0 || cfg->num_threads > 10000)
+               fatal_exit("num_threads value weird");
+       if(!cfg->do_ip4 && !cfg->do_ip6)
+               fatal_exit("ip4 and ip6 are both disabled, pointless");
+       if(!cfg->do_udp && !cfg->do_tcp)
+               fatal_exit("udp and tcp are both disabled, pointless");
+
+       if(cfg->chrootdir && strncmp(cfg->chrootdir, cfg->directory,
+               strlen(cfg->chrootdir)) != 0)
+               fatal_exit("working directory %s not in chrootdir %s",
+                       cfg->directory, cfg->chrootdir);
+       if(cfg->chrootdir && cfg->pidfile && cfg->pidfile[0] &&
+               strncmp(cfg->chrootdir, cfg->pidfile,
+                       strlen(cfg->chrootdir)) != 0)
+               fatal_exit("pid file %s not in chrootdir %s",
+                       cfg->pidfile, cfg->chrootdir);
+       if(cfg->chrootdir && cfg->logfile && cfg->logfile[0] &&
+               strncmp(cfg->chrootdir, cfg->logfile,
+                       strlen(cfg->chrootdir)) != 0)
+               fatal_exit("log file %s not in chrootdir %s",
+                       cfg->logfile, cfg->chrootdir);
+       
+       if(strcmp(cfg->module_conf, "iterator") != 0 &&
+               strcmp(cfg->module_conf, "validator iterator") != 0) {
+               fatal_exit("module conf %s is not known to work",
+                       cfg->module_conf);
+       }
+
+       if(cfg->username && cfg->username[0]) {
+               struct passwd *pwd;
+               if((pwd = getpwnam(cfg->username)) == NULL)
+                       fatal_exit("user '%s' does not exist.", cfg->username);
+               endpwent();
+       }
+}
+
+/** check config file */
+static void
+checkconf(const char* cfgfile)
+{
+       struct config_file* cfg = config_create();
+       if(!cfg)
+               fatal_exit("out of memory");
+       if(!config_read(cfg, cfgfile)) {
+               /* config_read prints messages to stderr */
+               config_delete(cfg);
+               exit(1);
+       }
+       morechecks(cfg);
+       check_mod(cfg, iter_get_funcblock());
+       check_mod(cfg, val_get_funcblock());
+       config_delete(cfg);
+       printf("unbound-checkconf: no errors in %s\n", cfgfile);
+}
+
+/** getopt global, in case header files fail to declare it. */
+extern int optind;
+/** getopt global, in case header files fail to declare it. */
+extern char* optarg;
+
+/** Main routine for checkconf */
+int main(int argc, char* argv[])
+{
+       int c;
+       log_ident_set("unbound-checkconf");
+       log_init(NULL, 0);
+       /* parse the options */
+       while( (c=getopt(argc, argv, "h")) != -1) {
+               switch(c) {
+               case '?':
+               case 'h':
+               default:
+                       usage();
+               }
+       }
+       argc -= optind;
+       argv += optind;
+       if(argc != 1)
+               usage();
+       checkconf(argv[0]);
+       return 0;
+}
index a1276ecb52600ca5a2fb7a2eafca37574ba1ec35..06185afd053c163dd52de55acf1b3a8a87e4c27f 100644 (file)
@@ -2,6 +2,7 @@
        - SIGHUP will reopen the log file.
        - Option to log to syslog.
        - please lint, fixup tests (that went to syslog on open, oops).
+       - config check program.
 
 25 September 2007: Wouter
        - tests for NSEC3. Fixup bitmap checks for NSEC3.
diff --git a/doc/unbound-checkconf.8 b/doc/unbound-checkconf.8
new file mode 100644 (file)
index 0000000..2275af4
--- /dev/null
@@ -0,0 +1,39 @@
+.\"
+.\" unbound-checkconf.8 -- unbound configuration checker manual
+.\"
+.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
+.\"
+.\" See LICENSE for the license.
+.\"
+.\"
+.Dd @date@
+.Dt unbound-checkconf 8
+.Sh NAME
+unbound-checkconf
+.Nd Check unbound configuration file for errors.
+.Sh SYNOPSIS
+.Nm unbound-checkconf
+.Op Fl h
+cfgfile
+.Sh DESCRIPTION
+.Ic Unbound-checkconf
+checks the configuration file for the
+.Xr unbound 8
+DNS resolver for syntax and other errors. 
+The config file syntax is
+described in 
+.Xr unbound.conf 5 .
+.Pp
+The available options are:
+.Bl -tag -width indent
+.It Fl h
+Show the version and commandline option help.
+.It cfgfile
+The config file to read with settings for unbound. It is checked.
+.Sh EXIT CODE
+The unbound-checkconf program exits with status code 1 on error, 
+0 for a correct config file.
+.El
+.Sh SEE ALSO
+.Xr unbound.conf 5 , 
+.Xr unbound 8 .
index 6431c3ba64c478fc92a251d5b6762b9a17dfab49..603eab0e1ba8edcd946bc89462aab2fc555edf8f 100644 (file)
@@ -38,7 +38,8 @@ Increase verbosity. If given multiple times, more information is logged.
 This is in addition to the verbosity (if any) from the config file.
 .El
 .Sh SEE ALSO
-.Xr unbound.conf 5 .
+.Xr unbound.conf 5 , 
+.Xr unbound-checkconf 8 .
 .Sh AUTHORS
 .Ic Unbound
 developers are mentioned in the CREDITS file in the distribution.
index 631ee40ed424169a8f90d6a4a833cec87afec2e1..e6cdf1fc5dddde7158a9546d1d10967390fa47a5 100644 (file)
@@ -23,6 +23,10 @@ The notation is: attribute: value.
 .Pp
 Comments start with # and last to the end of line. Empty lines are
 ignored as is whitespace at the beginning of a line.
+.Pp
+The utility 
+.Xr unbound-checkconf 8
+can be used to check unbound.conf prior to usage.
 .Sh EXAMPLE
 An example config file is shown below. Copy this to /etc/unbound/unbound.conf
 and start the server with:
@@ -55,7 +59,7 @@ directive. It can appear anywhere, and takes a single filename as an argument.
 Processing continues as if the text from the included file was copied into
 the config file at that point.
 .Ss Server Options
-There may only be one 
+These options are part of the
 .Ic server:
 clause.
 .Bl -tag -width indent
@@ -327,7 +331,8 @@ default unbound pidfile with process ID of the running daemon.
 unbound log file.
 .El
 .Sh SEE ALSO
-.Xr unbound 8
+.Xr unbound 8 , 
+.Xr unbound-checkconf 8 .
 .Sh AUTHORS
 .Ic Unbound 
 was written by NLnet Labs. Please see CREDITS file
index 4530f3fd9d3f4b70d7ca43e7a6d5e953d5d7e2f9..f1e263e0a57f3dca36ad64ed64a49814e3a020e0 100644 (file)
@@ -286,7 +286,8 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg)
                        return 0;
                if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
                        return 0;
-               delegpt_log(dp);
+               if(verbosity >= VERB_DETAIL)
+                       delegpt_log(dp);
        }
        return 1;
 }
@@ -312,7 +313,8 @@ hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
                        return 0;
                if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp))
                        return 0;
-               delegpt_log(dp);
+               if(verbosity >= VERB_DETAIL)
+                       delegpt_log(dp);
        }
 
        init_parents(hints);
index 60a6825ebcc23f7be983cb886cbcb187778f202a..b596dbd669b69a7d6cd9df055b1a6cebe788bdc4 100644 (file)
@@ -56,7 +56,7 @@
 #endif
 
 /* default verbosity */
-enum verbosity_value verbosity = 4;
+enum verbosity_value verbosity = 0;
 /** the file logged to. */
 static FILE* logfile = 0;
 /** if key has been created */