nice option interface. Nice debug output stream option.

git-svn-id: file:///svn/unbound/trunk@945 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2008-02-11 15:22:57 +00:00
parent 49d73f5f56
commit d7f47f4de6
12 changed files with 265 additions and 2 deletions

View file

@ -2,6 +2,8 @@
- changed library to use ub_ instead of ub_val_ as prefix. - changed library to use ub_ instead of ub_val_ as prefix.
- statistics output text nice. - statistics output text nice.
- etc/hosts handling. - etc/hosts handling.
- library function to put logging to a stream.
- set any option interface.
8 February 2008: Wouter 8 February 2008: Wouter
- test program for multiple queries over a TCP channel. - test program for multiple queries over a TCP channel.

View file

@ -55,3 +55,4 @@ o support multiple dns messages in a TCP query stream for the unbound server.
o SIG(0) and TSIG. o SIG(0) and TSIG.
o support OPT record placement on recv anywhere in the additional section. o support OPT record placement on recv anywhere in the additional section.
o add local-file: config with authority features. o add local-file: config with authority features.
o option to make local-data answers be secure for libunbound (default=no)

View file

@ -16,6 +16,7 @@
.B ub_callback_t, .B ub_callback_t,
.B ub_ctx_create, .B ub_ctx_create,
.B ub_ctx_delete, .B ub_ctx_delete,
.B ub_ctx_set_option,
.B ub_ctx_config, .B ub_ctx_config,
.B ub_ctx_set_fwd, .B ub_ctx_set_fwd,
.B ub_ctx_resolvconf, .B ub_ctx_resolvconf,
@ -23,6 +24,7 @@
.B ub_ctx_add_ta, .B ub_ctx_add_ta,
.B ub_ctx_add_ta_file, .B ub_ctx_add_ta_file,
.B ub_ctx_trustedkeys, .B ub_ctx_trustedkeys,
.B ub_ctx_debugout,
.B ub_ctx_debuglevel, .B ub_ctx_debuglevel,
.B ub_ctx_async, .B ub_ctx_async,
.B ub_poll, .B ub_poll,
@ -46,6 +48,9 @@
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx); \fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
.LP .LP
\fIint\fR \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); \fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP .LP
\fIint\fR \fIint\fR
@ -67,6 +72,9 @@
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); \fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP .LP
\fIint\fR \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); \fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
.LP .LP
\fIint\fR \fIint\fR
@ -146,6 +154,12 @@ to read them.
Delete validation context and free associated resources. Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for them. Outstanding async queries are killed and callbacks are not called for them.
.TP .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 .B ub_ctx_config
A power\-user interface that lets you specify an unbound config file, see 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 \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 At this time it is only possible to add trusted keys before the
first resolve is done. first resolve is done.
.TP .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 .B ub_ctx_debuglevel
Set debug verbosity for the context. Output is directed to stderr. Set debug verbosity for the context. Output is directed to stderr.
Higher debug level gives more output. Higher debug level gives more output.

View file

@ -55,7 +55,9 @@ context_finalize(struct ub_ctx* ctx)
{ {
struct config_file* cfg = ctx->env->cfg; struct config_file* cfg = ctx->env->cfg;
verbosity = cfg->verbosity; 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); config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL; return UB_INITFAIL;

View file

@ -87,6 +87,10 @@ struct ub_ctx {
int dothread; int dothread;
/** next thread number for new threads */ /** next thread number for new threads */
int thr_next_num; 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. * List of alloc-cache-id points per threadnum for notinuse threads.
* Simply the entire struct alloc_cache with the 'super' member used * Simply the entire struct alloc_cache with the 'super' member used

View file

@ -233,6 +233,22 @@ ub_ctx_delete(struct ub_ctx* ctx)
free(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 int
ub_ctx_config(struct ub_ctx* ctx, char* fname) 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; 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 int
ub_ctx_async(struct ub_ctx* ctx, int dothread) ub_ctx_async(struct ub_ctx* ctx, int dothread)
{ {

View file

@ -1,5 +1,6 @@
ub_ctx_create ub_ctx_create
ub_ctx_delete ub_ctx_delete
ub_ctx_set_option
ub_ctx_config ub_ctx_config
ub_ctx_set_fwd ub_ctx_set_fwd
ub_ctx_resolvconf ub_ctx_resolvconf
@ -7,6 +8,7 @@ ub_ctx_hosts
ub_ctx_add_ta ub_ctx_add_ta
ub_ctx_add_ta_file ub_ctx_add_ta_file
ub_ctx_trustedkeys ub_ctx_trustedkeys
ub_ctx_debugout
ub_ctx_debuglevel ub_ctx_debuglevel
ub_ctx_async ub_ctx_async
ub_poll ub_poll

View file

@ -207,6 +207,21 @@ struct ub_ctx* ub_ctx_create(void);
*/ */
void ub_ctx_delete(struct ub_ctx* ctx); 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. * setup configuration for the given context.
* @param ctx: 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); 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 * Set debug verbosity for the context
* Output is directed to stderr. * Output is directed to stderr.

View file

@ -164,6 +164,164 @@ struct config_file* config_create_forlib()
return cfg; 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 */ /** initialize the global cfg_parser object */
static void static void
create_cfg_parser(struct config_file* cfg, char* filename) create_cfg_parser(struct config_file* cfg, char* filename)

View file

@ -271,6 +271,17 @@ void config_delete(struct config_file* config);
*/ */
void config_apply(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. * Insert string into strlist.
* @param head: pointer to strlist head variable. * @param head: pointer to strlist head variable.

View file

@ -115,6 +115,11 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
logfile = f; logfile = f;
} }
void log_file(FILE *f)
{
logfile = f;
}
void log_thread_set(int* num) void log_thread_set(int* num)
{ {
ub_thread_key_set(logkey, num); ub_thread_key_set(logkey, num);
@ -140,6 +145,7 @@ log_vmsg(int pri, const char* type,
return; return;
} }
#endif /* HAVE_SYSLOG_H */ #endif /* HAVE_SYSLOG_H */
if(!logfile) return;
fprintf(logfile, "[%d] %s[%d:%x] %s: %s\n", (int)time(NULL), fprintf(logfile, "[%d] %s[%d:%x] %s: %s\n", (int)time(NULL),
ident, (int)getpid(), tid?*tid:0, type, message); ident, (int)getpid(), tid?*tid:0, type, message);
fflush(logfile); fflush(logfile);

View file

@ -84,6 +84,13 @@ void verbose(enum verbosity_value level,
*/ */
void log_init(const char* filename, int use_syslog, const char* chrootdir); 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). * 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. * Must be called from the thread itself. If not called 0 is printed.