diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
commit | 45d6379135504814ab723b57f0eb8be23393a51d (patch) | |
tree | d4f2ec4acca824a8446387a758b0ce4238a4dffa /bin/rndc | |
parent | Initial commit. (diff) | |
download | bind9-45d6379135504814ab723b57f0eb8be23393a51d.tar.xz bind9-45d6379135504814ab723b57f0eb8be23393a51d.zip |
Adding upstream version 1:9.16.44.upstream/1%9.16.44
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'bin/rndc')
-rw-r--r-- | bin/rndc/Makefile.in | 74 | ||||
l--------- | bin/rndc/include/.clang-format | 1 | ||||
-rw-r--r-- | bin/rndc/include/rndc/os.h | 36 | ||||
-rw-r--r-- | bin/rndc/rndc.c | 1105 | ||||
-rw-r--r-- | bin/rndc/rndc.conf | 41 | ||||
-rw-r--r-- | bin/rndc/rndc.conf.rst | 156 | ||||
-rw-r--r-- | bin/rndc/rndc.rst | 608 | ||||
-rw-r--r-- | bin/rndc/util.c | 49 | ||||
-rw-r--r-- | bin/rndc/util.h | 46 | ||||
-rw-r--r-- | bin/rndc/win32/rndc.vcxproj.filters.in | 27 | ||||
-rw-r--r-- | bin/rndc/win32/rndc.vcxproj.in | 122 | ||||
-rw-r--r-- | bin/rndc/win32/rndc.vcxproj.user | 3 | ||||
-rw-r--r-- | bin/rndc/win32/rndcutil.vcxproj.filters.in | 27 | ||||
-rw-r--r-- | bin/rndc/win32/rndcutil.vcxproj.in | 113 | ||||
-rw-r--r-- | bin/rndc/win32/rndcutil.vcxproj.user | 3 |
15 files changed, 2411 insertions, 0 deletions
diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in new file mode 100644 index 0000000..d2a5366 --- /dev/null +++ b/bin/rndc/Makefile.in @@ -0,0 +1,74 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +VERSION=@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I${srcdir}/include ${ISC_INCLUDES} ${ISCCC_INCLUDES} \ + ${ISCCFG_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ +ISCLIBS = ../../lib/isc/libisc.@A@ @NO_LIBTOOL_ISCLIBS@ +ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ @NO_LIBTOOL_ISCLIBS@ +DNSLIBS = ../../lib/dns/libdns.@A@ @NO_LIBTOOL_DNSLIBS@ +BIND9LIBS = ../../lib/bind9/libbind9.@A@ + +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +DNSDEPLIBS = ../../lib/dns/libdns.@A@ +BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@ + +LIBS = ${ISCLIBS} @LIBS@ +NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@ + +RNDCDEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${BIND9DEPLIBS} ${DNSDEPLIBS} ${ISCDEPLIBS} + +CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS} + +SRCS= rndc.c + +TARGETS = rndc@EXEEXT@ + +@BIND9_MAKE_RULES@ + +rndc.@O@: rndc.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \ + -DRNDC_KEYFILE=\"${sysconfdir}/rndc.key\" \ + -c ${srcdir}/rndc.c + +rndc@EXEEXT@: rndc.@O@ util.@O@ ${RNDCDEPLIBS} + export BASEOBJS="rndc.@O@ util.@O@"; \ + export LIBS0="${ISCCFGLIBS} ${ISCCCLIBS} ${BIND9LIBS} ${DNSLIBS} ${ISCLIBS}"; \ + ${FINALBUILDCMD} + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} + +install:: rndc@EXEEXT@ installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} rndc@EXEEXT@ ${DESTDIR}${sbindir} + +uninstall:: + ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${sbindir}/rndc@EXEEXT@ + +clean distclean maintainer-clean:: + rm -f ${TARGETS} diff --git a/bin/rndc/include/.clang-format b/bin/rndc/include/.clang-format new file mode 120000 index 0000000..0e62f72 --- /dev/null +++ b/bin/rndc/include/.clang-format @@ -0,0 +1 @@ +../../../.clang-format.headers
\ No newline at end of file diff --git a/bin/rndc/include/rndc/os.h b/bin/rndc/include/rndc/os.h new file mode 100644 index 0000000..000dbde --- /dev/null +++ b/bin/rndc/include/rndc/os.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifndef RNDC_OS_H +#define RNDC_OS_H 1 + +#include <stdio.h> + +#include <isc/lang.h> + +ISC_LANG_BEGINDECLS + +int +set_user(FILE *fd, const char *user); +/*%< + * Set the owner of the file referenced by 'fd' to 'user'. + * Returns: + * 0 success + * -1 insufficient permissions, or 'user' does not exist. + */ + +ISC_LANG_ENDDECLS + +#endif /* ifndef RNDC_OS_H */ diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c new file mode 100644 index 0000000..2fa9ca6 --- /dev/null +++ b/bin/rndc/rndc.c @@ -0,0 +1,1105 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <inttypes.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <isc/app.h> +#include <isc/atomic.h> +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/file.h> +#include <isc/log.h> +#include <isc/managers.h> +#include <isc/mem.h> +#include <isc/net.h> +#include <isc/print.h> +#include <isc/random.h> +#include <isc/refcount.h> +#include <isc/socket.h> +#include <isc/stdtime.h> +#include <isc/string.h> +#include <isc/task.h> +#include <isc/thread.h> +#include <isc/util.h> + +#include <pk11/site.h> + +#include <dns/name.h> + +#include <isccc/alist.h> +#include <isccc/base64.h> +#include <isccc/cc.h> +#include <isccc/ccmsg.h> +#include <isccc/result.h> +#include <isccc/sexpr.h> +#include <isccc/types.h> +#include <isccc/util.h> + +#include <isccfg/namedconf.h> + +#include <bind9/getaddresses.h> + +#include "util.h" + +#define SERVERADDRS 10 + +const char *progname; +bool verbose; + +static const char *admin_conffile; +static const char *admin_keyfile; +static const char *version = VERSION; +static const char *servername = NULL; +static isc_sockaddr_t serveraddrs[SERVERADDRS]; +static isc_sockaddr_t local4, local6; +static bool local4set = false, local6set = false; +static int nserveraddrs; +static int currentaddr = 0; +static unsigned int remoteport = 0; +static isc_socketmgr_t *socketmgr = NULL; +static isc_buffer_t *databuf; +static isccc_ccmsg_t ccmsg; +static uint32_t algorithm; +static isccc_region_t secret; +static bool failed = false; +static bool c_flag = false; +static isc_mem_t *rndc_mctx; +static atomic_uint_fast32_t sends = 0; +static atomic_uint_fast32_t recvs = 0; +static atomic_uint_fast32_t connects = 0; +static char *command; +static char *args; +static char program[256]; +static isc_socket_t *sock = NULL; +static uint32_t serial; +static bool quiet = false; +static bool showresult = false; + +static void +rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task); + +ISC_PLATFORM_NORETURN_PRE static void +usage(int status) ISC_PLATFORM_NORETURN_POST; + +static void +usage(int status) { + fprintf(stderr, "\ +Usage: %s [-b address] [-c config] [-s server] [-p port]\n\ + [-k key-file ] [-y key] [-r] [-V] [-4 | -6] command\n\ +\n\ +command is one of the following:\n\ +\n\ + addzone zone [class [view]] { zone-options }\n\ + Add zone to given view. Requires allow-new-zones option.\n\ + delzone [-clean] zone [class [view]]\n\ + Removes zone from given view.\n\ + dnssec -checkds [-key id [-alg algorithm]] [-when time] (published|withdrawn) zone [class [view]]\n\ + Mark the DS record for the KSK of the given zone as seen\n\ + in the parent. If the zone has multiple KSKs, select a\n\ + specific key by providing the keytag with -key id and\n\ + optionally the key's algorithm with -alg algorithm.\n\ + Requires the zone to have a dnssec-policy.\n\ + dnssec -rollover -key id [-alg algorithm] [-when time] zone [class [view]]\n\ + Rollover key with id of the given zone. Requires the zone\n\ + to have a dnssec-policy.\n\ + dnssec -status zone [class [view]]\n\ + Show the DNSSEC signing state for the specified zone.\n\ + Requires the zone to have a dnssec-policy.\n\ + dnstap -reopen\n\ + Close, truncate and re-open the DNSTAP output file.\n\ + dnstap -roll [count]\n\ + Close, rename and re-open the DNSTAP output file(s).\n\ + dumpdb [-all|-cache|-zones|-adb|-bad|-expired|-fail] [view ...]\n\ + Dump cache(s) to the dump file (named_dump.db).\n\ + flush Flushes all of the server's caches.\n\ + flush [view] Flushes the server's cache for a view.\n\ + flushname name [view]\n\ + Flush the given name from the server's cache(s)\n\ + flushtree name [view]\n\ + Flush all names under the given name from the server's cache(s)\n\ + freeze Suspend updates to all dynamic zones.\n\ + freeze zone [class [view]]\n\ + Suspend updates to a dynamic zone.\n\ + halt Stop the server without saving pending updates.\n\ + halt -p Stop the server without saving pending updates reporting\n\ + process id.\n\ + loadkeys zone [class [view]]\n\ + Update keys without signing immediately.\n\ + managed-keys refresh [class [view]]\n\ + Check trust anchor for RFC 5011 key changes\n\ + managed-keys status [class [view]]\n\ + Display RFC 5011 managed keys information\n\ + managed-keys sync [class [view]]\n\ + Write RFC 5011 managed keys to disk\n\ + modzone zone [class [view]] { zone-options }\n\ + Modify a zone's configuration.\n\ + Requires allow-new-zones option.\n\ + notify zone [class [view]]\n\ + Resend NOTIFY messages for the zone.\n\ + notrace Set debugging level to 0.\n\ + nta -dump\n\ + List all negative trust anchors.\n\ + nta [-lifetime duration] [-force] domain [view]\n\ + Set a negative trust anchor, disabling DNSSEC validation\n\ + for the given domain.\n\ + Using -lifetime specifies the duration of the NTA, up\n\ + to one week.\n\ + Using -force prevents the NTA from expiring before its\n\ + full lifetime, even if the domain can validate sooner.\n\ + nta -remove domain [view]\n\ + Remove a negative trust anchor, re-enabling validation\n\ + for the given domain.\n\ + querylog [ on | off ]\n\ + Enable / disable query logging.\n\ + reconfig Reload configuration file and new zones only.\n\ + recursing Dump the queries that are currently recursing (named.recursing)\n\ + refresh zone [class [view]]\n\ + Schedule immediate maintenance for a zone.\n\ + reload Reload configuration file and zones.\n\ + reload zone [class [view]]\n\ + Reload a single zone.\n\ + retransfer zone [class [view]]\n\ + Retransfer a single zone without checking serial number.\n\ + scan Scan available network interfaces for changes.\n\ + secroots [view ...]\n\ + Write security roots to the secroots file.\n\ + serve-stale [ on | off | reset | status ] [class [view]]\n\ + Control whether stale answers are returned\n\ + showzone zone [class [view]]\n\ + Print a zone's configuration.\n\ + sign zone [class [view]]\n\ + Update zone keys, and sign as needed.\n\ + signing -clear all zone [class [view]]\n\ + Remove the private records for all keys that have\n\ + finished signing the given zone.\n\ + signing -clear <keyid>/<algorithm> zone [class [view]]\n\ + Remove the private record that indicating the given key\n\ + has finished signing the given zone.\n\ + signing -list zone [class [view]]\n\ + List the private records showing the state of DNSSEC\n\ + signing in the given zone.\n\ + signing -nsec3param hash flags iterations salt zone [class [view]]\n\ + Add NSEC3 chain to zone if already signed.\n\ + Prime zone with NSEC3 chain if not yet signed.\n\ + signing -nsec3param none zone [class [view]]\n\ + Remove NSEC3 chains from zone.\n\ + signing -serial <value> zone [class [view]]\n\ + Set the zones's serial to <value>.\n\ + stats Write server statistics to the statistics file.\n\ + status Display status of the server.\n\ + stop Save pending updates to master files and stop the server.\n\ + stop -p Save pending updates to master files and stop the server\n\ + reporting process id.\n\ + sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\ + remove their journal files.\n\ + sync [-clean] zone [class [view]]\n\ + Dump a single zone's changes to disk, and optionally\n\ + remove its journal file.\n\ + tcp-timeouts Display the tcp-*-timeout option values\n\ + tcp-timeouts initial idle keepalive advertised\n\ + Update the tcp-*-timeout option values\n\ + thaw Enable updates to all dynamic zones and reload them.\n\ + thaw zone [class [view]]\n\ + Enable updates to a frozen dynamic zone and reload it.\n\ + trace Increment debugging level by one.\n\ + trace level Change the debugging level.\n\ + tsig-delete keyname [view]\n\ + Delete a TKEY-negotiated TSIG key.\n\ + tsig-list List all currently active TSIG keys, including both statically\n\ + configured and TKEY-negotiated keys.\n\ + validation [ on | off | status ] [view]\n\ + Enable / disable DNSSEC validation.\n\ + zonestatus zone [class [view]]\n\ + Display the current status of a zone.\n\ +\n\ +Version: %s\n", + progname, version); + + exit(status); +} + +#define CMDLINE_FLAGS "46b:c:hk:Mmp:qrs:Vy:" + +static void +preparse_args(int argc, char **argv) { + bool ipv4only = false, ipv6only = false; + int ch; + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '4': + if (ipv6only) { + fatal("only one of -4 and -6 allowed"); + } + ipv4only = true; + break; + case '6': + if (ipv4only) { + fatal("only one of -4 and -6 allowed"); + } + ipv6only = true; + break; + default: + break; + } + } + + isc_commandline_reset = true; + isc_commandline_index = 1; +} + +static void +get_addresses(const char *host, in_port_t port) { + isc_result_t result; + int found = 0, count; + + REQUIRE(host != NULL); + + if (*host == '/') { + result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs], + host); + if (result == ISC_R_SUCCESS) { + nserveraddrs++; + } + } else { + count = SERVERADDRS - nserveraddrs; + result = bind9_getaddresses( + host, port, &serveraddrs[nserveraddrs], count, &found); + nserveraddrs += found; + } + if (result != ISC_R_SUCCESS) { + fatal("couldn't get address for '%s': %s", host, + isc_result_totext(result)); + } + INSIST(nserveraddrs > 0); +} + +static void +rndc_senddone(isc_task_t *task, isc_event_t *event) { + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + + if (sevent->result != ISC_R_SUCCESS) { + fatal("send failed: %s", isc_result_totext(sevent->result)); + } + isc_event_free(&event); + if (atomic_fetch_sub_release(&sends, 1) == 1 && + atomic_load_acquire(&recvs) == 0) + { + isc_socket_detach(&sock); + isc_task_detach(&task); + isc_app_shutdown(); + } +} + +static void +rndc_recvdone(isc_task_t *task, isc_event_t *event) { + isccc_sexpr_t *response = NULL; + isccc_sexpr_t *data; + isccc_region_t source; + char *errormsg = NULL; + char *textmsg = NULL; + isc_result_t result; + + atomic_fetch_sub_release(&recvs, 1); + + if (ccmsg.result == ISC_R_EOF) { + fatal("connection to remote host closed\n" + "This may indicate that\n" + "* the remote server is using an older version of" + " the command protocol,\n" + "* this host is not authorized to connect,\n" + "* the clocks are not synchronized, or\n" + "* the key is invalid."); + } + + if (ccmsg.result != ISC_R_SUCCESS) { + fatal("recv failed: %s", isc_result_totext(ccmsg.result)); + } + + source.rstart = isc_buffer_base(&ccmsg.buffer); + source.rend = isc_buffer_used(&ccmsg.buffer); + + DO("parse message", + isccc_cc_fromwire(&source, &response, algorithm, &secret)); + + data = isccc_alist_lookup(response, "_data"); + if (!isccc_alist_alistp(data)) { + fatal("bad or missing data section in response"); + } + result = isccc_cc_lookupstring(data, "err", &errormsg); + if (result == ISC_R_SUCCESS) { + failed = true; + fprintf(stderr, "%s: '%s' failed: %s\n", progname, command, + errormsg); + } else if (result != ISC_R_NOTFOUND) { + fprintf(stderr, "%s: parsing response failed: %s\n", progname, + isc_result_totext(result)); + } + + result = isccc_cc_lookupstring(data, "text", &textmsg); + if (result == ISC_R_SUCCESS) { + if ((!quiet || failed) && strlen(textmsg) != 0U) { + fprintf(failed ? stderr : stdout, "%s\n", textmsg); + } + } else if (result != ISC_R_NOTFOUND) { + fprintf(stderr, "%s: parsing response failed: %s\n", progname, + isc_result_totext(result)); + } + + if (showresult) { + isc_result_t eresult; + + result = isccc_cc_lookupuint32(data, "result", &eresult); + if (result == ISC_R_SUCCESS) { + printf("%s %u\n", isc_result_toid(eresult), eresult); + } else { + printf("NONE -1\n"); + } + } + + isc_event_free(&event); + isccc_sexpr_free(&response); + if (atomic_load_acquire(&sends) == 0 && + atomic_load_acquire(&recvs) == 0) + { + isc_socket_detach(&sock); + isc_task_detach(&task); + isc_app_shutdown(); + } +} + +static void +rndc_recvnonce(isc_task_t *task, isc_event_t *event) { + isccc_sexpr_t *response = NULL; + isccc_sexpr_t *_ctrl; + isccc_region_t source; + isc_result_t result; + uint32_t nonce; + isccc_sexpr_t *request = NULL; + isccc_time_t now; + isc_region_t r; + isccc_sexpr_t *data; + isc_buffer_t b; + + atomic_fetch_sub_release(&recvs, 1); + + if (ccmsg.result == ISC_R_EOF) { + fatal("connection to remote host closed\n" + "This may indicate that\n" + "* the remote server is using an older version of" + " the command protocol,\n" + "* this host is not authorized to connect,\n" + "* the clocks are not synchronized,\n" + "* the key signing algorithm is incorrect, or\n" + "* the key is invalid."); + } + + if (ccmsg.result != ISC_R_SUCCESS) { + fatal("recv failed: %s", isc_result_totext(ccmsg.result)); + } + + source.rstart = isc_buffer_base(&ccmsg.buffer); + source.rend = isc_buffer_used(&ccmsg.buffer); + + DO("parse message", + isccc_cc_fromwire(&source, &response, algorithm, &secret)); + + _ctrl = isccc_alist_lookup(response, "_ctrl"); + if (!isccc_alist_alistp(_ctrl)) { + fatal("bad or missing ctrl section in response"); + } + nonce = 0; + if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS) { + nonce = 0; + } + + isc_stdtime_get(&now); + + DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, + now, now + 60, &request)); + data = isccc_alist_lookup(request, "_data"); + if (data == NULL) { + fatal("_data section missing"); + } + if (isccc_cc_definestring(data, "type", args) == NULL) { + fatal("out of memory"); + } + if (nonce != 0) { + _ctrl = isccc_alist_lookup(request, "_ctrl"); + if (_ctrl == NULL) { + fatal("_ctrl section missing"); + } + if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL) { + fatal("out of memory"); + } + } + + isc_buffer_clear(databuf); + /* Skip the length field (4 bytes) */ + isc_buffer_add(databuf, 4); + + DO("render message", + isccc_cc_towire(request, &databuf, algorithm, &secret)); + + isc_buffer_init(&b, databuf->base, 4); + isc_buffer_putuint32(&b, databuf->used - 4); + + r.base = databuf->base; + r.length = databuf->used; + + isccc_ccmsg_cancelread(&ccmsg); + DO("schedule recv", + isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvdone, NULL)); + atomic_fetch_add_relaxed(&recvs, 1); + DO("send message", + isc_socket_send(sock, &r, task, rndc_senddone, NULL)); + atomic_fetch_add_relaxed(&sends, 1); + + isc_event_free(&event); + isccc_sexpr_free(&response); + isccc_sexpr_free(&request); + return; +} + +static void +rndc_connected(isc_task_t *task, isc_event_t *event) { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + isccc_sexpr_t *request = NULL; + isccc_sexpr_t *data; + isccc_time_t now; + isc_region_t r; + isc_buffer_t b; + isc_result_t result; + + atomic_fetch_sub_release(&connects, 1); + + if (sevent->result != ISC_R_SUCCESS) { + isc_sockaddr_format(&serveraddrs[currentaddr], socktext, + sizeof(socktext)); + if (sevent->result != ISC_R_CANCELED && + ++currentaddr < nserveraddrs) + { + notify("connection failed: %s: %s", socktext, + isc_result_totext(sevent->result)); + isc_socket_detach(&sock); + isc_event_free(&event); + rndc_startconnect(&serveraddrs[currentaddr], task); + return; + } else { + fatal("connect failed: %s: %s", socktext, + isc_result_totext(sevent->result)); + } + } + + isc_stdtime_get(&now); + DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial, + now, now + 60, &request)); + data = isccc_alist_lookup(request, "_data"); + if (data == NULL) { + fatal("_data section missing"); + } + if (isccc_cc_definestring(data, "type", "null") == NULL) { + fatal("out of memory"); + } + + isc_buffer_clear(databuf); + /* Skip the length field (4 bytes) */ + isc_buffer_add(databuf, 4); + + DO("render message", + isccc_cc_towire(request, &databuf, algorithm, &secret)); + + isc_buffer_init(&b, databuf->base, 4); + isc_buffer_putuint32(&b, databuf->used - 4); + + r.base = databuf->base; + r.length = databuf->used; + + isccc_ccmsg_init(rndc_mctx, sock, &ccmsg); + isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024); + + DO("schedule recv", + isccc_ccmsg_readmessage(&ccmsg, task, rndc_recvnonce, NULL)); + atomic_fetch_add_relaxed(&recvs, 1); + DO("send message", + isc_socket_send(sock, &r, task, rndc_senddone, NULL)); + atomic_fetch_add_relaxed(&sends, 1); + isc_event_free(&event); + isccc_sexpr_free(&request); +} + +static void +rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) { + isc_result_t result; + int pf; + isc_sockettype_t type; + + char socktext[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(addr, socktext, sizeof(socktext)); + + notify("using server %s (%s)", servername, socktext); + + pf = isc_sockaddr_pf(addr); + if (pf == AF_INET || pf == AF_INET6) { + type = isc_sockettype_tcp; + } else { + type = isc_sockettype_unix; + } + DO("create socket", isc_socket_create(socketmgr, pf, type, &sock)); + switch (isc_sockaddr_pf(addr)) { + case AF_INET: + DO("bind socket", isc_socket_bind(sock, &local4, 0)); + break; + case AF_INET6: + DO("bind socket", isc_socket_bind(sock, &local6, 0)); + break; + default: + break; + } + DO("connect", + isc_socket_connect(sock, addr, task, rndc_connected, NULL)); + atomic_fetch_add_relaxed(&connects, 1); +} + +static void +rndc_start(isc_task_t *task, isc_event_t *event) { + isc_event_free(&event); + + currentaddr = 0; + rndc_startconnect(&serveraddrs[currentaddr], task); +} + +static void +parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, + cfg_parser_t **pctxp, cfg_obj_t **configp) { + isc_result_t result; + const char *conffile = admin_conffile; + const cfg_obj_t *addresses = NULL; + const cfg_obj_t *defkey = NULL; + const cfg_obj_t *options = NULL; + const cfg_obj_t *servers = NULL; + const cfg_obj_t *server = NULL; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key = NULL; + const cfg_obj_t *defport = NULL; + const cfg_obj_t *secretobj = NULL; + const cfg_obj_t *algorithmobj = NULL; + cfg_obj_t *config = NULL; + const cfg_obj_t *address = NULL; + const cfg_listelt_t *elt; + const char *secretstr; + const char *algorithmstr; + static char secretarray[1024]; + const cfg_type_t *conftype = &cfg_type_rndcconf; + bool key_only = false; + const cfg_listelt_t *element; + + if (!isc_file_exists(conffile)) { + conffile = admin_keyfile; + conftype = &cfg_type_rndckey; + + if (c_flag) { + fatal("%s does not exist", admin_conffile); + } + + if (!isc_file_exists(conffile)) { + fatal("neither %s nor %s was found", admin_conffile, + admin_keyfile); + } + key_only = true; + } else if (!c_flag && isc_file_exists(admin_keyfile)) { + fprintf(stderr, + "WARNING: key file (%s) exists, but using " + "default configuration file (%s)\n", + admin_keyfile, admin_conffile); + } + + DO("create parser", cfg_parser_create(mctx, log, pctxp)); + + /* + * The parser will output its own errors, so DO() is not used. + */ + result = cfg_parse_file(*pctxp, conffile, conftype, &config); + if (result != ISC_R_SUCCESS) { + fatal("could not load rndc configuration"); + } + + if (!key_only) { + (void)cfg_map_get(config, "options", &options); + } + + if (key_only && servername == NULL) { + servername = "127.0.0.1"; + } else if (servername == NULL && options != NULL) { + const cfg_obj_t *defserverobj = NULL; + (void)cfg_map_get(options, "default-server", &defserverobj); + if (defserverobj != NULL) { + servername = cfg_obj_asstring(defserverobj); + } + } + + if (servername == NULL) { + fatal("no server specified and no default"); + } + + if (!key_only) { + (void)cfg_map_get(config, "server", &servers); + if (servers != NULL) { + for (elt = cfg_list_first(servers); elt != NULL; + elt = cfg_list_next(elt)) + { + const char *name; + server = cfg_listelt_value(elt); + name = cfg_obj_asstring( + cfg_map_getname(server)); + if (strcasecmp(name, servername) == 0) { + break; + } + server = NULL; + } + } + } + + /* + * Look for the name of the key to use. + */ + if (keyname != NULL) { + /* Was set on command line, do nothing. */ + } else if (server != NULL) { + DO("get key for server", cfg_map_get(server, "key", &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (options != NULL) { + DO("get default key", + cfg_map_get(options, "default-key", &defkey)); + keyname = cfg_obj_asstring(defkey); + } else if (!key_only) { + fatal("no key for server and no default"); + } + + /* + * Get the key's definition. + */ + if (key_only) { + DO("get key", cfg_map_get(config, "key", &key)); + } else { + DO("get config key list", cfg_map_get(config, "key", &keys)); + for (elt = cfg_list_first(keys); elt != NULL; + elt = cfg_list_next(elt)) + { + key = cfg_listelt_value(elt); + if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), + keyname) == 0) + { + break; + } + } + if (elt == NULL) { + fatal("no key definition for name %s", keyname); + } + } + (void)cfg_map_get(key, "secret", &secretobj); + (void)cfg_map_get(key, "algorithm", &algorithmobj); + if (secretobj == NULL || algorithmobj == NULL) { + fatal("key must have algorithm and secret"); + } + + secretstr = cfg_obj_asstring(secretobj); + algorithmstr = cfg_obj_asstring(algorithmobj); + + if (strcasecmp(algorithmstr, "hmac-md5") == 0) { + algorithm = ISCCC_ALG_HMACMD5; + } else if (strcasecmp(algorithmstr, "hmac-sha1") == 0) { + algorithm = ISCCC_ALG_HMACSHA1; + } else if (strcasecmp(algorithmstr, "hmac-sha224") == 0) { + algorithm = ISCCC_ALG_HMACSHA224; + } else if (strcasecmp(algorithmstr, "hmac-sha256") == 0) { + algorithm = ISCCC_ALG_HMACSHA256; + } else if (strcasecmp(algorithmstr, "hmac-sha384") == 0) { + algorithm = ISCCC_ALG_HMACSHA384; + } else if (strcasecmp(algorithmstr, "hmac-sha512") == 0) { + algorithm = ISCCC_ALG_HMACSHA512; + } else { + fatal("unsupported algorithm: %s", algorithmstr); + } + + secret.rstart = (unsigned char *)secretarray; + secret.rend = (unsigned char *)secretarray + sizeof(secretarray); + DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); + secret.rend = secret.rstart; + secret.rstart = (unsigned char *)secretarray; + + /* + * Find the port to connect to. + */ + if (remoteport != 0) { + /* Was set on command line, do nothing. */ + } else { + if (server != NULL) { + (void)cfg_map_get(server, "port", &defport); + } + if (defport == NULL && options != NULL) { + (void)cfg_map_get(options, "default-port", &defport); + } + } + if (defport != NULL) { + remoteport = cfg_obj_asuint32(defport); + if (remoteport > 65535 || remoteport == 0) { + fatal("port %u out of range", remoteport); + } + } else if (remoteport == 0) { + remoteport = NS_CONTROL_PORT; + } + + if (server != NULL) { + result = cfg_map_get(server, "addresses", &addresses); + } else { + result = ISC_R_NOTFOUND; + } + if (result == ISC_R_SUCCESS) { + for (element = cfg_list_first(addresses); element != NULL; + element = cfg_list_next(element)) + { + isc_sockaddr_t sa; + + address = cfg_listelt_value(element); + if (!cfg_obj_issockaddr(address)) { + unsigned int myport; + const char *name; + const cfg_obj_t *obj; + + obj = cfg_tuple_get(address, "name"); + name = cfg_obj_asstring(obj); + obj = cfg_tuple_get(address, "port"); + if (cfg_obj_isuint32(obj)) { + myport = cfg_obj_asuint32(obj); + if (myport > UINT16_MAX || myport == 0) + { + fatal("port %u out of range", + myport); + } + } else { + myport = remoteport; + } + if (nserveraddrs < SERVERADDRS) { + get_addresses(name, (in_port_t)myport); + } else { + fprintf(stderr, + "too many address: " + "%s: dropped\n", + name); + } + continue; + } + sa = *cfg_obj_assockaddr(address); + if (isc_sockaddr_getport(&sa) == 0) { + isc_sockaddr_setport(&sa, remoteport); + } + if (nserveraddrs < SERVERADDRS) { + serveraddrs[nserveraddrs++] = sa; + } else { + char socktext[ISC_SOCKADDR_FORMATSIZE]; + + isc_sockaddr_format(&sa, socktext, + sizeof(socktext)); + fprintf(stderr, + "too many address: %s: dropped\n", + socktext); + } + } + } + + if (!local4set && server != NULL) { + address = NULL; + cfg_map_get(server, "source-address", &address); + if (address != NULL) { + local4 = *cfg_obj_assockaddr(address); + local4set = true; + } + } + if (!local4set && options != NULL) { + address = NULL; + cfg_map_get(options, "default-source-address", &address); + if (address != NULL) { + local4 = *cfg_obj_assockaddr(address); + local4set = true; + } + } + + if (!local6set && server != NULL) { + address = NULL; + cfg_map_get(server, "source-address-v6", &address); + if (address != NULL) { + local6 = *cfg_obj_assockaddr(address); + local6set = true; + } + } + if (!local6set && options != NULL) { + address = NULL; + cfg_map_get(options, "default-source-address-v6", &address); + if (address != NULL) { + local6 = *cfg_obj_assockaddr(address); + local6set = true; + } + } + + *configp = config; +} + +int +main(int argc, char **argv) { + isc_result_t result = ISC_R_SUCCESS; + bool show_final_mem = false; + isc_nm_t *netmgr = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_task_t *task = NULL; + isc_log_t *log = NULL; + isc_logconfig_t *logconfig = NULL; + isc_logdestination_t logdest; + cfg_parser_t *pctx = NULL; + cfg_obj_t *config = NULL; + const char *keyname = NULL; + struct in_addr in; + struct in6_addr in6; + char *p; + size_t argslen; + int ch; + int i; + + result = isc_file_progname(*argv, program, sizeof(program)); + if (result != ISC_R_SUCCESS) { + memmove(program, "rndc", 5); + } + progname = program; + + admin_conffile = RNDC_CONFFILE; + admin_keyfile = RNDC_KEYFILE; + + isc_sockaddr_any(&local4); + isc_sockaddr_any6(&local6); + + result = isc_app_start(); + if (result != ISC_R_SUCCESS) { + fatal("isc_app_start() failed: %s", isc_result_totext(result)); + } + + isc_commandline_errprint = false; + + preparse_args(argc, argv); + + while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { + switch (ch) { + case '4': + if (isc_net_probeipv4() != ISC_R_SUCCESS) { + fatal("can't find IPv4 networking"); + } + isc_net_disableipv6(); + break; + case '6': + if (isc_net_probeipv6() != ISC_R_SUCCESS) { + fatal("can't find IPv6 networking"); + } + isc_net_disableipv4(); + break; + case 'b': + if (inet_pton(AF_INET, isc_commandline_argument, &in) == + 1) + { + isc_sockaddr_fromin(&local4, &in, 0); + local4set = true; + } else if (inet_pton(AF_INET6, isc_commandline_argument, + &in6) == 1) + { + isc_sockaddr_fromin6(&local6, &in6, 0); + local6set = true; + } + break; + + case 'c': + admin_conffile = isc_commandline_argument; + c_flag = true; + break; + + case 'k': + admin_keyfile = isc_commandline_argument; + break; + + case 'M': + isc_mem_debugging = ISC_MEM_DEBUGTRACE; + break; + + case 'm': + show_final_mem = true; + break; + + case 'p': + remoteport = atoi(isc_commandline_argument); + if (remoteport > 65535 || remoteport == 0) { + fatal("port '%s' out of range", + isc_commandline_argument); + } + break; + + case 'q': + quiet = true; + break; + + case 'r': + showresult = true; + break; + + case 's': + servername = isc_commandline_argument; + break; + + case 'V': + verbose = true; + break; + + case 'y': + keyname = isc_commandline_argument; + break; + + case '?': + if (isc_commandline_option != '?') { + fprintf(stderr, "%s: invalid argument -%c\n", + program, isc_commandline_option); + usage(1); + } + FALLTHROUGH; + case 'h': + usage(0); + break; + default: + fprintf(stderr, "%s: unhandled option -%c\n", program, + isc_commandline_option); + exit(1); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + + if (argc < 1) { + usage(1); + } + + serial = isc_random32(); + + isc_mem_create(&rndc_mctx); + DO("create socket manager", + isc_socketmgr_create(rndc_mctx, &socketmgr)); + DO("create task manager", + isc_managers_create(rndc_mctx, 1, 0, &netmgr, &taskmgr)); + DO("create task", isc_task_create(taskmgr, 0, &task)); + + isc_log_create(rndc_mctx, &log, &logconfig); + isc_log_setcontext(log); + isc_log_settag(logconfig, progname); + logdest.file.stream = stderr; + logdest.file.name = NULL; + logdest.file.versions = ISC_LOG_ROLLNEVER; + logdest.file.maximum_size = 0; + isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, + ISC_LOG_INFO, &logdest, + ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL); + DO("enabling log channel", + isc_log_usechannel(logconfig, "stderr", NULL, NULL)); + + parse_config(rndc_mctx, log, keyname, &pctx, &config); + + isccc_result_register(); + + command = *argv; + + isc_buffer_allocate(rndc_mctx, &databuf, 2048); + + /* + * Convert argc/argv into a space-delimited command string + * similar to what the user might enter in interactive mode + * (if that were implemented). + */ + argslen = 0; + for (i = 0; i < argc; i++) { + argslen += strlen(argv[i]) + 1; + } + + args = isc_mem_get(rndc_mctx, argslen); + + p = args; + for (i = 0; i < argc; i++) { + size_t len = strlen(argv[i]); + memmove(p, argv[i], len); + p += len; + *p++ = ' '; + } + + p--; + *p++ = '\0'; + INSIST(p == args + argslen); + + notify("%s", command); + + if (strcmp(command, "restart") == 0) { + fatal("'%s' is not implemented", command); + } + + if (nserveraddrs == 0 && servername != NULL) { + get_addresses(servername, (in_port_t)remoteport); + } + + isc_task_attach(task, &(isc_task_t *){ NULL }); + DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL)); + + result = isc_app_run(); + if (result != ISC_R_SUCCESS) { + fatal("isc_app_run() failed: %s", isc_result_totext(result)); + } + + if (atomic_load_acquire(&connects) > 0 || + atomic_load_acquire(&sends) > 0 || atomic_load_acquire(&recvs) > 0) + { + isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); + } + + isc_task_detach(&task); + isc_managers_destroy(&netmgr, &taskmgr); + isc_socketmgr_destroy(&socketmgr); + isc_log_destroy(&log); + isc_log_setcontext(NULL); + + cfg_obj_destroy(pctx, &config); + cfg_parser_destroy(&pctx); + + isc_mem_put(rndc_mctx, args, argslen); + isccc_ccmsg_invalidate(&ccmsg); + + isc_buffer_free(&databuf); + + if (show_final_mem) { + isc_mem_stats(rndc_mctx, stderr); + } + + isc_mem_destroy(&rndc_mctx); + + if (failed) { + return (1); + } + + return (0); +} diff --git a/bin/rndc/rndc.conf b/bin/rndc/rndc.conf new file mode 100644 index 0000000..78ee858 --- /dev/null +++ b/bin/rndc/rndc.conf @@ -0,0 +1,41 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Sample rndc configuration file. + */ + +options { + default-server localhost; + default-key "key"; +}; + +server localhost { + key "key"; +}; + +key "cc64b3d1db63fc88d7cb5d2f9f57d258" { + algorithm hmac-sha256; + secret "34f88008d07deabbe65bd01f1d233d47"; +}; + +server "test1" { + key "cc64b3d1db63fc88d7cb5d2f9f57d258"; + port 5353; + addresses { 10.53.0.1; }; +}; + +key "key" { + algorithm hmac-sha256; + secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K"; +}; diff --git a/bin/rndc/rndc.conf.rst b/bin/rndc/rndc.conf.rst new file mode 100644 index 0000000..b02e780 --- /dev/null +++ b/bin/rndc/rndc.conf.rst @@ -0,0 +1,156 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. _man_rndc.conf: + +rndc.conf - rndc configuration file +----------------------------------- + +Synopsis +~~~~~~~~ + +:program:`rndc.conf` + +Description +~~~~~~~~~~~ + +``rndc.conf`` is the configuration file for ``rndc``, the BIND 9 name +server control utility. This file has a similar structure and syntax to +``named.conf``. Statements are enclosed in braces and terminated with a +semi-colon. Clauses in the statements are also semi-colon terminated. +The usual comment styles are supported: + +C style: /\* \*/ + +C++ style: // to end of line + +Unix style: # to end of line + +``rndc.conf`` is much simpler than ``named.conf``. The file uses three +statements: an options statement, a server statement, and a key +statement. + +The ``options`` statement contains five clauses. The ``default-server`` +clause is followed by the name or address of a name server. This host +is used when no name server is given as an argument to ``rndc``. +The ``default-key`` clause is followed by the name of a key, which is +identified by a ``key`` statement. If no ``keyid`` is provided on the +rndc command line, and no ``key`` clause is found in a matching +``server`` statement, this default key is used to authenticate the +server's commands and responses. The ``default-port`` clause is followed +by the port to connect to on the remote name server. If no ``port`` +option is provided on the rndc command line, and no ``port`` clause is +found in a matching ``server`` statement, this default port is used +to connect. The ``default-source-address`` and +``default-source-address-v6`` clauses can be used to set the IPv4 +and IPv6 source addresses respectively. + +After the ``server`` keyword, the server statement includes a string +which is the hostname or address for a name server. The statement has +three possible clauses: ``key``, ``port``, and ``addresses``. The key +name must match the name of a key statement in the file. The port number +specifies the port to connect to. If an ``addresses`` clause is supplied, +these addresses are used instead of the server name. Each address +can take an optional port. If an ``source-address`` or +``source-address-v6`` is supplied, it is used to specify the +IPv4 and IPv6 source address, respectively. + +The ``key`` statement begins with an identifying string, the name of the +key. The statement has two clauses. ``algorithm`` identifies the +authentication algorithm for ``rndc`` to use; currently only HMAC-MD5 +(for compatibility), HMAC-SHA1, HMAC-SHA224, HMAC-SHA256 (default), +HMAC-SHA384, and HMAC-SHA512 are supported. This is followed by a secret +clause which contains the base-64 encoding of the algorithm's +authentication key. The base-64 string is enclosed in double quotes. + +There are two common ways to generate the base-64 string for the secret. +The BIND 9 program ``rndc-confgen`` can be used to generate a random +key, or the ``mmencode`` program, also known as ``mimencode``, can be +used to generate a base-64 string from known input. ``mmencode`` does +not ship with BIND 9 but is available on many systems. See the Example +section for sample command lines for each. + +Example +~~~~~~~ + +:: + + options { + default-server localhost; + default-key samplekey; + }; + +:: + + server localhost { + key samplekey; + }; + +:: + + server testserver { + key testkey; + addresses { localhost port 5353; }; + }; + +:: + + key samplekey { + algorithm hmac-sha256; + secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz"; + }; + +:: + + key testkey { + algorithm hmac-sha256; + secret "R3HI8P6BKw9ZwXwN3VZKuQ=="; + }; + + +In the above example, ``rndc`` by default uses the server at +localhost (127.0.0.1) and the key called "samplekey". Commands to the +localhost server use the "samplekey" key, which must also be defined +in the server's configuration file with the same name and secret. The +key statement indicates that "samplekey" uses the HMAC-SHA256 algorithm +and its secret clause contains the base-64 encoding of the HMAC-SHA256 +secret enclosed in double quotes. + +If ``rndc -s testserver`` is used, then ``rndc`` connects to the server +on localhost port 5353 using the key "testkey". + +To generate a random secret with ``rndc-confgen``: + +``rndc-confgen`` + +A complete ``rndc.conf`` file, including the randomly generated key, +is written to the standard output. Commented-out ``key`` and +``controls`` statements for ``named.conf`` are also printed. + +To generate a base-64 secret with ``mmencode``: + +``echo "known plaintext for a secret" | mmencode`` + +Name Server Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The name server must be configured to accept rndc connections and to +recognize the key specified in the ``rndc.conf`` file, using the +controls statement in ``named.conf``. See the sections on the +``controls`` statement in the BIND 9 Administrator Reference Manual for +details. + +See Also +~~~~~~~~ + +:manpage:`rndc(8)`, :manpage:`rndc-confgen(8)`, :manpage:`mmencode(1)`, BIND 9 Administrator Reference Manual. diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst new file mode 100644 index 0000000..b2ec0e8 --- /dev/null +++ b/bin/rndc/rndc.rst @@ -0,0 +1,608 @@ +.. Copyright (C) Internet Systems Consortium, Inc. ("ISC") +.. +.. SPDX-License-Identifier: MPL-2.0 +.. +.. This Source Code Form is subject to the terms of the Mozilla Public +.. License, v. 2.0. If a copy of the MPL was not distributed with this +.. file, you can obtain one at https://mozilla.org/MPL/2.0/. +.. +.. See the COPYRIGHT file distributed with this work for additional +.. information regarding copyright ownership. + +.. highlight: console + +.. _man_rndc: + +rndc - name server control utility +---------------------------------- + +Synopsis +~~~~~~~~ + +:program:`rndc` [**-b** source-address] [**-c** config-file] [**-k** key-file] [**-s** server] [**-p** port] [**-q**] [**-r**] [**-V**] [**-y** key_id] [[**-4**] | [**-6**]] {command} + +Description +~~~~~~~~~~~ + +``rndc`` controls the operation of a name server; it supersedes the +``ndc`` utility. If ``rndc`` is +invoked with no command line options or arguments, it prints a short +summary of the supported commands and the available options and their +arguments. + +``rndc`` communicates with the name server over a TCP connection, +sending commands authenticated with digital signatures. In the current +versions of ``rndc`` and ``named``, the only supported authentication +algorithms are HMAC-MD5 (for compatibility), HMAC-SHA1, HMAC-SHA224, +HMAC-SHA256 (default), HMAC-SHA384, and HMAC-SHA512. They use a shared +secret on each end of the connection, which provides TSIG-style +authentication for the command request and the name server's response. +All commands sent over the channel must be signed by a key_id known to +the server. + +``rndc`` reads a configuration file to determine how to contact the name +server and decide what algorithm and key it should use. + +Options +~~~~~~~ + +``-4`` + This option indicates use of IPv4 only. + +``-6`` + This option indicates use of IPv6 only. + +``-b source-address`` + This option indicates ``source-address`` as the source address for the connection to the + server. Multiple instances are permitted, to allow setting of both the + IPv4 and IPv6 source addresses. + +``-c config-file`` + This option indicates ``config-file`` as the configuration file instead of the default, + ``/etc/rndc.conf``. + +``-k key-file`` + This option indicates ``key-file`` as the key file instead of the default, + ``/etc/rndc.key``. The key in ``/etc/rndc.key`` is used to + authenticate commands sent to the server if the config-file does not + exist. + +``-s server`` + ``server`` is the name or address of the server which matches a server + statement in the configuration file for ``rndc``. If no server is + supplied on the command line, the host named by the default-server + clause in the options statement of the ``rndc`` configuration file + is used. + +``-p port`` + This option instructs BIND 9 to send commands to TCP port ``port`` instead of its default control + channel port, 953. + +``-q`` + This option sets quiet mode, where message text returned by the server is not printed + unless there is an error. + +``-r`` + This option instructs ``rndc`` to print the result code returned by ``named`` + after executing the requested command (e.g., ISC_R_SUCCESS, + ISC_R_FAILURE, etc.). + +``-V`` + This option enables verbose logging. + +``-y key_id`` + This option indicates use of the key ``key_id`` from the configuration file. For control message validation to succeed, ``key_id`` must be known + by ``named`` with the same algorithm and secret string. If no ``key_id`` is specified, + ``rndc`` first looks for a key clause in the server statement of + the server being used, or if no server statement is present for that + host, then in the default-key clause of the options statement. Note that + the configuration file contains shared secrets which are used to send + authenticated control commands to name servers, and should therefore + not have general read or write access. + +Commands +~~~~~~~~ + +A list of commands supported by ``rndc`` can be seen by running ``rndc`` +without arguments. + +Currently supported commands are: + +``addzone`` *zone* [*class* [*view*]] *configuration* + This command adds a zone while the server is running. This command requires the + ``allow-new-zones`` option to be set to ``yes``. The configuration + string specified on the command line is the zone configuration text + that would ordinarily be placed in ``named.conf``. + + The configuration is saved in a file called ``viewname.nzf`` (or, if + ``named`` is compiled with liblmdb, an LMDB database file called + ``viewname.nzd``). ``viewname`` is the name of the view, unless the view + name contains characters that are incompatible with use as a file + name, in which case a cryptographic hash of the view name is used + instead. When ``named`` is restarted, the file is loaded into + the view configuration so that zones that were added can persist + after a restart. + + This sample ``addzone`` command adds the zone ``example.com`` to + the default view: + + ``rndc addzone example.com '{ type master; file "example.com.db"; };'`` + + (Note the brackets around and semi-colon after the zone configuration + text.) + + See also ``rndc delzone`` and ``rndc modzone``. + +``delzone`` [**-clean**] *zone* [*class* [*view*]] + This command deletes a zone while the server is running. + + If the ``-clean`` argument is specified, the zone's master file (and + journal file, if any) are deleted along with the zone. Without + the ``-clean`` option, zone files must be deleted manually. (If the + zone is of type ``secondary`` or ``stub``, the files needing to be removed + are reported in the output of the ``rndc delzone`` command.) + + If the zone was originally added via ``rndc addzone``, then it is + removed permanently. However, if it was originally configured in + ``named.conf``, then that original configuration remains in place; + when the server is restarted or reconfigured, the zone is + recreated. To remove it permanently, it must also be removed from + ``named.conf``. + + See also ``rndc addzone`` and ``rndc modzone``. + +``dnssec`` ( **-status** | **-rollover** **-key** id [**-alg** *algorithm*] [**-when** *time*] | **-checkds** [**-key** *id* [**-alg** *algorithm*]] [**-when** *time*] ( *published* | *withdrawn* )) *zone* [*class* [*view*]] + This command allows you to interact with the "dnssec-policy" of a given + zone. + + ``rndc dnssec -status`` show the DNSSEC signing state for the specified + zone. + + ``rndc dnssec -rollover`` allows you to schedule key rollover for a + specific key (overriding the original key lifetime). + + ``rndc dnssec -checkds`` informs :iscman:`named` that the DS for + a specified zone's key-signing key has been confirmed to be published + in, or withdrawn from, the parent zone. This is required in order to + complete a KSK rollover. The ``-key id`` and ``-alg algorithm`` arguments + can be used to specify a particular KSK, if necessary; if there is only + one key acting as a KSK for the zone, these arguments can be omitted. + The time of publication or withdrawal for the DS is set to the current + time by default, but can be overridden to a specific time with the + argument ``-when time``, where ``time`` is expressed in YYYYMMDDHHMMSS + notation. + +``dnstap`` ( **-reopen** | **-roll** [*number*] ) + This command closes and re-opens DNSTAP output files. + + ``rndc dnstap -reopen`` allows + the output file to be renamed externally, so that ``named`` can + truncate and re-open it. + + ``rndc dnstap -roll`` causes the output file + to be rolled automatically, similar to log files. The most recent + output file has ".0" appended to its name; the previous most recent + output file is moved to ".1", and so on. If ``number`` is specified, then + the number of backup log files is limited to that number. + +``dumpdb`` [**-all** | **-cache** | **-zones** | **-adb** | **-bad** | **-expired** | **-fail**] [*view ...*] + This command dumps the server's caches (default) and/or zones to the dump file for + the specified views. If no view is specified, all views are dumped. + (See the ``dump-file`` option in the BIND 9 Administrator Reference + Manual.) + +``flush`` + This command flushes the server's cache. + +``flushname`` *name* [*view*] + This command flushes the given name from the view's DNS cache and, if applicable, + from the view's nameserver address database, bad server cache, and + SERVFAIL cache. + +``flushtree`` *name* [*view*] + This command flushes the given name, and all of its subdomains, from the view's + DNS cache, address database, bad server cache, and SERVFAIL cache. + +``freeze`` [*zone* [*class* [*view*]]] + This command suspends updates to a dynamic zone. If no zone is specified, then all + zones are suspended. This allows manual edits to be made to a zone + normally updated by dynamic update, and causes changes in the + journal file to be synced into the master file. All dynamic update + attempts are refused while the zone is frozen. + + See also ``rndc thaw``. + +``halt`` [**-p**] + This command stops the server immediately. Recent changes made through dynamic + update or IXFR are not saved to the master files, but are rolled + forward from the journal files when the server is restarted. If + ``-p`` is specified, ``named``'s process ID is returned. This allows + an external process to determine when ``named`` has completed + halting. + + See also ``rndc stop``. + +``loadkeys`` [*zone* [*class* [*view*]]] + This command fetches all DNSSEC keys for the given zone from the key directory. If + they are within their publication period, they are merged into the + zone's DNSKEY RRset. Unlike ``rndc sign``, however, the zone is not + immediately re-signed by the new keys, but is allowed to + incrementally re-sign over time. + + This command requires that the zone be configured with a ``dnssec-policy``, or + that the ``auto-dnssec`` zone option be set to ``maintain``, and also requires the + zone to be configured to allow dynamic DNS. (See "Dynamic Update Policies" in + the Administrator Reference Manual for more details.) + +``managed-keys`` (*status* | *refresh* | *sync* | *destroy*) [*class* [*view*]] + This command inspects and controls the "managed-keys" database which handles + :rfc:`5011` DNSSEC trust anchor maintenance. If a view is specified, these + commands are applied to that view; otherwise, they are applied to all + views. + + - When run with the ``status`` keyword, this prints the current status of + the managed-keys database. + + - When run with the ``refresh`` keyword, this forces an immediate refresh + query to be sent for all the managed keys, updating the + managed-keys database if any new keys are found, without waiting + the normal refresh interval. + + - When run with the ``sync`` keyword, this forces an immediate dump of + the managed-keys database to disk (in the file + ``managed-keys.bind`` or (``viewname.mkeys``). This synchronizes + the database with its journal file, so that the database's current + contents can be inspected visually. + + - When run with the ``destroy`` keyword, the managed-keys database + is shut down and deleted, and all key maintenance is terminated. + This command should be used only with extreme caution. + + Existing keys that are already trusted are not deleted from + memory; DNSSEC validation can continue after this command is used. + However, key maintenance operations cease until ``named`` is + restarted or reconfigured, and all existing key maintenance states + are deleted. + + Running ``rndc reconfig`` or restarting ``named`` immediately + after this command causes key maintenance to be reinitialized + from scratch, just as if the server were being started for the + first time. This is primarily intended for testing, but it may + also be used, for example, to jumpstart the acquisition of new + keys in the event of a trust anchor rollover, or as a brute-force + repair for key maintenance problems. + +``modzone`` *zone* [*class* [*view*]] *configuration* + This command modifies the configuration of a zone while the server is running. This + command requires the ``allow-new-zones`` option to be set to ``yes``. + As with ``addzone``, the configuration string specified on the + command line is the zone configuration text that would ordinarily be + placed in ``named.conf``. + + If the zone was originally added via ``rndc addzone``, the + configuration changes are recorded permanently and are still + in effect after the server is restarted or reconfigured. However, if + it was originally configured in ``named.conf``, then that original + configuration remains in place; when the server is restarted or + reconfigured, the zone reverts to its original configuration. To + make the changes permanent, it must also be modified in + ``named.conf``. + + See also ``rndc addzone`` and ``rndc delzone``. + +``notify`` *zone* [*class* [*view*]] + This command resends NOTIFY messages for the zone. + +``notrace`` + This command sets the server's debugging level to 0. + + See also ``rndc trace``. + +``nta`` [( **-class** *class* | **-dump** | **-force** | **-remove** | **-lifetime** *duration*)] *domain* [*view*] + This command sets a DNSSEC negative trust anchor (NTA) for ``domain``, with a + lifetime of ``duration``. The default lifetime is configured in + ``named.conf`` via the ``nta-lifetime`` option, and defaults to one + hour. The lifetime cannot exceed one week. + + A negative trust anchor selectively disables DNSSEC validation for + zones that are known to be failing because of misconfiguration rather + than an attack. When data to be validated is at or below an active + NTA (and above any other configured trust anchors), ``named`` + aborts the DNSSEC validation process and treats the data as insecure + rather than bogus. This continues until the NTA's lifetime has + elapsed. + + NTAs persist across restarts of the ``named`` server. The NTAs for a + view are saved in a file called ``name.nta``, where ``name`` is the name + of the view; if it contains characters that are incompatible with + use as a file name, a cryptographic hash is generated from the name of + the view. + + An existing NTA can be removed by using the ``-remove`` option. + + An NTA's lifetime can be specified with the ``-lifetime`` option. + TTL-style suffixes can be used to specify the lifetime in seconds, + minutes, or hours. If the specified NTA already exists, its lifetime + is updated to the new value. Setting ``lifetime`` to zero is + equivalent to ``-remove``. + + If ``-dump`` is used, any other arguments are ignored and a list + of existing NTAs is printed. Note that this may include NTAs that are + expired but have not yet been cleaned up. + + Normally, ``named`` periodically tests to see whether data below + an NTA can now be validated (see the ``nta-recheck`` option in the + Administrator Reference Manual for details). If data can be + validated, then the NTA is regarded as no longer necessary and is + allowed to expire early. The ``-force`` parameter overrides this behavior + and forces an NTA to persist for its entire lifetime, regardless of + whether data could be validated if the NTA were not present. + + The view class can be specified with ``-class``. The default is class + ``IN``, which is the only class for which DNSSEC is currently + supported. + + All of these options can be shortened, i.e., to ``-l``, ``-r``, + ``-d``, ``-f``, and ``-c``. + + Unrecognized options are treated as errors. To refer to a domain or + view name that begins with a hyphen, use a double-hyphen (--) on the + command line to indicate the end of options. + +``querylog`` [(*on* | *off*)] + This command enables or disables query logging. For backward compatibility, this + command can also be used without an argument to toggle query logging + on and off. + + Query logging can also be enabled by explicitly directing the + ``queries`` ``category`` to a ``channel`` in the ``logging`` section + of ``named.conf``, or by specifying ``querylog yes;`` in the + ``options`` section of ``named.conf``. + +``reconfig`` + This command reloads the configuration file and loads new zones, but does not reload + existing zone files even if they have changed. This is faster than a + full ``reload`` when there is a large number of zones, because it + avoids the need to examine the modification times of the zone files. + +``recursing`` + This command dumps the list of queries ``named`` is currently + recursing on, and the list of domains to which iterative queries + are currently being sent. + + The first list includes all unique clients that are waiting for + recursion to complete, including the query that is awaiting a + response and the timestamp (seconds since the Unix epoch) of + when named started processing this client query. + + The second list comprises of domains for which there are active + (or recently active) fetches in progress. It reports the number + of active fetches for each domain and the number of queries that + have been passed (allowed) or dropped (spilled) as a result of + the ``fetches-per-zone`` limit. (Note: these counters are not + cumulative over time; whenever the number of active fetches for + a domain drops to zero, the counter for that domain is deleted, + and the next time a fetch is sent to that domain, it is recreated + with the counters set to zero). + +``refresh`` *zone* [*class* [*view*]] + This command schedules zone maintenance for the given zone. + +``reload`` + This command reloads the configuration file and zones. + +``reload`` *zone* [*class* [*view*]] + This command reloads the given zone. + +``retransfer`` *zone* [*class* [*view*]] + This command retransfers the given secondary zone from the primary server. + + If the zone is configured to use ``inline-signing``, the signed + version of the zone is discarded; after the retransfer of the + unsigned version is complete, the signed version is regenerated + with new signatures. + +``scan`` + This command scans the list of available network interfaces for changes, without + performing a full ``reconfig`` or waiting for the + ``interface-interval`` timer. + +``secroots`` [**-**] [*view* ...] + This command dumps the security roots (i.e., trust anchors configured via + ``trust-anchors``, or the ``managed-keys`` or ``trusted-keys`` statements + [both deprecated], or ``dnssec-validation auto``) and negative trust anchors + for the specified views. If no view is specified, all views are + dumped. Security roots indicate whether they are configured as trusted + keys, managed keys, or initializing managed keys (managed keys that have not + yet been updated by a successful key refresh query). + + If the first argument is ``-``, then the output is returned via the + ``rndc`` response channel and printed to the standard output. + Otherwise, it is written to the secroots dump file, which defaults to + ``named.secroots``, but can be overridden via the ``secroots-file`` + option in ``named.conf``. + + See also ``rndc managed-keys``. + +``serve-stale`` (**on** | **off** | **reset** | **status**) [*class* [*view*]] + This command enables, disables, resets, or reports the current status of the serving + of stale answers as configured in ``named.conf``. + + If serving of stale answers is disabled by ``rndc-serve-stale off``, + then it remains disabled even if ``named`` is reloaded or + reconfigured. ``rndc serve-stale reset`` restores the setting as + configured in ``named.conf``. + + ``rndc serve-stale status`` reports whether serving of stale + answers is currently enabled, disabled by the configuration, or + disabled by ``rndc``. It also reports the values of + ``stale-answer-ttl`` and ``max-stale-ttl``. + +``showzone`` *zone* [*class* [*view*]] + This command prints the configuration of a running zone. + + See also ``rndc zonestatus``. + +``sign`` *zone* [*class* [*view*]] + This command fetches all DNSSEC keys for the given zone from the key directory (see + the ``key-directory`` option in the BIND 9 Administrator Reference + Manual). If they are within their publication period, they are merged into + the zone's DNSKEY RRset. If the DNSKEY RRset is changed, then the + zone is automatically re-signed with the new key set. + + This command requires that the zone be configured with a ``dnssec-policy``, or + that the ``auto-dnssec`` zone option be set to ``allow`` or ``maintain``, + and also requires the zone to be configured to allow dynamic DNS. (See + "Dynamic Update Policies" in the BIND 9 Administrator Reference Manual for more + details.) + + See also ``rndc loadkeys``. + +``signing`` [(**-list** | **-clear** *keyid/algorithm* | **-clear** *all* | **-nsec3param** ( *parameters* | none ) | **-serial** *value* ) *zone* [*class* [*view*]] + This command lists, edits, or removes the DNSSEC signing-state records for the + specified zone. The status of ongoing DNSSEC operations, such as + signing or generating NSEC3 chains, is stored in the zone in the form + of DNS resource records of type ``sig-signing-type``. + ``rndc signing -list`` converts these records into a human-readable + form, indicating which keys are currently signing or have finished + signing the zone, and which NSEC3 chains are being created or + removed. + + ``rndc signing -clear`` can remove a single key (specified in the + same format that ``rndc signing -list`` uses to display it), or all + keys. In either case, only completed keys are removed; any record + indicating that a key has not yet finished signing the zone is + retained. + + ``rndc signing -nsec3param`` sets the NSEC3 parameters for a zone. + This is the only supported mechanism for using NSEC3 with + ``inline-signing`` zones. Parameters are specified in the same format + as an NSEC3PARAM resource record: ``hash algorithm``, ``flags``, ``iterations``, + and ``salt``, in that order. + + Currently, the only defined value for ``hash algorithm`` is ``1``, + representing SHA-1. The ``flags`` may be set to ``0`` or ``1``, + depending on whether the opt-out bit in the NSEC3 + chain should be set. ``iterations`` defines the number of additional times to apply + the algorithm when generating an NSEC3 hash. The ``salt`` is a string + of data expressed in hexadecimal, a hyphen (``-``) if no salt is to be + used, or the keyword ``auto``, which causes ``named`` to generate a + random 64-bit salt. + + The only recommended configuration is ``rndc signing -nsec3param 1 0 0 - zone``, + i.e. no salt, no additional iterations, no opt-out. + + .. warning:: + Do not use extra iterations, salt, or opt-out unless all their implications + are fully understood. A higher number of iterations causes interoperability + problems and opens servers to CPU-exhausting DoS attacks. + + ``rndc signing -nsec3param none`` removes an existing NSEC3 chain and + replaces it with NSEC. + + ``rndc signing -serial value`` sets the serial number of the zone to + ``value``. If the value would cause the serial number to go backwards, it + is rejected. The primary use of this parameter is to set the serial number on inline + signed zones. + +``stats`` + This command writes server statistics to the statistics file. (See the + ``statistics-file`` option in the BIND 9 Administrator Reference + Manual.) + +``status`` + This command displays the status of the server. Note that the number of zones includes + the internal ``bind/CH`` zone and the default ``./IN`` hint zone, if + there is no explicit root zone configured. + +``stop`` **-p** + This command stops the server, making sure any recent changes made through dynamic + update or IXFR are first saved to the master files of the updated + zones. If ``-p`` is specified, ``named(8)`'s process ID is returned. + This allows an external process to determine when ``named`` has + completed stopping. + + See also ``rndc halt``. + +``sync`` **-clean** [*zone* [*class* [*view*]]] + This command syncs changes in the journal file for a dynamic zone to the master + file. If the "-clean" option is specified, the journal file is also + removed. If no zone is specified, then all zones are synced. + +``tcp-timeouts`` [*initial* *idle* *keepalive* *advertised*] + When called without arguments, this command displays the current values of the + ``tcp-initial-timeout``, ``tcp-idle-timeout``, + ``tcp-keepalive-timeout``, and ``tcp-advertised-timeout`` options. + When called with arguments, these values are updated. This allows an + administrator to make rapid adjustments when under a + denial-of-service (DoS) attack. See the descriptions of these options in the BIND 9 + Administrator Reference Manual for details of their use. + +``thaw`` [*zone* [*class* [*view*]]] + This command enables updates to a frozen dynamic zone. If no zone is specified, + then all frozen zones are enabled. This causes the server to reload + the zone from disk, and re-enables dynamic updates after the load has + completed. After a zone is thawed, dynamic updates are no longer + refused. If the zone has changed and the ``ixfr-from-differences`` + option is in use, the journal file is updated to reflect + changes in the zone. Otherwise, if the zone has changed, any existing + journal file is removed. + + See also ``rndc freeze``. + +``trace`` + This command increments the server's debugging level by one. + +``trace`` *level* + This command sets the server's debugging level to an explicit value. + + See also ``rndc notrace``. + +``tsig-delete`` *keyname* [*view*] + This command deletes a given TKEY-negotiated key from the server. This does not + apply to statically configured TSIG keys. + +``tsig-list`` + This command lists the names of all TSIG keys currently configured for use by + ``named`` in each view. The list includes both statically configured keys and + dynamic TKEY-negotiated keys. + +``validation`` (**on** | **off** | **status**) [*view* ...]`` + This command enables, disables, or checks the current status of DNSSEC validation. By + default, validation is enabled. + + The cache is flushed when validation is turned on or off to avoid using data + that might differ between states. + +``zonestatus`` *zone* [*class* [*view*]] + This command displays the current status of the given zone, including the master + file name and any include files from which it was loaded, when it was + most recently loaded, the current serial number, the number of nodes, + whether the zone supports dynamic updates, whether the zone is DNSSEC + signed, whether it uses automatic DNSSEC key management or inline + signing, and the scheduled refresh or expiry times for the zone. + + See also ``rndc showzone``. + +``rndc`` commands that specify zone names, such as ``reload``, +``retransfer``, or ``zonestatus``, can be ambiguous when applied to zones +of type ``redirect``. Redirect zones are always called ``.``, and can be +confused with zones of type ``hint`` or with secondary copies of the root +zone. To specify a redirect zone, use the special zone name +``-redirect``, without a trailing period. (With a trailing period, this +would specify a zone called "-redirect".) + +Limitations +~~~~~~~~~~~ + +There is currently no way to provide the shared secret for a ``key_id`` +without using the configuration file. + +Several error messages could be clearer. + +See Also +~~~~~~~~ + +:manpage:`rndc.conf(5)`, :manpage:`rndc-confgen(8)`, +:manpage:`named(8)`, :manpage:`named.conf(5)`, :manpage:`ndc(8)`, BIND 9 Administrator +Reference Manual. diff --git a/bin/rndc/util.c b/bin/rndc/util.c new file mode 100644 index 0000000..3b3587c --- /dev/null +++ b/bin/rndc/util.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include "util.h" +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include <isc/print.h> + +extern bool verbose; +extern const char *progname; + +void +notify(const char *fmt, ...) { + va_list ap; + + if (verbose) { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputs("\n", stderr); + } +} + +void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} diff --git a/bin/rndc/util.h b/bin/rndc/util.h new file mode 100644 index 0000000..2d3c664 --- /dev/null +++ b/bin/rndc/util.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef RNDC_UTIL_H +#define RNDC_UTIL_H 1 + +/*! \file */ + +#include <isc/formatcheck.h> +#include <isc/lang.h> +#include <isc/platform.h> + +#define NS_CONTROL_PORT 953 + +#undef DO +#define DO(name, function) \ + do { \ + result = function; \ + if (result != ISC_R_SUCCESS) \ + fatal("%s: %s", name, isc_result_totext(result)); \ + else \ + notify("%s", name); \ + } while (0) + +ISC_LANG_BEGINDECLS + +void +notify(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2); + +ISC_PLATFORM_NORETURN_PRE void +fatal(const char *format, ...) + ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; + +ISC_LANG_ENDDECLS + +#endif /* RNDC_UTIL_H */ diff --git a/bin/rndc/win32/rndc.vcxproj.filters.in b/bin/rndc/win32/rndc.vcxproj.filters.in new file mode 100644 index 0000000..5187c16 --- /dev/null +++ b/bin/rndc/win32/rndc.vcxproj.filters.in @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\util.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\rndc.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/bin/rndc/win32/rndc.vcxproj.in b/bin/rndc/win32/rndc.vcxproj.in new file mode 100644 index 0000000..2a72f5e --- /dev/null +++ b/bin/rndc/win32/rndc.vcxproj.in @@ -0,0 +1,122 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|@PLATFORM@"> + <Configuration>Debug</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|@PLATFORM@"> + <Configuration>Release</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{39721F26-8B80-4AA9-9826-2AEF7322C3D5}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>rndc</RootNamespace> + @WINDOWS_TARGET_PLATFORM_VERSION@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <TreatWarningAsError>false</TreatWarningAsError> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <BrowseInformation>true</BrowseInformation> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <TreatWarningAsError>true</TreatWarningAsError> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <WholeProgramOptimization>false</WholeProgramOptimization> + <StringPooling>true</StringPooling> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> + <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@util.lib;libisc.lib;libdns.lib;libisccfg.lib;libisccc.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\util.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\rndc.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/bin/rndc/win32/rndc.vcxproj.user b/bin/rndc/win32/rndc.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/bin/rndc/win32/rndc.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +</Project>
\ No newline at end of file diff --git a/bin/rndc/win32/rndcutil.vcxproj.filters.in b/bin/rndc/win32/rndcutil.vcxproj.filters.in new file mode 100644 index 0000000..766ea80 --- /dev/null +++ b/bin/rndc/win32/rndcutil.vcxproj.filters.in @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\util.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\util.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/bin/rndc/win32/rndcutil.vcxproj.in b/bin/rndc/win32/rndcutil.vcxproj.in new file mode 100644 index 0000000..fad1472 --- /dev/null +++ b/bin/rndc/win32/rndcutil.vcxproj.in @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|@PLATFORM@"> + <Configuration>Debug</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|@PLATFORM@"> + <Configuration>Release</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{7C8681A1-E3A8-470E-9EEF-16054D111A19}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>rndcutil</RootNamespace> + @WINDOWS_TARGET_PLATFORM_VERSION@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>.\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + <TargetName>util</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>.\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + <TargetName>util</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <TreatWarningAsError>false</TreatWarningAsError> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <BrowseInformation>true</BrowseInformation> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <TreatWarningAsError>true</TreatWarningAsError> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <WholeProgramOptimization>false</WholeProgramOptimization> + <StringPooling>true</StringPooling> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + </Lib> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="..\util.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\util.c" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/bin/rndc/win32/rndcutil.vcxproj.user b/bin/rndc/win32/rndcutil.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/bin/rndc/win32/rndcutil.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +</Project>
\ No newline at end of file |