\fB\-t\fP, \fB\-\-timeout\fP \fIseconds\fP
Use a control timeout in seconds. Set 0 for infinity (default is 10).
.TP
+\fB\-b\fP, \fB\-\-blocking\fP
+Zone event trigger commands wait until the event is finished.
+.TP
\fB\-f\fP, \fB\-\-force\fP
Forced operation. Overrides some checks.
.TP
Trigger a zone reload from a disk without checking its modification time. For
slave zone, the refresh from a master server is scheduled; for master zone,
the notification of slave servers is scheduled. An open zone transaction
-will be aborted!
+will be aborted! (#)
.TP
\fBzone\-refresh\fP [\fIzone\fP\&...]
Trigger a check for the zone serial on the zone\(aqs master. If the master has a
-newer zone, a transfer is scheduled. This command is valid for slave zones.
+newer zone, a transfer is scheduled. This command is valid for slave zones. (#)
.TP
\fBzone\-retransfer\fP [\fIzone\fP\&...]
Trigger a zone transfer from the zone\(aqs master. The server doesn\(aqt check the
-serial of the master\(aqs zone. This command is valid for slave zones.
+serial of the master\(aqs zone. This command is valid for slave zones. (#)
.TP
\fBzone\-notify\fP [\fIzone\fP\&...]
Trigger a NOTIFY message to all configured remotes. This can help in cases
-when previous NOTIFY had been lost or the slaves offline.
+when previous NOTIFY had been lost or the slaves offline. (#)
.TP
\fBzone\-flush\fP [\fIzone\fP\&...] [\fB+outdir\fP \fIdirectory\fP]
Trigger a zone journal flush into the zone file. If output dir is specified,
instead of flushing the zonefile, the zone is dumped to a file in the specified
-directory.
+directory. (#)
.TP
\fBzone\-sign\fP [\fIzone\fP\&...]
Trigger a DNSSEC re\-sign of the zone. Existing signatures will be dropped.
-This command is valid for zones with DNSSEC signing enabled.
+This command is valid for zones with DNSSEC signing enabled. (#)
.TP
\fBzone\-key\-rollover\fP \fIzone\fP \fIkey_type\fP
Trigger immediate key rollover. Publish new key and start a key rollover,
even when the key has a lifetime to go. Key type can be \fBksk\fP (also for CSK)
or \fBzsk\fP\&. This command is valid for zones with DNSSEC signing and automatic
-key management enabled.
+key management enabled. Note that complete key rollover consists of several steps
+and the blocking mode relates to the initial one only! (#)
.TP
\fBzone\-ksk\-submitted\fP \fIzone\fP\&...
Use when the zone\(aqs KSK rollover is in submittion phase. By calling this command
the user confirms manually that the parent zone contains DS record for the new
-KSK in submission phase and the old KSK can be retired.
+KSK in submission phase and the old KSK can be retired. (#)
.TP
\fBzone\-freeze\fP [\fIzone\fP\&...]
Temporarily postpone zone\-changing events (load, refresh, update, flush, and
-DNSSEC signing).
+DNSSEC signing). (#)
.TP
\fBzone\-thaw\fP [\fIzone\fP\&...]
-Dismiss zone freeze.
+Dismiss zone freeze. (#)
.TP
\fBzone\-read\fP \fIzone\fP [\fIowner\fP [\fItype\fP]]
Get zone data that are currently being presented.
Available filters are \fB+expire\fP, \fB+zonefile\fP, \fB+journal\fP, \fB+timers\fP,
and \fB+kaspdb\fP\&. If no filter is specified, all filters are enabled.
If the zone is no longer configured, add \fB+orphan\fP filter (zone file cannot
-be purged in this case).
+be purged in this case). (#)
.TP
\fBzone\-stats\fP \fIzone\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]]
Show zone statistics counter(s). To print also counters with value 0, use
.sp
(*) indicates a local operation which requires a configuration.
.sp
-Use \fB\-\-force\fP or \fB\-f\fP as the first parameter of any command to force it.
+(#) indicates an optionally blocking operation.
+.sp
+The \fI\-b\fP and \fI\-f\fP options can be placed right after the command name.
.SS Interactive mode
.sp
The utility provides interactive mode with basic line editing functionality,
**-t**, **--timeout** *seconds*
Use a control timeout in seconds. Set 0 for infinity (default is 10).
+**-b**, **--blocking**
+ Zone event trigger commands wait until the event is finished.
+
**-f**, **--force**
Forced operation. Overrides some checks.
Trigger a zone reload from a disk without checking its modification time. For
slave zone, the refresh from a master server is scheduled; for master zone,
the notification of slave servers is scheduled. An open zone transaction
- will be aborted!
+ will be aborted! (#)
**zone-refresh** [*zone*...]
Trigger a check for the zone serial on the zone's master. If the master has a
- newer zone, a transfer is scheduled. This command is valid for slave zones.
+ newer zone, a transfer is scheduled. This command is valid for slave zones. (#)
**zone-retransfer** [*zone*...]
Trigger a zone transfer from the zone's master. The server doesn't check the
- serial of the master's zone. This command is valid for slave zones.
+ serial of the master's zone. This command is valid for slave zones. (#)
**zone-notify** [*zone*...]
Trigger a NOTIFY message to all configured remotes. This can help in cases
- when previous NOTIFY had been lost or the slaves offline.
+ when previous NOTIFY had been lost or the slaves offline. (#)
**zone-flush** [*zone*...] [**+outdir** *directory*]
Trigger a zone journal flush into the zone file. If output dir is specified,
instead of flushing the zonefile, the zone is dumped to a file in the specified
- directory.
+ directory. (#)
**zone-sign** [*zone*...]
Trigger a DNSSEC re-sign of the zone. Existing signatures will be dropped.
- This command is valid for zones with DNSSEC signing enabled.
+ This command is valid for zones with DNSSEC signing enabled. (#)
**zone-key-rollover** *zone* *key_type*
Trigger immediate key rollover. Publish new key and start a key rollover,
even when the key has a lifetime to go. Key type can be **ksk** (also for CSK)
or **zsk**. This command is valid for zones with DNSSEC signing and automatic
- key management enabled.
+ key management enabled. Note that complete key rollover consists of several steps
+ and the blocking mode relates to the initial one only! (#)
**zone-ksk-submitted** *zone*...
Use when the zone's KSK rollover is in submittion phase. By calling this command
the user confirms manually that the parent zone contains DS record for the new
- KSK in submission phase and the old KSK can be retired.
+ KSK in submission phase and the old KSK can be retired. (#)
**zone-freeze** [*zone*...]
Temporarily postpone zone-changing events (load, refresh, update, flush, and
- DNSSEC signing).
+ DNSSEC signing). (#)
**zone-thaw** [*zone*...]
- Dismiss zone freeze.
+ Dismiss zone freeze. (#)
**zone-read** *zone* [*owner* [*type*]]
Get zone data that are currently being presented.
Available filters are **+expire**, **+zonefile**, **+journal**, **+timers**,
and **+kaspdb**. If no filter is specified, all filters are enabled.
If the zone is no longer configured, add **+orphan** filter (zone file cannot
- be purged in this case).
+ be purged in this case). (#)
**zone-stats** *zone* [*module*\ [\ **.**\ *counter*\ ]]
Show zone statistics counter(s). To print also counters with value 0, use
(*) indicates a local operation which requires a configuration.
-Use **--force** or **-f** as the first parameter of any command to force it.
+(\#) indicates an optionally blocking operation.
+
+The *-b* and *-f* options can be placed right after the command name.
Interactive mode
................
#define MATCH_AND_FILTER(args, code) ((args)->data[KNOT_CTL_IDX_FILTER] != NULL && \
strchr((args)->data[KNOT_CTL_IDX_FILTER], (code)) != NULL)
+static void schedule_trigger(zone_t *zone, ctl_args_t *args, zone_event_type_t event,
+ bool user)
+{
+ if (ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_BLOCKING)) {
+ zone_events_schedule_blocking(zone, event, user);
+ } else if (user) {
+ zone_events_schedule_user(zone, event);
+ } else {
+ zone_events_schedule_now(zone, event);
+ }
+}
+
void ctl_log_data(knot_ctl_data_t *data)
{
if (data == NULL) {
return KNOT_ENOTSUP;
}
- zone_events_schedule_user(zone, ZONE_EVENT_LOAD);
+ schedule_trigger(zone, args, ZONE_EVENT_LOAD, true);
return KNOT_EOK;
}
return KNOT_ENOTSUP;
}
- zone_events_schedule_user(zone, ZONE_EVENT_REFRESH);
+ schedule_trigger(zone, args, ZONE_EVENT_REFRESH, true);
return KNOT_EOK;
}
}
zone->flags |= ZONE_FORCE_AXFR;
- zone_events_schedule_user(zone, ZONE_EVENT_REFRESH);
+ schedule_trigger(zone, args, ZONE_EVENT_REFRESH, true);
return KNOT_EOK;
}
{
UNUSED(args);
- zone_events_schedule_user(zone, ZONE_EVENT_NOTIFY);
+ schedule_trigger(zone, args, ZONE_EVENT_NOTIFY, true);
return KNOT_EOK;
}
zone->flags |= ZONE_FORCE_FLUSH;
}
- zone_events_schedule_user(zone, ZONE_EVENT_FLUSH);
+ schedule_trigger(zone, args, ZONE_EVENT_FLUSH, true);
return KNOT_EOK;
}
}
zone->flags |= ZONE_FORCE_RESIGN;
- zone_events_schedule_user(zone, ZONE_EVENT_DNSSEC);
+ schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, true);
return KNOT_EOK;
}
return KNOT_EINVAL;
}
- zone_events_schedule_user(zone, ZONE_EVENT_DNSSEC);
+ schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, true);
return KNOT_EOK;
}
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_SIGNING, zone->name);
if (ret == KNOT_EOK && conf_bool(&val)) {
// NOT zone_events_schedule_user(), intentionally!
- zone_events_schedule_now(zone, ZONE_EVENT_DNSSEC);
+ schedule_trigger(zone, args, ZONE_EVENT_DNSSEC, false);
}
return ret;
{
UNUSED(args);
- zone_events_schedule_now(zone, ZONE_EVENT_UFREEZE);
+ schedule_trigger(zone, args, ZONE_EVENT_UFREEZE, false);
return KNOT_EOK;
}
{
UNUSED(args);
- zone_events_schedule_now(zone, ZONE_EVENT_UTHAW);
+ schedule_trigger(zone, args, ZONE_EVENT_UTHAW, false);
return KNOT_EOK;
}
// Expire the zone.
if (MATCH_OR_FILTER(args, CTL_FILTER_PURGE_EXPIRE)) {
- zone_events_schedule_user(zone, ZONE_EVENT_EXPIRE);
+ schedule_trigger(zone, args, ZONE_EVENT_EXPIRE, true);
}
// Purge the zone file.
-/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "libknot/libknot.h"
#include "knot/server/server.h"
-#define CTL_FLAG_FORCE "F"
-#define CTL_FLAG_ADD "+"
-#define CTL_FLAG_REM "-"
+#define CTL_FLAG_FORCE "F"
+#define CTL_FLAG_BLOCKING "B"
+#define CTL_FLAG_ADD "+"
+#define CTL_FLAG_REM "-"
#define CTL_FILTER_FLUSH_OUTDIR 'd'
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL,
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
[KNOT_CTL_IDX_TYPE] = args->argc > 0 ? args->argv[0] : NULL
};
{
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
};
int ret = set_stats_items(args, &data);
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL,
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
[KNOT_CTL_IDX_ZONE] = args->argv[0],
[KNOT_CTL_IDX_TYPE] = args->argv[1],
};
{
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
};
// Check the number of arguments.
{
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
};
if (args->desc->cmd == CTL_ZONE_PURGE && !args->force) {
{
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
};
char rdata[65536]; // Maximum item size in libknot control interface.
knot_ctl_data_t data = {
[KNOT_CTL_IDX_CMD] = ctl_cmd_to_str(args->desc->cmd),
- [KNOT_CTL_IDX_FLAGS] = args->force ? CTL_FLAG_FORCE : NULL
+ [KNOT_CTL_IDX_FLAGS] = args->flags,
};
// Send the command without parameters.
{ "", "", "" },
{ CMD_ZONE_CHECK, "[<zone>...]", "Check if the zone can be loaded. (*)" },
{ CMD_ZONE_MEMSTATS, "[<zone>...]", "Estimate memory use for the zone. (*)" },
- { CMD_ZONE_RELOAD, "[<zone>...]", "Reload a zone from a disk." },
- { CMD_ZONE_REFRESH, "[<zone>...]", "Force slave zone refresh." },
- { CMD_ZONE_NOTIFY, "[<zone>...]", "Send a NOTIFY message to all configured remotes." },
- { CMD_ZONE_RETRANSFER, "[<zone>...]", "Force slave zone retransfer (no serial check)." },
- { CMD_ZONE_FLUSH, "[<zone>...] [<filter>...]", "Flush zone journal into the zone file." },
- { CMD_ZONE_SIGN, "[<zone>...]", "Re-sign the automatically signed zone." },
- { CMD_ZONE_KEY_ROLL, " <zone> ksk|zsk", "Trigger immediate key rollover." },
- { CMD_ZONE_KSK_SBM, " <zone>...", "When KSK submission, confirm parent's DS presence." },
- { CMD_ZONE_FREEZE, "[<zone>...]", "Temporarily postpone automatic zone-changing events." },
- { CMD_ZONE_THAW, "[<zone>...]", "Dismiss zone freeze." },
+ { CMD_ZONE_RELOAD, "[<zone>...]", "Reload a zone from a disk. (#)" },
+ { CMD_ZONE_REFRESH, "[<zone>...]", "Force slave zone refresh. (#)" },
+ { CMD_ZONE_NOTIFY, "[<zone>...]", "Send a NOTIFY message to all configured remotes. (#)" },
+ { CMD_ZONE_RETRANSFER, "[<zone>...]", "Force slave zone retransfer (no serial check). (#)" },
+ { CMD_ZONE_FLUSH, "[<zone>...] [<filter>...]", "Flush zone journal into the zone file. (#)" },
+ { CMD_ZONE_SIGN, "[<zone>...]", "Re-sign the automatically signed zone. (#)" },
+ { CMD_ZONE_KEY_ROLL, " <zone> ksk|zsk", "Trigger immediate key rollover. (#)" },
+ { CMD_ZONE_KSK_SBM, " <zone>...", "When KSK submission, confirm parent's DS presence. (#)" },
+ { CMD_ZONE_FREEZE, "[<zone>...]", "Temporarily postpone automatic zone-changing events. (#)" },
+ { CMD_ZONE_THAW, "[<zone>...]", "Dismiss zone freeze. (#)" },
{ "", "", "" },
{ CMD_ZONE_READ, "<zone> [<owner> [<type>]]", "Get zone data that are currently being presented." },
{ CMD_ZONE_BEGIN, "<zone>...", "Begin a zone transaction." },
{ CMD_ZONE_GET, "<zone> [<owner> [<type>]]", "Get zone data within the transaction." },
{ CMD_ZONE_SET, "<zone> <owner> [<ttl>] <type> <rdata>", "Add zone record within the transaction." },
{ CMD_ZONE_UNSET, "<zone> <owner> [<type> [<rdata>]]", "Remove zone data within the transaction." },
- { CMD_ZONE_PURGE, "<zone>... [<filter>...]", "Purge zone data, zone file, journal, timers, and KASP data." },
+ { CMD_ZONE_PURGE, "<zone>... [<filter>...]", "Purge zone data, zone file, journal, timers, and KASP data. (#)" },
{ CMD_ZONE_STATS, "<zone> [<module>[.<counter>]]", "Show zone statistics counter(s)."},
{ CMD_ZONE_STATUS, "<zone> [<filter>...]", "Show the zone status." },
{ "", "", "" },
" Empty or '--' <zone> parameter means all zones or all zones with a transaction.\n"
" Type <item> parameter in the form of <section>[<identifier>].<name>.\n"
" (*) indicates a local operation which requires a configuration.\n"
- " Use '--force' or '-f' as the first parameter of any command to force it.\n");
+ " (#) indicates an optionally blocking operation.\n"
+ " The '-b' and '-f' options can be placed right after the command name.\n");
}
-/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
knot_ctl_t *ctl;
int argc;
const char **argv;
+ char flags[4];
bool force;
+ bool blocking;
} cmd_args_t;
/*! \brief Command callback description. */
" "SPACE" (default %s)\n"
" -t, --timeout <sec> "SPACE"Use a control socket timeout (max 7200 seconds).\n"
" "SPACE" (default %u seconds)\n"
+ " -b, --blocking "SPACE"Zone event trigger commands wait until the event is finished.\n"
" -f, --force "SPACE"Forced operation. Overrides some checks.\n"
" -v, --verbose "SPACE"Enable debug output.\n"
" -h, --help "SPACE"Print the program help.\n"
{ "max-conf-size", required_argument, NULL, 'm' },
{ "socket", required_argument, NULL, 's' },
{ "timeout", required_argument, NULL, 't' },
+ { "blocking", no_argument, NULL, 'b' },
{ "force", no_argument, NULL, 'f' },
{ "verbose", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
/* Parse command line arguments */
int opt = 0;
- while ((opt = getopt_long(argc, argv, "+c:C:m:s:t:fvhV", opts, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+c:C:m:s:t:bfvhV", opts, NULL)) != -1) {
switch (opt) {
case 'c':
params.config = optarg;
/* Convert to milliseconds. */
params.timeout *= 1000;
break;
+ case 'b':
+ params.blocking = true;
+ break;
case 'f':
params.force = true;
break;
-/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+#include <stddef.h>
#include <sys/stat.h>
+#include "contrib/openbsd/strlcat.h"
#include "knot/conf/conf.h"
#include "knot/common/log.h"
#include "utils/knotc/commands.h"
return false;
}
+static bool get_cmd_blocking_flag(const char *arg)
+{
+ if (strcmp(arg, "-b") == 0 || strcmp(arg, "--blocking") == 0) {
+ return true;
+ }
+ return false;
+}
+
int set_config(const cmd_desc_t *desc, params_t *params)
{
if (params->config != NULL && params->confdb != NULL) {
.desc = desc,
.argc = argc - 1,
.argv = argv + 1,
- .force = params->force
+ .force = params->force,
+ .blocking = params->blocking
};
- /* Check for --force flag after command. */
- if (args.argc > 0 && get_cmd_force_flag(args.argv[0])) {
- args.force = true;
- args.argc--;
- args.argv++;
+ /* Check for special flags after command. */
+ while (args.argc > 0) {
+ if (get_cmd_force_flag(args.argv[0])) {
+ args.force = true;
+ args.argc--;
+ args.argv++;
+ } else if (get_cmd_blocking_flag(args.argv[0])) {
+ args.blocking = true;
+ args.argc--;
+ args.argv++;
+ } else {
+ break;
+ }
+ }
+
+ /* Prepare flags parameter. */
+ if (args.force) {
+ strlcat(args.flags, CTL_FLAG_FORCE, sizeof(args.flags));
+ }
+ if (args.blocking) {
+ strlcat(args.flags, CTL_FLAG_BLOCKING, sizeof(args.flags));
}
/* Set control interface if necessary. */
-/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
const char *socket;
bool verbose;
bool force;
+ bool blocking;
int timeout;
} params_t;