]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
nice option interface. Nice debug output stream option.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 11 Feb 2008 15:22:57 +0000 (15:22 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 11 Feb 2008 15:22:57 +0000 (15:22 +0000)
git-svn-id: file:///svn/unbound/trunk@945 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
doc/Changelog
doc/TODO
doc/libunbound.3
libunbound/context.c
libunbound/context.h
libunbound/libunbound.c
libunbound/ubsyms.def
libunbound/unbound.h
util/config_file.c
util/config_file.h
util/log.c
util/log.h

index b3078769744fcc8c14d358c57418a381b19fb97d..5404c1351dfa1ee38b46f719c2b7ba496ec9d3f2 100644 (file)
@@ -2,6 +2,8 @@
        - changed library to use ub_ instead of ub_val_ as prefix.
        - statistics output text nice.
        - etc/hosts handling.
+       - library function to put logging to a stream.
+       - set any option interface.
 
 8 February 2008: Wouter
        - test program for multiple queries over a TCP channel.
index c60f8f638849aad78ad537ca41950f66590d0450..9876ed40d34bc1e4dcc5797a827a0589d23892a3 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -55,3 +55,4 @@ o support multiple dns messages in a TCP query stream for the unbound server.
 o SIG(0) and TSIG.
 o support OPT record placement on recv anywhere in the additional section. 
 o add local-file: config with authority features.
+o option to make local-data answers be secure for libunbound (default=no)
index dd9f97cacec4c249a5bbe071b76275514aa9c3a9..81e8de1cadc5b0a7a78688635e8ced6c400aa8bc 100644 (file)
@@ -16,6 +16,7 @@
 .B ub_callback_t,
 .B ub_ctx_create,
 .B ub_ctx_delete,
+.B ub_ctx_set_option,
 .B ub_ctx_config,
 .B ub_ctx_set_fwd,
 .B ub_ctx_resolvconf,
@@ -23,6 +24,7 @@
 .B ub_ctx_add_ta,
 .B ub_ctx_add_ta_file,
 .B ub_ctx_trustedkeys,
+.B ub_ctx_debugout,
 .B ub_ctx_debuglevel,
 .B ub_ctx_async,
 .B ub_poll,
@@ -46,6 +48,9 @@
 \fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
 .LP
 \fIint\fR
+\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
+.LP
+\fIint\fR
 \fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
 .LP
 \fIint\fR
@@ -67,6 +72,9 @@
 \fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
 .LP
 \fIint\fR
+\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
+.LP
+\fIint\fR
 \fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
 .LP
 \fIint\fR
@@ -146,6 +154,12 @@ to read them.
 Delete validation context and free associated resources.
 Outstanding async queries are killed and callbacks are not called for them.
 .TP
+.B ub_ctx_set_option
+A power\-user interface that lets you specify one of the options from the
+config file format, see \fIunbound.conf\fR(5). Not all options are
+relevant. For some specific options, such as adding trust anchors, special
+routines exist. Pass the option name with the trailing ':'.
+.TP
 .B ub_ctx_config
 A power\-user interface that lets you specify an unbound config file, see
 \fIunbound.conf\fR(5), which is read for configuration. Not all options are
@@ -198,6 +212,11 @@ Pass the name of a bind-style config file with trusted-keys{}.
 At this time it is only possible to add trusted keys before the
 first resolve is done.
 .TP
+.B ub_ctx_debugout
+Set debug and error log output to the given stream. Pass NULL to disable
+output. Default is stderr. File-names or using syslog can be enabled
+using config options, this routine is for using your own stream.
+.TP
 .B ub_ctx_debuglevel
 Set debug verbosity for the context. Output is directed to stderr.
 Higher debug level gives more output.
index 188157cf4f2acbe11fabc7d94ec29de0d14f99a8..dc6137920abfe2f20e52288ec38c5c6c23216889 100644 (file)
@@ -55,7 +55,9 @@ context_finalize(struct ub_ctx* ctx)
 {
        struct config_file* cfg = ctx->env->cfg;
        verbosity = cfg->verbosity;
-       log_init(cfg->logfile, cfg->use_syslog, NULL);
+       if(ctx->logfile_override)
+               log_file(ctx->log_out);
+       else    log_init(cfg->logfile, cfg->use_syslog, NULL);
        config_apply(cfg);
        if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
                return UB_INITFAIL;
index ef193ef23f6ecab39365969bfc4129601ee8586a..13a6c4f36945741bb33f528a174973e763193f58 100644 (file)
@@ -87,6 +87,10 @@ struct ub_ctx {
        int dothread;
        /** next thread number for new threads */
        int thr_next_num;
+       /** if logfile is overriden */
+       int logfile_override;
+       /** what logfile to use instead */
+       FILE* log_out;
        /** 
         * List of alloc-cache-id points per threadnum for notinuse threads.
         * Simply the entire struct alloc_cache with the 'super' member used
index 0533fca5bd062def0f4be4202638ccf9fe10ba17..2b694dac174e812413e1bee0f366ae13dad80b2b 100644 (file)
@@ -233,6 +233,22 @@ ub_ctx_delete(struct ub_ctx* ctx)
        free(ctx);
 }
 
+int 
+ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val)
+{
+       lock_basic_lock(&ctx->cfglock);
+       if(ctx->finalized) {
+               lock_basic_unlock(&ctx->cfglock);
+               return UB_AFTERFINAL;
+       }
+       if(!config_set_option(ctx->env->cfg, opt, val)) {
+               lock_basic_unlock(&ctx->cfglock);
+               return UB_SYNTAX;
+       }
+       lock_basic_unlock(&ctx->cfglock);
+       return UB_NOERROR;
+}
+
 int 
 ub_ctx_config(struct ub_ctx* ctx, char* fname)
 {
@@ -316,6 +332,16 @@ ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
        return UB_NOERROR;
 }
 
+int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
+{
+       lock_basic_lock(&ctx->cfglock);
+       log_file((FILE*)out);
+       ctx->logfile_override = 1;
+       ctx->log_out = out;
+       lock_basic_unlock(&ctx->cfglock);
+       return UB_NOERROR;
+}
+
 int 
 ub_ctx_async(struct ub_ctx* ctx, int dothread)
 {
index 2b7b174fc910eb6657ff67b81dbb36609503d9fb..7a8c5852fd6c84d58a2da617146e57e2a6749841 100644 (file)
@@ -1,5 +1,6 @@
 ub_ctx_create
 ub_ctx_delete
+ub_ctx_set_option
 ub_ctx_config
 ub_ctx_set_fwd
 ub_ctx_resolvconf
@@ -7,6 +8,7 @@ ub_ctx_hosts
 ub_ctx_add_ta
 ub_ctx_add_ta_file
 ub_ctx_trustedkeys
+ub_ctx_debugout
 ub_ctx_debuglevel
 ub_ctx_async
 ub_poll
index f5f8248ff9b1846c0b06ebd772af069d780a696a..9ee32b9c05ef2f46278cb66d57c93ee5aada5dab 100644 (file)
@@ -207,6 +207,21 @@ struct ub_ctx* ub_ctx_create(void);
  */
 void ub_ctx_delete(struct ub_ctx* ctx);
 
+/**
+ * Set an option for the context.
+ * @param ctx: context.
+ * @param opt: option name from the unbound.conf config file format.
+ *     (not all settings applicable). The name includes the trailing ':'
+ *     for example ub_ctx_set_option("logfile:", "mylog.txt");
+ *     This is a power-users interface that lets you specify all sorts
+ *     of options.
+ *     For some specific options, such as adding trust anchors, special
+ *     routines exist.
+ * @param val: value of the option.
+ * @return: 0 if OK, else error.
+ */
+int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
+
 /**
  * setup configuration for the given context.
  * @param ctx: context.
@@ -303,6 +318,16 @@ int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
  */
 int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
 
+/**
+ * Set debug output (and error output) to the specified stream.
+ * Pass NULL to disable. Default is stderr.
+ * @param ctx: context.
+ * @param out: FILE* out file stream to log to.
+ *     Type void* to avoid stdio dependency of this header file.
+ * @return 0 if OK, else error.
+ */
+int ub_ctx_debugout(struct ub_ctx* ctx, void* out);
+
 /**
  * Set debug verbosity for the context
  * Output is directed to stderr.
index 42728b6f932b685981f2171ca3f07e3f7b187ac7..e7266c079f3709cdefb7a2828b2b1340aea2882c 100644 (file)
@@ -164,6 +164,164 @@ struct config_file* config_create_forlib()
        return cfg;
 }
 
+int config_set_option(struct config_file* cfg, const char* opt,
+        const char* val)
+{
+#define IS_NUMBER_OR_ZERO \
+       if(atoi(val) == 0 && strcmp(val, "0") != 0) return 0
+#define IS_NONZERO_NUMBER \
+       if(atoi(val) == 0) return 0
+#define IS_POW2_NUMBER \
+       if(atoi(val) == 0 || !is_pow2(atoi(val))) return 0
+#define IS_YES_OR_NO \
+       if(strcmp(val, "yes") != 0 && strcmp(val, "no") != 0) return 0
+
+       if(strcmp(opt, "verbosity:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->verbosity = atoi(val);
+       } else if(strcmp(opt, "statistics-interval:") == 0) {
+               if(strcmp(val, "0") == 0 || strcmp(val, "") == 0)
+                       cfg->stat_interval = 0;
+               else if(atoi(val) == 0)
+                       return 0;
+               else cfg->stat_interval = atoi(val);
+       } else if(strcmp(opt, "num_threads:") == 0) {
+               /* not supported, library must have 1 thread in bgworker */
+               return 0;
+       } else if(strcmp(opt, "do-ip4:") == 0) {
+               IS_YES_OR_NO;
+               cfg->do_ip4 = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "do-ip6:") == 0) {
+               IS_YES_OR_NO;
+               cfg->do_ip6 = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "do-udp:") == 0) {
+               IS_YES_OR_NO;
+               cfg->do_udp = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "do-tcp:") == 0) {
+               IS_YES_OR_NO;
+               cfg->do_tcp = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "outgoing-port:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->outgoing_base_port = atoi(val);
+       } else if(strcmp(opt, "outgoing-range:") == 0) {
+               IS_NONZERO_NUMBER;
+               cfg->outgoing_num_ports = atoi(val);
+       } else if(strcmp(opt, "outgoing-num-tcp:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->outgoing_num_tcp = atoi(val);
+       } else if(strcmp(opt, "incoming-num-tcp:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->incoming_num_tcp = atoi(val);
+       } else if(strcmp(opt, "msg-buffer-size:") == 0) {
+               IS_NONZERO_NUMBER;
+               cfg->msg_buffer_size = atoi(val);
+       } else if(strcmp(opt, "msg-cache-size:") == 0) {
+               return cfg_parse_memsize(val, &cfg->msg_cache_size);
+       } else if(strcmp(opt, "msg-cache-slabs:") == 0) {
+               IS_POW2_NUMBER;
+               cfg->msg_cache_slabs = atoi(val);
+       } else if(strcmp(opt, "num-queries-per-thread:") == 0) {
+               IS_NONZERO_NUMBER;
+               cfg->num_queries_per_thread = atoi(val);
+       } else if(strcmp(opt, "rrset-cache-size:") == 0) {
+               return cfg_parse_memsize(val, &cfg->rrset_cache_size);
+       } else if(strcmp(opt, "rrset-cache-slabs:") == 0) {
+               IS_POW2_NUMBER;
+               cfg->rrset_cache_slabs = atoi(val);
+       } else if(strcmp(opt, "cache-max-ttl:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->max_ttl = atoi(val);
+       } else if(strcmp(opt, "infra-host-ttl:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->host_ttl = atoi(val);
+       } else if(strcmp(opt, "infra-lame-ttl:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->lame_ttl = atoi(val);
+       } else if(strcmp(opt, "infra-cache-slabs:") == 0) {
+               IS_POW2_NUMBER;
+               cfg->infra_cache_slabs = atoi(val);
+       } else if(strcmp(opt, "infra-cache-numhosts:") == 0) {
+               IS_NONZERO_NUMBER;
+               cfg->infra_cache_numhosts = atoi(val);
+       } else if(strcmp(opt, "infra-cache-lame-size:") == 0) {
+               return cfg_parse_memsize(val, &cfg->infra_cache_lame_size);
+       } else if(strcmp(opt, "logfile:") == 0) {
+               cfg->use_syslog = 0;
+               free(cfg->logfile);
+               return (cfg->logfile = strdup(val)) != NULL;
+       } else if(strcmp(opt, "use-syslog:") == 0) {
+               IS_YES_OR_NO;
+               cfg->use_syslog = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "root-hints:") == 0) {
+               return cfg_strlist_insert(&cfg->root_hints, strdup(val));
+       } else if(strcmp(opt, "target-fetch-policy:") == 0) {
+               free(cfg->target_fetch_policy);
+               return (cfg->target_fetch_policy = strdup(val)) != NULL;
+       } else if(strcmp(opt, "harden-glue:") == 0) {
+               IS_YES_OR_NO;
+               cfg->harden_glue = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "harden-short-bufsize:") == 0) {
+               IS_YES_OR_NO;
+               cfg->harden_short_bufsize = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "harden-large-queries:") == 0) {
+               IS_YES_OR_NO;
+               cfg->harden_large_queries = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "harden-dnssec-stripped:") == 0) {
+               IS_YES_OR_NO;
+               cfg->harden_dnssec_stripped = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "do-not-query-localhost:") == 0) {
+               IS_YES_OR_NO;
+               cfg->donotquery_localhost = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "do-not-query-address:") == 0) {
+               return cfg_strlist_insert(&cfg->donotqueryaddrs, strdup(val));
+       } else if(strcmp(opt, "trust-anchor-file:") == 0) {
+               return cfg_strlist_insert(&cfg->trust_anchor_file_list, 
+                       strdup(val));
+       } else if(strcmp(opt, "trust-anchor:") == 0) {
+               return cfg_strlist_insert(&cfg->trust_anchor_list, 
+                       strdup(val));
+       } else if(strcmp(opt, "trusted-keys-file:") == 0) {
+               return cfg_strlist_insert(&cfg->trusted_keys_file_list, 
+                       strdup(val));
+       } else if(strcmp(opt, "val-override-date:") == 0) {
+               if(strcmp(val, "") == 0 || strcmp(val, "0") == 0) {
+                       cfg->val_date_override = 0;
+               } else if(strlen(val) == 14) {
+                       cfg->val_date_override = cfg_convert_timeval(val);
+                       return cfg->val_date_override != 0;
+               } else {
+                       if(atoi(val) == 0) return 0;
+                       cfg->val_date_override = atoi(val);
+               }
+       } else if(strcmp(opt, "val-bogus-ttl:") == 0) {
+               IS_NUMBER_OR_ZERO;
+               cfg->bogus_ttl = atoi(val);
+       } else if(strcmp(opt, "val-clean-additional:") == 0) {
+               IS_YES_OR_NO;
+               cfg->val_clean_additional = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "val-permissive-mode:") == 0) {
+               IS_YES_OR_NO;
+               cfg->val_permissive_mode = (strcmp(val, "yes") == 0);
+       } else if(strcmp(opt, "val-nsec3-keysize-iterations:") == 0) {
+               free(cfg->val_nsec3_key_iterations);
+               return (cfg->val_nsec3_key_iterations = strdup(val)) != NULL;
+       } else if(strcmp(opt, "key-cache-size:") == 0) {
+               return cfg_parse_memsize(val, &cfg->key_cache_size);
+       } else if(strcmp(opt, "key-cache-slabs:") == 0) {
+               IS_POW2_NUMBER;
+               cfg->key_cache_slabs = atoi(val);
+       } else if(strcmp(opt, "local-data:") == 0) {
+               return cfg_strlist_insert(&cfg->local_data, strdup(val));
+       } else if(strcmp(opt, "module-config:") == 0) {
+               free(cfg->module_conf);
+               return (cfg->module_conf = strdup(val)) != NULL;
+       } else {
+               /* unknown or unsupported (from the library interface) */
+               return 0;
+       }
+       return 1;
+}
+
 /** initialize the global cfg_parser object */
 static void
 create_cfg_parser(struct config_file* cfg, char* filename)
index ffb6b3bbaf0bb432548b435c50cf2001822153d4..c52cc1665f01e733fdae244b83ab970bd5894ca5 100644 (file)
@@ -271,6 +271,17 @@ void config_delete(struct config_file* config);
  */
 void config_apply(struct config_file* config);
 
+/**
+ * Set the given keyword to the given value.
+ * @param config: where to store config
+ * @param option: option name, including the ':' character.
+ * @param value: value, this string is copied if needed, or parsed.
+ *     The caller owns the value string.
+ * @return 0 on error (malloc or syntax error).
+ */
+int config_set_option(struct config_file* config, const char* option,
+       const char* value);
+
 /**
  * Insert string into strlist.
  * @param head: pointer to strlist head variable.
index c1db604cc8efdb06b5e448fb197cf0e15acc9446..998b4c2910093d6170da288d2c5a21cb23711140 100644 (file)
@@ -104,7 +104,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
        }
        /* open the file for logging */
        if(chrootdir && chrootdir[0] && strncmp(filename, chrootdir,
-               strlen(chrootdir)) == 0)
+               strlen(chrootdir)) == 0) 
                filename += strlen(chrootdir);
        f = fopen(filename, "a");
        if(!f) {
@@ -115,6 +115,11 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
        logfile = f;
 }
 
+void log_file(FILE *f)
+{
+       logfile = f;
+}
+
 void log_thread_set(int* num)
 {
        ub_thread_key_set(logkey, num);
@@ -140,6 +145,7 @@ log_vmsg(int pri, const char* type,
                return;
        }
 #endif /* HAVE_SYSLOG_H */
+       if(!logfile) return;
        fprintf(logfile, "[%d] %s[%d:%x] %s: %s\n", (int)time(NULL), 
                ident, (int)getpid(), tid?*tid:0, type, message);
        fflush(logfile);
index f6983181eada6fcdfd7b537fd4452480d15a5297..394a20111eede7f0bfc6084b3b892c6332e70953 100644 (file)
@@ -84,6 +84,13 @@ void verbose(enum verbosity_value level,
  */
 void log_init(const char* filename, int use_syslog, const char* chrootdir);
 
+/**
+ * Set logging to go to the specified file *.
+ * This setting does not affect the use_syslog setting.
+ * @param f: to that file, or pass NULL to disable logging.
+ */
+void log_file(FILE *f);
+
 /**
  * Init a thread (will print this number for the thread log entries).
  * Must be called from the thread itself. If not called 0 is printed.