rndc.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 2000-2016 Internet Systems Consortium, Inc. ("ISC")
*
* 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 http://mozilla.org/MPL/2.0/.
*/
/*! \file */
/*
* Principal Author: DCL
*/
#include <config.h>
#include <stdlib.h>
#include <isc/commandline.h>
#include <isccfg/namedconf.h>
#include <bind9/getaddresses.h>
#include "util.h"
#define SERVERADDRS 10
const char *progname;
static const char *admin_conffile;
static const char *admin_keyfile;
static const char *servername = NULL;
static int nserveraddrs;
static int currentaddr = 0;
static unsigned int remoteport = 0;
static isc_buffer_t *databuf;
static isccc_ccmsg_t ccmsg;
static isc_uint32_t algorithm;
static isccc_region_t secret;
static char *command;
static char *args;
static char program[256];
static isc_uint32_t serial;
ISC_PLATFORM_NORETURN_PRE static void
static void
Usage: %s [-b address] [-c config] [-s server] [-p port]\n\
[-k key-file ] [-y key] [-r] [-V] 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\
dumpdb [-all|-cache|-zones|-adb|-bad|-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 newstate\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\
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\
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\
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 newstate [view]\n\
Enable / disable DNSSEC validation.\n\
zonestatus zone [class [view]]\n\
Display the current status of a zone.\n\
\n\
Version: %s\n",
}
static void
if (*host == '/') {
host);
if (result == ISC_R_SUCCESS)
nserveraddrs++;
} else {
nserveraddrs += found;
}
if (result != ISC_R_SUCCESS)
fatal("couldn't get address for '%s': %s",
INSIST(nserveraddrs > 0);
}
static void
sends--;
}
}
static void
recvs--;
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.");
DO("parse message",
if (!isccc_alist_alistp(data))
fatal("bad or missing data section in response");
if (result == ISC_R_SUCCESS) {
}
else if (result != ISC_R_NOTFOUND)
if (result == ISC_R_SUCCESS) {
} else if (result != ISC_R_NOTFOUND)
if (showresult) {
if (result == ISC_R_SUCCESS)
else
printf("NONE -1\n");
}
}
}
static void
isc_region_t r;
isc_buffer_t b;
recvs--;
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.");
DO("parse message",
if (!isccc_alist_alistp(_ctrl))
fatal("bad or missing ctrl section in response");
nonce = 0;
nonce = 0;
fatal("_data section missing");
fatal("out of memory");
if (nonce != 0) {
fatal("_ctrl section missing");
fatal("out of memory");
}
/* Skip the length field (4 bytes) */
DO("render message",
rndc_recvdone, NULL));
recvs++;
NULL));
sends++;
return;
}
static void
char socktext[ISC_SOCKADDR_FORMATSIZE];
isc_region_t r;
isc_buffer_t b;
connects--;
sizeof(socktext));
++currentaddr < nserveraddrs)
{
return;
} else
}
fatal("_data section missing");
fatal("out of memory");
/* Skip the length field (4 bytes) */
DO("render message",
rndc_recvnonce, NULL));
recvs++;
NULL));
sends++;
}
static void
int pf;
char socktext[ISC_SOCKADDR_FORMATSIZE];
else
switch (isc_sockaddr_pf(addr)) {
case AF_INET:
break;
case AF_INET6:
break;
default:
break;
}
NULL));
connects++;
}
static void
currentaddr = 0;
}
static void
{
const char *conffile = admin_conffile;
const cfg_listelt_t *elt;
const char *secretstr;
const char *algorithmstr;
static char secretarray[1024];
const cfg_listelt_t *element;
if (! isc_file_exists(conffile)) {
if (c_flag)
if (! isc_file_exists(conffile))
fatal("neither %s nor %s was found",
"default configuration file (%s)\n",
}
/*
* The parser will output its own errors, so DO() is not used.
*/
if (result != ISC_R_SUCCESS)
fatal("could not load rndc configuration");
if (!key_only)
servername = "127.0.0.1";
if (defserverobj != NULL)
}
if (servername == NULL)
fatal("no server specified and no default");
if (!key_only) {
{
const char *name;
break;
}
}
}
/*
* Look for the name of the key to use.
*/
; /* Was set on command line, do nothing. */
&defkey));
} else if (!key_only)
fatal("no key for server and no default");
/*
* Get the key's definition.
*/
if (key_only)
else {
{
keyname) == 0)
break;
}
}
fatal("key must have algorithm and secret");
else
/*
* Find the port to connect to.
*/
if (remoteport != 0)
; /* Was set on command line, do nothing. */
else {
}
} else if (remoteport == 0)
else
if (result == ISC_R_SUCCESS) {
{
if (!cfg_obj_issockaddr(address)) {
unsigned int myport;
const char *name;
if (cfg_obj_isuint32(obj)) {
if (myport > ISC_UINT16_MAX ||
myport == 0)
fatal("port %u out of range",
myport);
} else
myport = remoteport;
if (nserveraddrs < SERVERADDRS)
else
"%s: dropped\n", name);
continue;
}
if (isc_sockaddr_getport(&sa) == 0)
if (nserveraddrs < SERVERADDRS)
else {
char socktext[ISC_SOCKADDR_FORMATSIZE];
sizeof(socktext));
"too many address: %s: dropped\n",
socktext);
}
}
}
}
}
}
}
}
}
}
}
}
int
char *p;
int ch;
int i;
if (result != ISC_R_SUCCESS)
result = isc_app_start();
if (result != ISC_R_SUCCESS)
!= -1) {
switch (ch) {
case 'b':
&in) == 1) {
&in6) == 1) {
}
break;
case 'c':
break;
case 'k':
break;
case 'M':
break;
case 'm':
break;
case 'p':
fatal("port '%s' out of range",
break;
case 'q':
break;
case 'r':
break;
case 's':
break;
case 'V':
break;
case 'y':
break;
case '?':
if (isc_commandline_option != '?') {
usage(1);
}
/* FALLTHROUGH */
case 'h':
usage(0);
break;
default:
exit(1);
}
}
if (argc < 1)
usage(1);
DO("creating log channel",
DO("allocate data buffer",
/*
* similar to what the user might enter in interactive mode
* (if that were implemented).
*/
argslen = 0;
for (i = 0; i < argc; i++)
p = args;
for (i = 0; i < argc; i++) {
p += len;
*p++ = ' ';
}
p--;
*p++ = '\0';
if (nserveraddrs == 0)
result = isc_app_run();
if (result != ISC_R_SUCCESS)
if (show_final_mem)
if (failed)
return (1);
return (0);
}