From: Wouter Wijngaards Date: Tue, 23 Feb 2010 13:53:10 +0000 (+0000) Subject: get and set option more accessible. X-Git-Tag: release-1.4.2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=423b4d88938a3341c712bcdf0c232cbebb78c809;p=thirdparty%2Funbound.git get and set option more accessible. git-svn-id: file:///svn/unbound/trunk@1990 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/daemon/remote.c b/daemon/remote.c index 03767d49d..286968063 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -1469,6 +1469,39 @@ do_log_reopen(SSL* ssl, struct worker* worker) log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); } +/** do the set_option command */ +static void +do_set_option(SSL* ssl, struct worker* worker, char* arg) +{ + char* arg2; + if(!find_arg2(ssl, arg, &arg2)) + return; + if(!config_set_option(worker->env.cfg, arg, arg2)) { + (void)ssl_printf(ssl, "error setting option\n"); + return; + } + send_ok(ssl); +} + +/* routine to printout option values over SSL */ +void remote_get_opt_ssl(char* line, void* arg) +{ + SSL* ssl = (SSL*)arg; + (void)ssl_printf(ssl, "%s\n", line); +} + +/** do the get_option command */ +static void +do_get_option(SSL* ssl, struct worker* worker, char* arg) +{ + int r; + r = config_get_option(worker->env.cfg, arg, remote_get_opt_ssl, ssl); + if(!r) { + (void)ssl_printf(ssl, "error unknown option\n"); + return; + } +} + /** tell other processes to execute the command */ void distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd) @@ -1564,6 +1597,10 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, do_dump_requestlist(ssl, worker); } else if(strncmp(p, "log_reopen", 10) == 0) { do_log_reopen(ssl, worker); + } else if(strncmp(p, "set_option", 10) == 0) { + do_set_option(ssl, worker, skipwhite(p+10)); + } else if(strncmp(p, "get_option", 10) == 0) { + do_get_option(ssl, worker, skipwhite(p+10)); } else { (void)ssl_printf(ssl, "error unknown command '%s'\n", p); } diff --git a/daemon/remote.h b/daemon/remote.h index cdbab9ba8..bd58cbc90 100644 --- a/daemon/remote.h +++ b/daemon/remote.h @@ -171,4 +171,7 @@ int ssl_printf(SSL* ssl, const char* format, ...) */ int ssl_read_line(SSL* ssl, char* buf, size_t max); +/** routine to printout option values over SSL */ +void remote_get_opt_ssl(char* line, void* arg); + #endif /* DAEMON_REMOTE_H */ diff --git a/doc/Changelog b/doc/Changelog index b4b1ae7e6..3060b97df 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +23 February 2010: Wouter + - libunbound ub_ctx_get_option() added. + - unbound-control set_option and get_option commands. + - iana portlist updated. + 18 February 2010: Wouter - A little more strict DS scrubbing. - No more blacklisting of unresponsive servers, a 2 minute timeout diff --git a/doc/libunbound.3.in b/doc/libunbound.3.in index 1adfb7317..80041fd44 100644 --- a/doc/libunbound.3.in +++ b/doc/libunbound.3.in @@ -17,6 +17,7 @@ .B ub_ctx_create, .B ub_ctx_delete, .B ub_ctx_set_option, +.B ub_ctx_get_option, .B ub_ctx_config, .B ub_ctx_set_fwd, .B ub_ctx_resolvconf, @@ -56,6 +57,9 @@ \fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val); .LP \fIint\fR +\fBub_ctx_get_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 @@ -178,6 +182,11 @@ 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_get_option +A power\-user interface that gets an option value. Some options cannot be +gotten, and others return a newline separated list. Pass the option name +without trailing ':'. The returned value must be free(2)d by the caller. +.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 diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 06434140a..ee6694311 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -142,7 +142,20 @@ Show what is worked on. Prints all queries that the server is currently working on. Prints the time that users have been waiting. For internal requests, no time is printed. And then prints out the module status. .TP -.B forward [off | addr ... ] +.B set_option \fIopt: val +Set the option to the given value without a reload. The cache is therefore +not flushed. The option must end with a ':' and whitespace must be between the +option and the value. Some values may not have an effect if set this way, +not all options are supported. +.TP +.B get_option \fIopt +Get the value of the option. Give the option name without a trailing ':'. +The value is printed. If the value is "", nothing is printed and the +connection closes. On error 'error ...' is printed (it gives a syntax +error on unknown option). For some options a list of values, one on +each line, is printed. Not all options are supported. +.TP +.B forward \fR[\fIoff\fR | \fIaddr ...\fR ] Setup forwarding mode. Configures if the server should ask other upstream nameservers, should go to the internet root nameservers itself, or show the current config. You could pass the nameservers after a DHCP update. diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index a30177d72..aae452ace 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -243,6 +243,19 @@ ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val) return UB_NOERROR; } +int +ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str) +{ + int r; + lock_basic_lock(&ctx->cfglock); + r = config_get_option_collate(ctx->env->cfg, opt, str); + lock_basic_unlock(&ctx->cfglock); + if(r == 0) r = UB_NOERROR; + else if(r == 1) r = UB_SYNTAX; + else if(r == 2) r = UB_NOMEM; + return r; +} + int ub_ctx_config(struct ub_ctx* ctx, char* fname) { diff --git a/libunbound/libworker.c b/libunbound/libworker.c index f23b1af67..315a791b3 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -868,6 +868,11 @@ int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) return 0; } +void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + #ifdef UB_ON_WINDOWS void worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void* diff --git a/libunbound/ubsyms.def b/libunbound/ubsyms.def index 0d50a2b9e..74d671f1e 100644 --- a/libunbound/ubsyms.def +++ b/libunbound/ubsyms.def @@ -1,5 +1,6 @@ ub_ctx_create ub_ctx_delete +ub_ctx_get_option ub_ctx_set_option ub_ctx_config ub_ctx_set_fwd diff --git a/libunbound/unbound.h b/libunbound/unbound.h index bbbe60387..174c5bc6b 100644 --- a/libunbound/unbound.h +++ b/libunbound/unbound.h @@ -227,7 +227,7 @@ void ub_ctx_delete(struct ub_ctx* ctx); * @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"); + * for example ub_ctx_set_option(ctx, "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 @@ -237,6 +237,22 @@ void ub_ctx_delete(struct ub_ctx* ctx); */ int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val); +/** + * Get an option from the context. + * @param ctx: context. + * @param opt: option name from the unbound.conf config file format. + * (not all settings applicable). The name excludes the trailing ':' + * for example ub_ctx_get_option(ctx, "logfile", &result); + * This is a power-users interface that lets you specify all sorts + * of options. + * @param str: the string is malloced and returned here. NULL on error. + * The caller must free() the string. In cases with multiple + * entries (auto-trust-anchor-file), a newline delimited list is + * returned in the string. + * @return 0 if OK else an error code (malloc failure, syntax error). + */ +int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** str); + /** * setup configuration for the given context. * @param ctx: context. diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index b60fb231f..579485742 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -84,6 +84,8 @@ usage() printf(" flush_stats flush statistics, make zero\n"); printf(" flush_requestlist drop queries that are worked on\n"); printf(" dump_requestlist show what is worked on\n"); + printf(" set_option opt: val set option to value, no reload\n"); + printf(" get_option opt get option value\n"); printf(" forward [off | addr ...] without arg show forward setup\n"); printf(" or off to turn off root forwarding\n"); printf(" or give list of ip addresses\n"); diff --git a/smallapp/worker_cb.c b/smallapp/worker_cb.c index 02774c756..78ee01963 100644 --- a/smallapp/worker_cb.c +++ b/smallapp/worker_cb.c @@ -241,3 +241,8 @@ int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b)) log_assert(0); return 0; } + +void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} diff --git a/testcode/testbound.c b/testcode/testbound.c index c461b641c..f61eea9bd 100644 --- a/testcode/testbound.c +++ b/testcode/testbound.c @@ -389,6 +389,11 @@ int remote_control_callback(struct comm_point* ATTR_UNUSED(c), return 0; } +void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + void wsvc_command_option(const char* ATTR_UNUSED(wopt), const char* ATTR_UNUSED(cfgfile), int ATTR_UNUSED(v), int ATTR_UNUSED(c)) diff --git a/util/config_file.c b/util/config_file.c index e3a3bf92f..d34a3142f 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -512,13 +512,91 @@ void config_print_func(char* line, void* arg) (void)fprintf(f, "%s\n", line); } +/** collate func arg */ +struct config_collate_arg { + /** list of result items */ + struct config_strlist_head list; + /** if a malloc error occurred, 0 is OK */ + int status; +}; + +void config_collate_func(char* line, void* arg) +{ + struct config_collate_arg* m = (struct config_collate_arg*)arg; + if(m->status) + return; + if(!cfg_strlist_append(&m->list, strdup(line))) + m->status = 1; +} + +int config_get_option_list(struct config_file* cfg, const char* opt, + struct config_strlist** list) +{ + struct config_collate_arg m; + memset(&m, 0, sizeof(m)); + *list = NULL; + if(!config_get_option(cfg, opt, config_collate_func, &m)) + return 1; + if(m.status) { + config_delstrlist(m.list.first); + return 2; + } + *list = m.list.first; + return 0; +} + +int +config_get_option_collate(struct config_file* cfg, const char* opt, char** str) +{ + struct config_strlist* list = NULL; + int r; + *str = NULL; + if((r = config_get_option_list(cfg, opt, &list)) != 0) + return r; + *str = config_collate_cat(list); + config_delstrlist(list); + if(!*str) return 2; + return 0; +} + +char* +config_collate_cat(struct config_strlist* list) +{ + size_t total = 0, left; + struct config_strlist* s; + char *r, *w; + if(!list) /* no elements */ + return strdup(""); + if(list->next == NULL) /* one element , no newline at end. */ + return strdup(list->str); + /* count total length */ + for(s=list; s; s=s->next) + total += strlen(s->str) + 1; /* len + newline */ + left = total+1; /* one extra for nul at end */ + r = malloc(left); + if(!r) + return NULL; + w = r; + for(s=list; s; s=s->next) { + size_t this = strlen(s->str); + if(this+2 > left) { /* sanity check */ + free(r); + return NULL; + } + snprintf(w, left, "%s\n", s->str); + w += this+1; + left -= this+1; + } + return r; +} + int config_get_option(struct config_file* cfg, const char* opt, void (*func)(char*,void*), void* arg) { char buf[1024]; size_t len = sizeof(buf); - fptr_whitelist_print_func(func); + fptr_ok(fptr_whitelist_print_func(func)); O_DEC(opt, "verbosity", verbosity) else O_DEC(opt, "statistics-interval", stat_interval) else O_YNO(opt, "statistics-cumulative", stat_interval) @@ -869,6 +947,24 @@ int ub_c_wrap() return 1; } +int cfg_strlist_append(struct config_strlist_head* list, char* item) +{ + struct config_strlist *s; + if(!item || !list) + return 0; + s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist)); + if(!s) + return 0; + s->str = item; + s->next = NULL; + if(list->last) + list->last->next = s; + else + list->first = s; + list->last = s; + return 1; +} + int cfg_strlist_insert(struct config_strlist** head, char* item) { diff --git a/util/config_file.h b/util/config_file.h index fb136346e..0ad374f44 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -315,6 +315,14 @@ struct config_str2list { char* str2; }; +/** List head for strlist processing, used for append operation. */ +struct config_strlist_head { + /** first in list of text items */ + struct config_strlist* first; + /** last in list of text items */ + struct config_strlist* last; +}; + /** * Create config file structure. Filled with default values. * @return: the new structure or NULL on memory error. @@ -373,6 +381,26 @@ int config_set_option(struct config_file* config, const char* option, int config_get_option(struct config_file* cfg, const char* opt, void (*func)(char*,void*), void* arg); +/** + * Get an option and return strlist + * @param cfg: config file + * @param opt: option name. + * @param list: list is returned here. malloced, caller must free it. + * @return 0=OK, 1=syntax error, 2=malloc failed. + */ +int config_get_option_list(struct config_file* cfg, const char* opt, + struct config_strlist** list); + +/** + * Get an option and collate results into string + * @param cfg: config file + * @param opt: option name. + * @param str: string. malloced, caller must free it. + * @return 0=OK, 1=syntax error, 2=malloc failed. + */ +int config_get_option_collate(struct config_file* cfg, const char* opt, + char** str); + /** * function to print to a file, use as func with config_get_option. * @param line: text to print. \n appended. @@ -380,6 +408,28 @@ int config_get_option(struct config_file* cfg, const char* opt, */ void config_print_func(char* line, void* arg); +/** + * function to collate the text strings into a strlist_head. + * @param line: text to append. + * @param arg: pass a strlist_head structure. zeroed on start. + */ +void config_collate_func(char* line, void* arg); + +/** + * take a strlist_head list and return a malloc string. separated with newline. + * @param list: strlist first to collate. zeroes return "". + * @return NULL on malloc failure. Or if malloc failure happened in strlist. + */ +char* config_collate_cat(struct config_strlist* list); + +/** + * Append text at end of list. + * @param list: list head. zeroed at start. + * @param item: new item. malloced by caller. if NULL the insertion fails. + * @return true on success. + */ +int cfg_strlist_append(struct config_strlist_head* list, char* item); + /** * Insert string into strlist. * @param head: pointer to strlist head variable. diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index f77e98674..5d96382d8 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -393,5 +393,7 @@ int fptr_whitelist_mesh_cb(mesh_cb_func_t fptr) int fptr_whitelist_print_func(void (*fptr)(char*,void*)) { if(fptr == &config_print_func) return 1; + else if(fptr == &config_collate_func) return 1; + else if(fptr == &remote_get_opt_ssl) return 1; return 0; } diff --git a/util/iana_ports.inc b/util/iana_ports.inc index d770618ed..d2820126d 100644 --- a/util/iana_ports.inc +++ b/util/iana_ports.inc @@ -3985,6 +3985,7 @@ 4894, 4899, 4900, +4912, 4914, 4937, 4940, @@ -4516,7 +4517,9 @@ 7164, 7165, 7166, +7169, 7170, +7171, 7174, 7200, 7201,