diff --git a/doc/man/knotc.8in b/doc/man/knotc.8in index 557f2aa6a26572ac283421a2fc6773fe4e569db1..79e8515ec88d5642e594e71bf2dfb7a9087e306a 100644 --- a/doc/man/knotc.8in +++ b/doc/man/knotc.8in @@ -38,167 +38,127 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .INDENT 0.0 .TP \fB\-c\fP, \fB\-\-config\fP \fIfile\fP -Use a textual configuration file (default is \fB@conf_dir@/knot.conf\fP). +Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). .TP \fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database. +Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. .TP -\fB\-s\fP, \fB\-\-server\fP \fIserver\fP -Remote UNIX socket/IP address (default is \fB@run_dir@/knot.sock\fP). -.TP -\fB\-p\fP, \fB\-\-port\fP \fIport\fP -Remote server port (only for IP). -.TP -\fB\-y\fP, \fB\-\-key\fP [\fIalg\fP:]\fIname\fP:\fIkey\fP -Use the TSIG key specified on the command line (default algorithm is hmac\-md5). -.TP -\fB\-k\fP, \fB\-\-keyfile\fP \fIfile\fP -Use the TSIG key stored in a file \fIfile\fP to authenticate the request. The -file must contain the key in the same format, which is accepted by the -\fB\-y\fP option. +\fB\-s\fP, \fB\-\-socket\fP \fIpath\fP +Use a remote control UNIX socket path (default is \fB@run_dir@/knot.sock\fP). .TP \fB\-f\fP, \fB\-\-force\fP -Force operation. Overrides some checks. +Forced operation. Overrides some checks. .TP \fB\-v\fP, \fB\-\-verbose\fP -Verbose mode. Print additional runtime information. +Enable debug output. +.TP +\fB\-h\fP, \fB\-\-help\fP +Print the program help. .TP \fB\-V\fP, \fB\-\-version\fP Print the program version. -.TP -\fB\-h\fP, \fB\-\-help\fP -Print help and usage. .UNINDENT .SS Actions -.sp -If the optional \fIzone\fP argument is not specified, the command is applied to all -zones. -Configuration \fIitem\fP is in the \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIitem\fP] -format. .INDENT 0.0 .TP +\fBstatus\fP +Check if the server is running. +.TP \fBstop\fP -Stop server (no\-op if not running). +Stop the server if running. .TP -\fBreload\fP [\fIzone\fP\&...] -Reload particular zones or reload the whole configuration and changed zones. +\fBreload\fP +Reload the server configuration. .TP -\fBflush\fP [\fIzone\fP\&...] -Flush journal and update zone files. +\fBzone\-check\fP [\fIzone\fP\&...] +Check the zone. (*) .TP -\fBstatus\fP -Check if server is running. +\fBzone\-memstats\fP [\fIzone\fP\&...] +Estimate memory use for the zone. (*) +.TP +\fBzone\-status\fP [\fIzone\fP\&...] +Show the status of the zone. (*) .TP -\fBzonestatus\fP [\fIzone\fP\&...] -Show the status of listed zones. +\fBzone\-reload\fP [\fIzone\fP\&...] +Trigger a zone reload. .TP -\fBrefresh\fP [\fIzone\fP\&...] -Refresh slave zones. The \fB\-f\fP flag forces re\-transfer (zones must be specified). +\fBzone\-refresh\fP [\fIzone\fP\&...] +Trigger a zone refresh (if slave). .TP -\fBcheckconf\fP -Check the current configuration. +\fBzone\-retransfer\fP [\fIzone\fP\&...] +Trigger a zone retransfer (if slave). .TP -\fBcheckzone\fP [\fIzone\fP\&...] -Check zones. +\fBzone\-flush\fP [\fIzone\fP\&...] +Trigger a zone journal flush into the zone file. .TP -\fBmemstats\fP [\fIzone\fP\&...] -Estimate memory consumption for zones. +\fBzone\-sing\fP [\fIzone\fP\&...] +Trigger a zone resign (if enabled). .TP -\fBsignzone\fP \fIzone\fP\&... -Re\-sign the zone (drop all existing signatures and create new ones). +\fBconf\-check\fP +Check the server configuration. (*) .TP \fBconf\-import\fP \fIfilename\fP -Offline import of the configuration DB from a file. This is a -potentially dangerous operation so the \fB\-f\fP flag is required. Also the -destination configuration DB must be specified via \fB\-C\fP\&. Ensure the server -is not running! +Import a config file into the confdb. Ensure the server is not accessing +the confdb! (*) .TP \fBconf\-export\fP \fIfilename\fP -Export the configuration DB to a file. If no source configuration DB is -specified, the temporary DB, corresponding to textual configuration file, is -used. +Export the confdb into a config file. (*) .TP -\fBconf\-desc\fP [\fIsection\fP] -Get the configuration section items list. If no section is specified, -the list of sections is returned. +\fBconf\-list\fP [\fIitem\fP] +List the confdb sections or section items. .TP \fBconf\-read\fP [\fIitem\fP] -Read from the current configuration DB. +Read the item from the active confdb. .TP \fBconf\-begin\fP -Begin a writing configuration DB transaction. Only one transaction can be -opened at a time. +Begin a writing confdb transaction. Only one transaction can be opened at a time. .TP \fBconf\-commit\fP -Commit the current writing configuration DB transaction. +Commit the confdb transaction. .TP \fBconf\-abort\fP -Abort the current writing configuration DB transaction. +Rollback the confdb transaction. .TP \fBconf\-diff\fP [\fIitem\fP] -Get the difference between the active writing transaction and the current -configuration DB. Requires active writing configuration DB transaction. +Get the item difference in the transaction. .TP \fBconf\-get\fP [\fIitem\fP] -Read from the active writing configuration DB transaction. -Requires active writing configuration DB transaction. +Get the item data from the transaction. .TP \fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...] -Write to the active writing configuration DB transaction. -Requires active writing configuration DB transaction. +Set the item data in the transaction. .TP \fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...] -Delete from the active writing configuration DB transaction. -Requires active writing configuration DB transaction. -.UNINDENT -.SH EXAMPLES -.SS Setup a key file for remote control -.INDENT 0.0 -.INDENT 3.5 -.sp -.nf -.ft C -$ keymgr tsig generate knotc\-key > knotc\-key.conf -.ft P -.fi -.UNINDENT +Unset the item data in the transaction. .UNINDENT +.SH NOTE .sp -The generated key file contains a key in the server configuration format and -thus can be directly included into the server configuration file. -.sp -Knot DNS utilities accept one\-line format which is included in the generated -key file on the first line as a comment. It can be extracted easily: -.INDENT 0.0 -.INDENT 3.5 +Empty \fIzone\fP parameter means all zones. .sp -.nf -.ft C -$ head \-1 knotc\-key.conf | sed \(aqs/^#\es*//\(aq > knotc.key -.ft P -.fi -.UNINDENT -.UNINDENT +Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP]. .sp -Make sure the key file can be read only by the owner for security reasons. -.SS Reload server remotely +(*) indicates a local operation requiring a configuration specified. +.SH EXAMPLES +.SS Reload the whole server configuration .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C -$ knotc \-s 127.0.0.1 \-k knotc.key reload +$ knotc reload .ft P .fi .UNINDENT .UNINDENT -.SS Flush all zones locally +.SS Flush the example.com and example.eu zones .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C -$ knotc \-c knot.conf flush +$ knotc zone\-flush example.com example.eu .ft P .fi .UNINDENT diff --git a/doc/man/knotd.8in b/doc/man/knotd.8in index 4a72710c602ed00c6877135f9d05ba20a67e880b..19926353f97782f814da07b44f91ad11fd854c97 100644 --- a/doc/man/knotd.8in +++ b/doc/man/knotd.8in @@ -41,7 +41,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP). .TP \fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP -Use a binary configuration database directory. +Use a binary configuration database directory (default is \fB@storage_dir@/confdb\fP). +The default configuration database, if exists, has a preference to the default +configuration file. .TP \fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP] Run the server as a daemon. New root directory may be specified diff --git a/doc/man_knotc.rst b/doc/man_knotc.rst index 087471d0493c7f04172388ced04b9a662822b776..3451ac34e5179dd6973f1427371e21566ea30819 100644 --- a/doc/man_knotc.rst +++ b/doc/man_knotc.rst @@ -15,152 +15,131 @@ Parameters .......... **-c**, **--config** *file* - Use a textual configuration file (default is :file:`@conf_dir@/knot.conf`). + Use a textual configuration file (default is :file:`@config_dir@/knot.conf`). **-C**, **--confdb** *directory* - Use a binary configuration database. + Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`). + The default configuration database, if exists, has a preference to the default + configuration file. -**-s**, **--server** *server* - Remote UNIX socket/IP address (default is :file:`@run_dir@/knot.sock`). - -**-p**, **--port** *port* - Remote server port (only for IP). - -**-y**, **--key** [*alg*:]\ *name*:*key* - Use the TSIG key specified on the command line (default algorithm is hmac-md5). - -**-k**, **--keyfile** *file* - Use the TSIG key stored in a file *file* to authenticate the request. The - file must contain the key in the same format, which is accepted by the - **-y** option. +**-s**, **--socket** *path* + Use a remote control UNIX socket path (default is :file:`@run_dir@/knot.sock`). **-f**, **--force** - Force operation. Overrides some checks. + Forced operation. Overrides some checks. **-v**, **--verbose** - Verbose mode. Print additional runtime information. + Enable debug output. + +**-h**, **--help** + Print the program help. **-V**, **--version** Print the program version. -**-h**, **--help** - Print help and usage. - Actions ....... -If the optional *zone* argument is not specified, the command is applied to all -zones. -Configuration *item* is in the *section*\ [**[**\ *id*\ **]**\ ][**.**\ *item*] -format. +**status** + Check if the server is running. **stop** - Stop server (no-op if not running). + Stop the server if running. -**reload** [*zone*...] - Reload particular zones or reload the whole configuration and changed zones. +**reload** + Reload the server configuration. -**flush** [*zone*...] - Flush journal and update zone files. -**status** - Check if server is running. +**zone-check** [*zone*...] + Check the zone. (*) + +**zone-memstats** [*zone*...] + Estimate memory use for the zone. (*) + +**zone-status** [*zone*...] + Show the status of the zone. (*) -**zonestatus** [*zone*...] - Show the status of listed zones. +**zone-reload** [*zone*...] + Trigger a zone reload. -**refresh** [*zone*...] - Refresh slave zones. The **-f** flag forces re-transfer (zones must be specified). +**zone-refresh** [*zone*...] + Trigger a zone refresh (if slave). -**checkconf** - Check the current configuration. +**zone-retransfer** [*zone*...] + Trigger a zone retransfer (if slave). -**checkzone** [*zone*...] - Check zones. +**zone-flush** [*zone*...] + Trigger a zone journal flush into the zone file. -**memstats** [*zone*...] - Estimate memory consumption for zones. +**zone-sing** [*zone*...] + Trigger a zone resign (if enabled). -**signzone** *zone*... - Re-sign the zone (drop all existing signatures and create new ones). + +**conf-init** + Initialize the confdb. (*) + +**conf-check** + Check the server configuration. (*) **conf-import** *filename* - Offline import of the configuration DB from a file. This is a - potentially dangerous operation so the **-f** flag is required. Also the - destination configuration DB must be specified via **-C**. Ensure the server - is not running! + Import a config file into the confdb. Ensure the server is not accessing + the confdb! (*) **conf-export** *filename* - Export the configuration DB to a file. If no source configuration DB is - specified, the temporary DB, corresponding to textual configuration file, is - used. + Export the confdb into a config file. (*) -**conf-desc** [*section*] - Get the configuration section items list. If no section is specified, - the list of sections is returned. +**conf-list** [*item*] + List the confdb sections or section items. **conf-read** [*item*] - Read from the current configuration DB. + Read the item from the active confdb. **conf-begin** - Begin a writing configuration DB transaction. Only one transaction can be - opened at a time. + Begin a writing confdb transaction. Only one transaction can be opened at a time. **conf-commit** - Commit the current writing configuration DB transaction. + Commit the confdb transaction. **conf-abort** - Abort the current writing configuration DB transaction. + Rollback the confdb transaction. **conf-diff** [*item*] - Get the difference between the active writing transaction and the current - configuration DB. Requires active writing configuration DB transaction. + Get the item difference in the transaction. **conf-get** [*item*] - Read from the active writing configuration DB transaction. - Requires active writing configuration DB transaction. + Get the item data from the transaction. **conf-set** *item* [*data*...] - Write to the active writing configuration DB transaction. - Requires active writing configuration DB transaction. + Set the item data in the transaction. **conf-unset** [*item*] [*data*...] - Delete from the active writing configuration DB transaction. - Requires active writing configuration DB transaction. - -Examples --------- + Unset the item data in the transaction. -Setup a key file for remote control -................................... +Note +---- -:: - - $ keymgr tsig generate knotc-key > knotc-key.conf - -The generated key file contains a key in the server configuration format and -thus can be directly included into the server configuration file. +Empty *zone* parameter means all zones. -Knot DNS utilities accept one-line format which is included in the generated -key file on the first line as a comment. It can be extracted easily:: +Type *item* parameter in the form of *section*\ [**[**\ *id*\ **]**\ ][**.**\ *name*]. - $ head -1 knotc-key.conf | sed 's/^#\s*//' > knotc.key +(*) indicates a local operation requiring a configuration specified. -Make sure the key file can be read only by the owner for security reasons. +Examples +-------- -Reload server remotely -...................... +Reload the whole server configuration +..................................... :: - $ knotc -s 127.0.0.1 -k knotc.key reload + $ knotc reload -Flush all zones locally -....................... +Flush the example.com and example.eu zones +.......................................... :: - $ knotc -c knot.conf flush + $ knotc zone-flush example.com example.eu Get the current server configuration .................................... diff --git a/doc/man_knotd.rst b/doc/man_knotd.rst index 9b8bfa7c6e5e37f1ed2940ebf3400e6edc9a7045..29212f9aba11ebc7e1ad9487af7d7b3b5a0e23ca 100644 --- a/doc/man_knotd.rst +++ b/doc/man_knotd.rst @@ -18,7 +18,9 @@ Parameters Use a textual configuration file (default is :file:`@config_dir@/knot.conf`). **-C**, **--confdb** *directory* - Use a binary configuration database directory. + Use a binary configuration database directory (default is :file:`@storage_dir@/confdb`). + The default configuration database, if exists, has a preference to the default + configuration file. **-d**, **--daemonize** [*directory*] Run the server as a daemon. New root directory may be specified diff --git a/src/utils/knotc/main.c b/src/utils/knotc/main.c index 2734b99ad526caf4c2b7d6da2f7944f24510227d..8791cb5d73eab896c69653e9585e74a2402cdcc0 100644 --- a/src/utils/knotc/main.c +++ b/src/utils/knotc/main.c @@ -18,114 +18,191 @@ #include <stdio.h> #include <sys/stat.h> -#include "contrib/sockaddr.h" #include "dnssec/crypto.h" #include "knot/common/log.h" #include "knot/conf/conf.h" #include "libknot/libknot.h" #include "utils/knotc/commands.h" +#include "utils/common/params.h" -/*! \brief Print help. */ -static void help(void) +#define PROGRAM_NAME "knotc" + +static void print_help(void) { - printf("Usage: knotc [parameters] <action> [action_args]\n" + printf("Usage: %s [parameters] <action> [action_args]\n" "\n" "Parameters:\n" - " -c, --config <file> Select configuration file.\n" - " (default %s)\n" - " -C, --confdb <dir> Select configuration database directory.\n" - " -s, --socket <path> Remote control UNIX socket.\n" - " (default %s)\n" - " -f, --force Force operation - override some checks.\n" - " -v, --verbose Verbose mode - additional runtime information.\n" - " -V, --version Print %s server version.\n" - " -h, --help Print help and usage.\n" + " -c, --config <file> Use a textual configuration file.\n" + " (default %s)\n" + " -C, --confdb <dir> Use a binary configuration database directory.\n" + " (default %s)\n" + " -s, --socket <path> Use a remote control UNIX socket path.\n" + " (default %s)\n" + " -f, --force Forced operation. Overrides some checks.\n" + " -v, --verbose Enable debug output.\n" + " -h, --help Print the program help.\n" + " -V, --version Print the program version.\n" "\n" "Actions:\n", - CONF_DEFAULT_FILE, RUN_DIR "/knot.sock", PACKAGE_NAME); - cmd_help_t *c = cmd_help_table; - while (c->name != NULL) { - printf(" %-13s %-20s %s\n", c->name, c->params, c->desc); - ++c; - } - printf("\nThe item argument must be in the section[identifier].item format.\n"); - printf("\nIf optional <zone> parameter is not specified, command is applied to all zones.\n\n"); + PROGRAM_NAME, CONF_DEFAULT_FILE, CONF_DEFAULT_DBDIR, RUN_DIR "/knot.sock"); + + for (const cmd_help_t *cmd = cmd_help_table; cmd->name != NULL; cmd++) { + printf(" %-15s %-20s %s\n", cmd->name, cmd->params, cmd->desc); + } + + printf("\n" + "Note:\n" + " Empty <zone> parameter means all zones.\n" + " Type <item> parameter in the form of <section>[<identifier>].<name>.\n" + " (*) indicates a local operation requiring a configuration specified.\n"); +} + +static int set_config(const cmd_desc_t *desc, const char *confdb, + const char *config, char *socket) +{ + if (config != NULL && confdb != NULL) { + log_error("ambiguous configuration source"); + return KNOT_EINVAL; + } + + /* Choose the optimal config source. */ + struct stat st; + bool import = false; + if (desc->flags == CMD_CONF_FNONE && socket != NULL) { + import = false; + confdb = NULL; + } else if (confdb != NULL) { + import = false; + } else if (desc->flags == CMD_CONF_FWRITE) { + import = false; + confdb = CONF_DEFAULT_DBDIR; + } else if (config != NULL){ + import = true; + } else if (stat(CONF_DEFAULT_DBDIR, &st) == 0) { + import = false; + confdb = CONF_DEFAULT_DBDIR; + } else if (stat(CONF_DEFAULT_FILE, &st) == 0) { + import = true; + config = CONF_DEFAULT_FILE; + } else if (desc->flags != CMD_CONF_FNONE) { + log_error("no configuration source available"); + return KNOT_EINVAL; + } + + const char *src = import ? config : confdb; + log_debug("%s '%s'", import ? "config" : "confdb", + (src != NULL) ? src : "empty"); + + /* Prepare config flags. */ + conf_flag_t conf_flags = CONF_FNONE; + if (confdb != NULL && !(desc->flags & CMD_CONF_FWRITE)) { + conf_flags |= CONF_FREADONLY; + } + + /* Open confdb. */ + conf_t *new_conf = NULL; + int ret = conf_new(&new_conf, conf_scheme, confdb, conf_flags); + if (ret != KNOT_EOK) { + log_error("failed to open configuration database '%s' (%s)", + (confdb != NULL) ? confdb : "", knot_strerror(ret)); + return ret; + } + + /* Import the config file. */ + if (import) { + ret = conf_import(new_conf, config, true); + if (ret != KNOT_EOK) { + log_error("failed to load configuration file '%s' (%s)", + config, knot_strerror(ret)); + conf_free(new_conf); + return ret; + } + } + + /* Finalize the config (needed for conf check and cached items). */ + ret = conf_post_open(new_conf); + if (ret != KNOT_EOK) { + log_error("failed to use configuration (%s)", knot_strerror(ret)); + conf_free(new_conf); + return ret; + } + + /* Update to the new config. */ + conf_update(new_conf); + + return KNOT_EOK; } int main(int argc, char **argv) { - /* Parse command line arguments */ - int c = 0, li = 0, rc = 0; - unsigned flags = CMD_NONE; - const char *config_fn = CONF_DEFAULT_FILE; - const char *config_db = NULL; + cmd_flag_t flags = CMD_FNONE; + const char *config = NULL; + const char *confdb = NULL; char *socket = NULL; - - /* Initialize. */ - log_init(); - log_levels_set(LOG_SYSLOG, LOG_ANY, 0); + bool verbose = false; /* Long options. */ struct option opts[] = { - { "config", required_argument, 0, 'c' }, - { "confdb", required_argument, 0, 'C' }, - { "socket", required_argument, 0, 's' }, - { "force", no_argument, 0, 'f' }, - { "verbose", no_argument, 0, 'v' }, - { "help", no_argument, 0, 'h' }, - { "version", no_argument, 0, 'V' }, + { "config", required_argument, NULL, 'c' }, + { "confdb", required_argument, NULL, 'C' }, + { "socket", required_argument, NULL, 's' }, + { "force", no_argument, NULL, 'f' }, + { "verbose", no_argument, NULL, 'v' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'V' }, { NULL } }; - while ((c = getopt_long(argc, argv, "s:fc:C:vVh", opts, &li)) != -1) { - switch (c) { + /* Parse command line arguments */ + int opt = 0, li = 0; + while ((opt = getopt_long(argc, argv, "c:C:s:fvhV", opts, &li)) != -1) { + switch (opt) { case 'c': - config_fn = optarg; + config = optarg; break; case 'C': - config_db = optarg; + confdb = optarg; break; case 's': - socket = strdup(optarg); + socket = optarg; break; case 'f': - flags |= CMD_FORCE; + flags |= CMD_FFORCE; break; case 'v': - log_levels_add(LOGT_STDOUT, LOG_ANY, - LOG_MASK(LOG_INFO) | LOG_MASK(LOG_DEBUG)); + verbose = true; break; - case 'V': - rc = 0; - printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION); - goto exit; case 'h': - case '?': - rc = 0; - help(); - goto exit; + print_help(); + return EXIT_SUCCESS; + case 'V': + print_version(PROGRAM_NAME); + return EXIT_SUCCESS; default: - rc = 1; - help(); - goto exit; + print_help(); + return EXIT_FAILURE; } } /* Check if there's at least one remaining non-option. */ if (argc - optind < 1) { - rc = 1; - help(); - goto exit; + print_help(); + return EXIT_FAILURE; } - /* Check for existing config DB destination. */ - struct stat st; - if (config_db != NULL && stat(config_db, &st) != 0) { - flags |= CMD_NOCONFDB; + /* Set up simplified logging just to stdout/stderr. */ + log_init(); + log_levels_set(LOGT_STDOUT, LOG_ANY, LOG_MASK(LOG_INFO) | LOG_MASK(LOG_NOTICE)); + log_levels_set(LOGT_STDERR, LOG_ANY, LOG_UPTO(LOG_WARNING)); + log_levels_set(LOGT_SYSLOG, LOG_ANY, 0); + log_flag_set(LOG_FNO_TIMESTAMP | LOG_FNO_INFO); + if (verbose) { + log_levels_add(LOGT_STDOUT, LOG_ANY, LOG_MASK(LOG_DEBUG)); } + /* Translate old command name. */ const char *command = argv[optind]; - for (cmd_desc_old_t *desc = cmd_table_old; desc->old_name != NULL; desc++) { + for (const cmd_desc_old_t *desc = cmd_table_old; desc->old_name != NULL; desc++) { if (strcmp(desc->old_name, command) == 0) { log_notice("obsolete command '%s', using '%s' instead", desc->old_name, desc->new_name); @@ -135,94 +212,56 @@ int main(int argc, char **argv) } /* Find requested command. */ - cmd_desc_t *desc = cmd_table; + const cmd_desc_t *desc = cmd_table; while (desc->name != NULL) { if (strcmp(desc->name, command) == 0) { break; } - ++desc; + desc++; } - - /* Command not found. */ if (desc->name == NULL) { - log_fatal("invalid command: '%s'", argv[optind]); - rc = 1; - goto exit; + log_error("invalid command '%s'", command); + log_close(); + return EXIT_FAILURE; } - /* Open configuration. */ - conf_t *new_conf = NULL; - if (config_db == NULL) { - int ret = conf_new(&new_conf, conf_scheme, NULL, false); - if (ret != KNOT_EOK) { - log_fatal("failed to initialize configuration database " - "(%s)", knot_strerror(ret)); - rc = 1; - goto exit; - } - - /* Import the configuration file. */ - ret = conf_import(new_conf, config_fn, true); - if (ret != KNOT_EOK) { - log_fatal("failed to load configuration file (%s)", - knot_strerror(ret)); - conf_free(new_conf, false); - rc = 1; - goto exit; - } - - new_conf->filename = strdup(config_fn); - } else { - /* Open configuration database. */ - bool ronly = !(desc->flags & CMD_CONF_WRITE); - int ret = conf_new(&new_conf, conf_scheme, config_db, ronly); - if (ret != KNOT_EOK) { - log_fatal("failed to open configuration database '%s' " - "(%s)", config_db, knot_strerror(ret)); - rc = 1; - goto exit; - } - } - - /* Run post-open config operations. */ - int ret = conf_post_open(new_conf); + /* Set up the configuration */ + int ret = set_config(desc, confdb, config, socket); if (ret != KNOT_EOK) { - log_fatal("failed to use configuration (%s)", knot_strerror(ret)); - conf_free(new_conf, false); - rc = 1; - goto exit; + log_close(); + return EXIT_FAILURE; } - /* Update to the new config. */ - conf_update(new_conf); + /* Prepare command parameters. */ + cmd_args_t args = { + socket, + argc - optind - 1, + argv + optind + 1, + flags + }; - /* Get control socket path. */ + /* Get the control socket from confdb if not specified. */ if (socket == NULL) { conf_val_t listen_val = conf_get(conf(), C_CTL, C_LISTEN); conf_val_t rundir_val = conf_get(conf(), C_SRV, C_RUNDIR); char *rundir = conf_abs_path(&rundir_val, NULL); - socket = conf_abs_path(&listen_val, rundir); + args.socket = conf_abs_path(&listen_val, rundir); free(rundir); } - cmd_args_t args = { - socket, - argc - optind - 1, - argv + optind + 1, - flags, - config_db - }; + log_debug("socket '%s'", (args.socket != NULL) ? args.socket : ""); - /* Execute command. */ + /* Execute the command. */ dnssec_crypto_init(); - rc = desc->cmd(&args); + ret = desc->cmd(&args); dnssec_crypto_cleanup(); -exit: - /* Finish */ - conf_free(conf(), false); + /* Cleanup */ + if (socket == NULL) { + free(args.socket); + } + conf_free(conf()); log_close(); - free(socket); - return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE; + return ret == KNOT_EOK ? EXIT_SUCCESS : EXIT_FAILURE; }