Commit 71d7f795 authored by Daniel Salzman's avatar Daniel Salzman

knotc: parameters processing refactoring

parent 3d2796c5
...@@ -38,167 +38,127 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] ...@@ -38,167 +38,127 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.INDENT 0.0 .INDENT 0.0
.TP .TP
\fB\-c\fP, \fB\-\-config\fP \fIfile\fP \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 .TP
\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP \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 .TP
\fB\-s\fP, \fB\-\-server\fP \fIserver\fP \fB\-s\fP, \fB\-\-socket\fP \fIpath\fP
Remote UNIX socket/IP address (default is \fB@run_dir@/knot.sock\fP). Use a remote control UNIX socket path (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.
.TP .TP
\fB\-f\fP, \fB\-\-force\fP \fB\-f\fP, \fB\-\-force\fP
Force operation. Overrides some checks. Forced operation. Overrides some checks.
.TP .TP
\fB\-v\fP, \fB\-\-verbose\fP \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 .TP
\fB\-V\fP, \fB\-\-version\fP \fB\-V\fP, \fB\-\-version\fP
Print the program version. Print the program version.
.TP
\fB\-h\fP, \fB\-\-help\fP
Print help and usage.
.UNINDENT .UNINDENT
.SS Actions .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 .INDENT 0.0
.TP .TP
\fBstatus\fP
Check if the server is running.
.TP
\fBstop\fP \fBstop\fP
Stop server (no\-op if not running). Stop the server if running.
.TP .TP
\fBreload\fP [\fIzone\fP\&...] \fBreload\fP
Reload particular zones or reload the whole configuration and changed zones. Reload the server configuration.
.TP .TP
\fBflush\fP [\fIzone\fP\&...] \fBzone\-check\fP [\fIzone\fP\&...]
Flush journal and update zone files. Check the zone. (*)
.TP .TP
\fBstatus\fP \fBzone\-memstats\fP [\fIzone\fP\&...]
Check if server is running. Estimate memory use for the zone. (*)
.TP
\fBzone\-status\fP [\fIzone\fP\&...]
Show the status of the zone. (*)
.TP .TP
\fBzonestatus\fP [\fIzone\fP\&...] \fBzone\-reload\fP [\fIzone\fP\&...]
Show the status of listed zones. Trigger a zone reload.
.TP .TP
\fBrefresh\fP [\fIzone\fP\&...] \fBzone\-refresh\fP [\fIzone\fP\&...]
Refresh slave zones. The \fB\-f\fP flag forces re\-transfer (zones must be specified). Trigger a zone refresh (if slave).
.TP .TP
\fBcheckconf\fP \fBzone\-retransfer\fP [\fIzone\fP\&...]
Check the current configuration. Trigger a zone retransfer (if slave).
.TP .TP
\fBcheckzone\fP [\fIzone\fP\&...] \fBzone\-flush\fP [\fIzone\fP\&...]
Check zones. Trigger a zone journal flush into the zone file.
.TP .TP
\fBmemstats\fP [\fIzone\fP\&...] \fBzone\-sing\fP [\fIzone\fP\&...]
Estimate memory consumption for zones. Trigger a zone resign (if enabled).
.TP .TP
\fBsignzone\fP \fIzone\fP\&... \fBconf\-check\fP
Re\-sign the zone (drop all existing signatures and create new ones). Check the server configuration. (*)
.TP .TP
\fBconf\-import\fP \fIfilename\fP \fBconf\-import\fP \fIfilename\fP
Offline import of the configuration DB from a file. This is a Import a config file into the confdb. Ensure the server is not accessing
potentially dangerous operation so the \fB\-f\fP flag is required. Also the the confdb! (*)
destination configuration DB must be specified via \fB\-C\fP\&. Ensure the server
is not running!
.TP .TP
\fBconf\-export\fP \fIfilename\fP \fBconf\-export\fP \fIfilename\fP
Export the configuration DB to a file. If no source configuration DB is Export the confdb into a config file. (*)
specified, the temporary DB, corresponding to textual configuration file, is
used.
.TP .TP
\fBconf\-desc\fP [\fIsection\fP] \fBconf\-list\fP [\fIitem\fP]
Get the configuration section items list. If no section is specified, List the confdb sections or section items.
the list of sections is returned.
.TP .TP
\fBconf\-read\fP [\fIitem\fP] \fBconf\-read\fP [\fIitem\fP]
Read from the current configuration DB. Read the item from the active confdb.
.TP .TP
\fBconf\-begin\fP \fBconf\-begin\fP
Begin a writing configuration DB transaction. Only one transaction can be Begin a writing confdb transaction. Only one transaction can be opened at a time.
opened at a time.
.TP .TP
\fBconf\-commit\fP \fBconf\-commit\fP
Commit the current writing configuration DB transaction. Commit the confdb transaction.
.TP .TP
\fBconf\-abort\fP \fBconf\-abort\fP
Abort the current writing configuration DB transaction. Rollback the confdb transaction.
.TP .TP
\fBconf\-diff\fP [\fIitem\fP] \fBconf\-diff\fP [\fIitem\fP]
Get the difference between the active writing transaction and the current Get the item difference in the transaction.
configuration DB. Requires active writing configuration DB transaction.
.TP .TP
\fBconf\-get\fP [\fIitem\fP] \fBconf\-get\fP [\fIitem\fP]
Read from the active writing configuration DB transaction. Get the item data from the transaction.
Requires active writing configuration DB transaction.
.TP .TP
\fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...] \fBconf\-set\fP \fIitem\fP [\fIdata\fP\&...]
Write to the active writing configuration DB transaction. Set the item data in the transaction.
Requires active writing configuration DB transaction.
.TP .TP
\fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...] \fBconf\-unset\fP [\fIitem\fP] [\fIdata\fP\&...]
Delete from the active writing configuration DB transaction. Unset the item data in the 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
.UNINDENT .UNINDENT
.SH NOTE
.sp .sp
The generated key file contains a key in the server configuration format and Empty \fIzone\fP parameter means all zones.
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
.sp .sp
.nf Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP].
.ft C
$ head \-1 knotc\-key.conf | sed \(aqs/^#\es*//\(aq > knotc.key
.ft P
.fi
.UNINDENT
.UNINDENT
.sp .sp
Make sure the key file can be read only by the owner for security reasons. (*) indicates a local operation requiring a configuration specified.
.SS Reload server remotely .SH EXAMPLES
.SS Reload the whole server configuration
.INDENT 0.0 .INDENT 0.0
.INDENT 3.5 .INDENT 3.5
.sp .sp
.nf .nf
.ft C .ft C
$ knotc \-s 127.0.0.1 \-k knotc.key reload $ knotc reload
.ft P .ft P
.fi .fi
.UNINDENT .UNINDENT
.UNINDENT .UNINDENT
.SS Flush all zones locally .SS Flush the example.com and example.eu zones
.INDENT 0.0 .INDENT 0.0
.INDENT 3.5 .INDENT 3.5
.sp .sp
.nf .nf
.ft C .ft C
$ knotc \-c knot.conf flush $ knotc zone\-flush example.com example.eu
.ft P .ft P
.fi .fi
.UNINDENT .UNINDENT
......
...@@ -41,7 +41,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] ...@@ -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). Use a textual configuration file (default is \fB@config_dir@/knot.conf\fP).
.TP .TP
\fB\-C\fP, \fB\-\-confdb\fP \fIdirectory\fP \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 .TP
\fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP] \fB\-d\fP, \fB\-\-daemonize\fP [\fIdirectory\fP]
Run the server as a daemon. New root directory may be specified Run the server as a daemon. New root directory may be specified
......
...@@ -15,152 +15,131 @@ Parameters ...@@ -15,152 +15,131 @@ Parameters
.......... ..........
**-c**, **--config** *file* **-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* **-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* **-s**, **--socket** *path*
Remote UNIX socket/IP address (default is :file:`@run_dir@/knot.sock`). Use a remote control UNIX socket path (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.
**-f**, **--force** **-f**, **--force**
Force operation. Overrides some checks. Forced operation. Overrides some checks.
**-v**, **--verbose** **-v**, **--verbose**
Verbose mode. Print additional runtime information. Enable debug output.
**-h**, **--help**
Print the program help.
**-V**, **--version** **-V**, **--version**
Print the program version. Print the program version.
**-h**, **--help**
Print help and usage.
Actions Actions
....... .......
If the optional *zone* argument is not specified, the command is applied to all **status**
zones. Check if the server is running.
Configuration *item* is in the *section*\ [**[**\ *id*\ **]**\ ][**.**\ *item*]
format.
**stop** **stop**
Stop server (no-op if not running). Stop the server if running.
**reload** [*zone*...] **reload**
Reload particular zones or reload the whole configuration and changed zones. Reload the server configuration.
**flush** [*zone*...]
Flush journal and update zone files.
**status** **zone-check** [*zone*...]
Check if server is running. Check the zone. (*)
**zone-memstats** [*zone*...]
Estimate memory use for the zone. (*)
**zone-status** [*zone*...]
Show the status of the zone. (*)
**zonestatus** [*zone*...] **zone-reload** [*zone*...]
Show the status of listed zones. Trigger a zone reload.
**refresh** [*zone*...] **zone-refresh** [*zone*...]
Refresh slave zones. The **-f** flag forces re-transfer (zones must be specified). Trigger a zone refresh (if slave).
**checkconf** **zone-retransfer** [*zone*...]
Check the current configuration. Trigger a zone retransfer (if slave).
**checkzone** [*zone*...] **zone-flush** [*zone*...]
Check zones. Trigger a zone journal flush into the zone file.
**memstats** [*zone*...] **zone-sing** [*zone*...]
Estimate memory consumption for zones. 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* **conf-import** *filename*
Offline import of the configuration DB from a file. This is a Import a config file into the confdb. Ensure the server is not accessing
potentially dangerous operation so the **-f** flag is required. Also the the confdb! (*)
destination configuration DB must be specified via **-C**. Ensure the server
is not running!
**conf-export** *filename* **conf-export** *filename*
Export the configuration DB to a file. If no source configuration DB is Export the confdb into a config file. (*)
specified, the temporary DB, corresponding to textual configuration file, is
used.
**conf-desc** [*section*] **conf-list** [*item*]
Get the configuration section items list. If no section is specified, List the confdb sections or section items.
the list of sections is returned.
**conf-read** [*item*] **conf-read** [*item*]
Read from the current configuration DB. Read the item from the active confdb.
**conf-begin** **conf-begin**
Begin a writing configuration DB transaction. Only one transaction can be Begin a writing confdb transaction. Only one transaction can be opened at a time.
opened at a time.
**conf-commit** **conf-commit**
Commit the current writing configuration DB transaction. Commit the confdb transaction.
**conf-abort** **conf-abort**
Abort the current writing configuration DB transaction. Rollback the confdb transaction.
**conf-diff** [*item*] **conf-diff** [*item*]
Get the difference between the active writing transaction and the current Get the item difference in the transaction.
configuration DB. Requires active writing configuration DB transaction.
**conf-get** [*item*] **conf-get** [*item*]
Read from the active writing configuration DB transaction. Get the item data from the transaction.
Requires active writing configuration DB transaction.
**conf-set** *item* [*data*...] **conf-set** *item* [*data*...]
Write to the active writing configuration DB transaction. Set the item data in the transaction.
Requires active writing configuration DB transaction.
**conf-unset** [*item*] [*data*...] **conf-unset** [*item*] [*data*...]
Delete from the active writing configuration DB transaction. Unset the item data in the transaction.
Requires active writing configuration DB transaction.
Examples
--------
Setup a key file for remote control Note
................................... ----
:: Empty *zone* parameter means all zones.
$ 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.
Knot DNS utilities accept one-line format which is included in the generated Type *item* parameter in the form of *section*\ [**[**\ *id*\ **]**\ ][**.**\ *name*].
key file on the first line as a comment. It can be extracted easily::
$ 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 Get the current server configuration
.................................... ....................................
......
...@@ -18,7 +18,9 @@ Parameters ...@@ -18,7 +18,9 @@ Parameters
Use a textual configuration file (default is :file:`@config_dir@/knot.conf`). Use a textual configuration file (default is :file:`@config_dir@/knot.conf`).
**-C**, **--confdb** *directory* **-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*] **-d**, **--daemonize** [*directory*]
Run the server as a daemon. New root directory may be specified Run the server as a daemon. New root directory may be specified
......
...@@ -18,114 +18,191 @@ ...@@ -18,114 +18,191 @@
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "contrib/sockaddr.h"
#include "dnssec/crypto.h" #include "dnssec/crypto.h"
#include "knot/common/log.h" #include "knot/common/log.h"
#include "knot/conf/conf.h" #include "knot/conf/conf.h"
#include "libknot/libknot.h" #include "libknot/libknot.h"
#include "utils/knotc/commands.h" #include "utils/knotc/commands.h"
#include "utils/common/params.h"
/*! \brief Print help. */ #define PROGRAM_NAME "knotc"
static void help(void)
static void print_help(void)
{ {
printf("Usage: knotc [parameters] <action> [action_args]\n" printf("Usage: %s [parameters] <action> [action_args]\n"
"\n" "\n"
"Parameters:\n" "Parameters:\n"
" -c, --config <file> Select configuration file.\n" " -c, --config <file> Use a textual configuration file.\n"
" (default %s)\n" " (default %s)\n"
" -C, --confdb <dir> Select configuration database directory.\n" " -C, --confdb <dir> Use a binary configuration database directory.\n"
" -s, --socket <path> Remote control UNIX socket.\n" " (default %s)\n"
" (default %s)\n" " -s, --socket <path> Use a remote control UNIX socket path.\n"
" -f, --force Force operation - override some checks.\n" " (default %s)\n"
" -v, --verbose Verbose mode - additional runtime information.\n" " -f, --force Forced operation. Overrides some checks.\n"
" -V, --version Print %s server version.\n" " -v, --verbose Enable debug output.\n"
" -h, --help Print help and usage.\n" " -h, --help Print the program help.\n"
" -V, --version Print the program version.\n"
"\n" "\n"
"Actions:\n", "Actions:\n",
CONF_DEFAULT_FILE, RUN_DIR "/knot.sock", PACKAGE_NAME); PROGRAM_NAME, CONF_DEFAULT_FILE, CONF_DEFAULT_DBDIR, RUN_DIR "/knot.sock");
cmd_help_t *c = cmd_help_table;
while (c->name != NULL) { for (const cmd_help_t *cmd = cmd_help_table; cmd->name != NULL; cmd++) {
printf(" %-13s %-20s %s\n", c->name, c->params, c->desc); printf(" %-15s %-20s %s\n", cmd->name, cmd->params, cmd->desc);
++c; }
}
printf("\nThe item argument must be in the section[identifier].item format.\n"); printf("\n"
printf("\nIf optional <zone> parameter is not specified, command is applied to all zones.\n\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) int main(int argc, char **argv)
{ {
/* Parse command line arguments */ cmd_flag_t flags = CMD_FNONE;
int c = 0, li = 0, rc = 0; const char *config = NULL;
unsigned flags = CMD_NONE; const char *confdb = NULL;
const char *config_fn = CONF_DEFAULT_FILE;
const char *config_db = NULL;
char *socket = NULL; char *socket = NULL;
bool verbose = false;
/* Initialize. */
log_init();
log_levels_set(LOG_SYSLOG, LOG_ANY, 0);
/* Long options. */ /* Long options. */
struct option opts[] = { struct option opts[] = {
{ "config", required_argument, 0, 'c' }, { "config", required_argument, NULL, 'c' },
{ "confdb", required_argument, 0, 'C' }, { "confdb", required_argument, NULL, 'C' },
{ "socket", required_argument, 0, 's' }, { "socket", required_argument, NULL, 's' },
{ "force", no_argument, 0, 'f' }, { "force", no_argument, NULL, 'f' },
{ "verbose", no_argument, 0, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, 0, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, 0, 'V' }, { "version", no_argument, NULL, 'V' },
{ NULL } { NULL }
}; };
while ((c = getopt_long(argc, argv, "s:fc:C:vVh", opts, &li)) != -1) { /* Parse command line arguments */
switch (c) { int opt = 0, li = 0;
while ((opt = getopt_long(argc, argv, "c:C:s:fvhV", opts, &li)) != -1) {
switch (opt) {
case 'c': case 'c':
config_fn = optarg; config = optarg;
break; break;
case 'C': case 'C':
config_db = optarg; confdb = optarg;
break; break;
case 's': case 's':
socket = strdup(optarg); socket = optarg;
break; break;
case 'f': case 'f':
flags |= CMD_FORCE; flags |= CMD_FFORCE;
break; break;
case 'v': case 'v':
log_levels_add(LOGT_STDOUT, LOG_ANY, verbose = true;
LOG_MASK(LOG_INFO) | LOG_MASK(LOG_DEBUG));
break;