rndc.c revision 927e4c9fecf448bf3894c68fcaf9dc2f89557f3a
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*
ebf264ea105fc78b8316a1166bae0624d488d83bMark Andrews * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2000-2003 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Permission to use, copy, modify, and/or distribute this software for any
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * purpose with or without fee is hereby granted, provided that the above
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/* $Id: rndc.c,v 1.142 2012/02/03 22:27:17 each Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Principal Author: DCL
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <config.h>
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <stdlib.h>
b3e77535185043f089b346166440402d092030c3David Lawrence
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington#include <isc/app.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/buffer.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/commandline.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/file.h>
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein#include <isc/log.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/net.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/mem.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/random.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/socket.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/stdtime.h>
72166c5cf59db011cce11e98abe377f5aa6f7052Andreas Gustafsson#include <isc/string.h>
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister#include <isc/task.h>
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington#include <isc/thread.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isc/util.h>
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson#include <isccfg/namedconf.h>
b3e77535185043f089b346166440402d092030c3David Lawrence
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson#include <isccc/alist.h>
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson#include <isccc/base64.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isccc/cc.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isccc/ccmsg.h>
b3e77535185043f089b346166440402d092030c3David Lawrence#include <isccc/result.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isccc/sexpr.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#include <isccc/types.h>
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <isccc/util.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson#include <dns/name.h>
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include <bind9/getaddresses.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#include "util.h"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister#define SERVERADDRS 10
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrenceconst char *progname;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerisc_boolean_t verbose;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic const char *admin_conffile;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic const char *admin_keyfile;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic const char *version = VERSION;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic const char *servername = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_sockaddr_t serveraddrs[SERVERADDRS];
b3e77535185043f089b346166440402d092030c3David Lawrencestatic isc_sockaddr_t local4, local6;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_boolean_t local4set = ISC_FALSE, local6set = ISC_FALSE;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic int nserveraddrs;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic int currentaddr = 0;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic unsigned int remoteport = 0;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_socketmgr_t *socketmgr = NULL;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic unsigned char databuf[2048];
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isccc_ccmsg_t ccmsg;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_uint32_t algorithm;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isccc_region_t secret;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_boolean_t failed = ISC_FALSE;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_boolean_t c_flag = ISC_FALSE;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_mem_t *mctx;
b3e77535185043f089b346166440402d092030c3David Lawrencestatic int sends, recvs, connects;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic char *command;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic char *args;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic char program[256];
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_socket_t *sock = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic isc_uint32_t serial;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James BristerISC_PLATFORM_NORETURN_PRE static void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerusage(int status) ISC_PLATFORM_NORETURN_POST;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerusage(int status) {
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson fprintf(stderr, "\
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas GustafssonUsage: %s [-b address] [-c config] [-s server] [-p port]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister [-k key-file ] [-y key] [-V] command\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister\n\
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafssoncommand is one of the following:\n\
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister reload Reload configuration file and zones.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister reload zone [class [view]]\n\
b3e77535185043f089b346166440402d092030c3David Lawrence Reload a single zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister refresh zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Schedule immediate maintenance for a zone.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence retransfer zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Retransfer a single zone without checking serial number.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister freeze Suspend updates to all dynamic zones.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister freeze zone [class [view]]\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence Suspend updates to a dynamic zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister thaw Enable updates to all dynamic zones and reload them.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister thaw zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Enable updates to a frozen dynamic zone and reload it.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson remove their journal files.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister sync [-clean] zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Dump a single zone's changes to disk, and optionally\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence remove its journal file.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister notify zone [class [view]]\n\
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson Resend NOTIFY messages for the zone.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence reconfig Reload configuration file and new zones only.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister sign zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Update zone keys, and sign as needed.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister loadkeys zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Update keys without signing immediately.\n\
b3e77535185043f089b346166440402d092030c3David Lawrence zonestatus zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Display the current status of a zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister stats Write server statistics to the statistics file.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister querylog newstate\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence Enable / disable query logging.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews dumpdb [-all|-cache|-zones] [view ...]\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews Dump cache(s) to the dump file (named_dump.db).\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews secroots [view ...]\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews Write security roots to the secroots file.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews stop Save pending updates to master files and stop the server.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews stop -p Save pending updates to master files and stop the server\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews reporting process id.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews halt Stop the server without saving pending updates.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews halt -p Stop the server without saving pending updates reporting\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews process id.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews trace Increment debugging level by one.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews trace level Change the debugging level.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews notrace Set debugging level to 0.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews flush Flushes all of the server's caches.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister flush [view] Flushes the server's cache for a view.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence flushname name [view]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Flush the given name from the server's cache(s)\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister flushtree name [view]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Flush all names under the given name from the server's cache(s)\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister status Display status of the server.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister recursing Dump the queries that are currently recursing (named.recursing)\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister tsig-list List all currently active TSIG keys, including both statically\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence configured and TKEY-negotiated keys.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister tsig-delete keyname [view] \n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Delete a TKEY-negotiated TSIG key.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence validation newstate [view]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Enable / disable DNSSEC validation.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister addzone zone [class [view]] { zone-options }\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews Add zone to given view. Requires new-zone-file option.\n\
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews delzone [-clean] zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Removes zone from given view. Requires new-zone-file option.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence signing -list zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister List the private records showing the state of DNSSEC\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister signing in the given zone.\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence signing -clear <keyid>/<algorithm> zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Remove the private record that indicating the given key\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister has finished signing the given zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister signing -clear all zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Remove the private records for all keys that have\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister finished signing the given zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister signing -nsec3param none zone [class [view]]\n\
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence Remove NSEC3 chains from zone.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister signing -nsec3param hash flags iterations salt zone [class [view]]\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Add NSEC3 chain to zone if already signed.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister Prime zone with NSEC3 chain if not yet signed.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister *restart Restart the server.\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister\n\
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister* == not yet implemented\n\
b3e77535185043f089b346166440402d092030c3David LawrenceVersion: %s\n",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister progname, version);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister exit(status);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerget_addresses(const char *host, in_port_t port) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_result_t result;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence int found = 0, count;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence if (*host == '/') {
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs],
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews host);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews if (result == ISC_R_SUCCESS)
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews nserveraddrs++;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews } else {
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews count = SERVERADDRS - nserveraddrs;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews result = bind9_getaddresses(host, port,
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews &serveraddrs[nserveraddrs],
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews count, &found);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews nserveraddrs += found;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews }
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews if (result != ISC_R_SUCCESS)
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews fatal("couldn't get address for '%s': %s",
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews host, isc_result_totext(result));
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews INSIST(nserveraddrs > 0);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews}
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsstatic void
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrewsrndc_senddone(isc_task_t *task, isc_event_t *event) {
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews isc_socketevent_t *sevent = (isc_socketevent_t *)event;
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister UNUSED(task);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister sends--;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (sevent->result != ISC_R_SUCCESS)
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson fatal("send failed: %s", isc_result_totext(sevent->result));
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson isc_event_free(&event);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (sends == 0 && recvs == 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_socket_detach(&sock);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_task_shutdown(task);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
4844ed026a9b5a91044e76399cee80a6514cbf0dMark Andrews }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerrndc_recvdone(isc_task_t *task, isc_event_t *event) {
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_sexpr_t *response = NULL;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_sexpr_t *data;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_region_t source;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister char *errormsg = NULL;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 char *textmsg = NULL;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_result_t result;
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence recvs--;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (ccmsg.result == ISC_R_EOF)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fatal("connection to remote host closed\n"
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence "This may indicate that\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "* the remote server is using an older version of"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister " the command protocol,\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "* this host is not authorized to connect,\n"
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson "* the clocks are not synchronized, or\n"
b3e77535185043f089b346166440402d092030c3David Lawrence "* the key is invalid.");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (ccmsg.result != ISC_R_SUCCESS)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fatal("recv failed: %s", isc_result_totext(ccmsg.result));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister source.rstart = isc_buffer_base(&ccmsg.buffer);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence source.rend = isc_buffer_used(&ccmsg.buffer);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("parse message",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_cc_fromwire(&source, &response, algorithm, &secret));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister data = isccc_alist_lookup(response, "_data");
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson if (data == NULL)
b3e77535185043f089b346166440402d092030c3David Lawrence fatal("no data section in response");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister result = isccc_cc_lookupstring(data, "err", &errormsg);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (result == ISC_R_SUCCESS) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister failed = ISC_TRUE;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fprintf(stderr, "%s: '%s' failed: %s\n",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister progname, command, errormsg);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister else if (result != ISC_R_NOTFOUND)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fprintf(stderr, "%s: parsing response failed: %s\n",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister progname, isc_result_totext(result));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister result = isccc_cc_lookupstring(data, "text", &textmsg);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (result == ISC_R_SUCCESS) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (strlen(textmsg) != 0U)
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson printf("%s\n", textmsg);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson } else if (result != ISC_R_NOTFOUND)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fprintf(stderr, "%s: parsing response failed: %s\n",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister progname, isc_result_totext(result));
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson isc_event_free(&event);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_sexpr_free(&response);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (sends == 0 && recvs == 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_socket_detach(&sock);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_task_shutdown(task);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencerndc_recvnonce(isc_task_t *task, isc_event_t *event) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_sexpr_t *response = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_sexpr_t *_ctrl;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_region_t source;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_result_t result;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_uint32_t nonce;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_sexpr_t *request = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_time_t now;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_region_t r;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isccc_sexpr_t *data;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 isccc_region_t message;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 isc_uint32_t len;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 isc_buffer_t b;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 recvs--;
f3ca27e9fe307b55e35ea8d7b37351650630e5a3Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (ccmsg.result == ISC_R_EOF)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fatal("connection to remote host closed\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "This may indicate that\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "* the remote server is using an older version of"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister " the command protocol,\n"
b3e77535185043f089b346166440402d092030c3David Lawrence "* this host is not authorized to connect,\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "* the clocks are not synchronized,\n"
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence "* the the key signing algorithm is incorrect, or\n"
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "* the key is invalid.");
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
b3e77535185043f089b346166440402d092030c3David Lawrence if (ccmsg.result != ISC_R_SUCCESS)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence fatal("recv failed: %s", isc_result_totext(ccmsg.result));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence source.rstart = isc_buffer_base(&ccmsg.buffer);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence source.rend = isc_buffer_used(&ccmsg.buffer);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("parse message",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isccc_cc_fromwire(&source, &response, algorithm, &secret));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence _ctrl = isccc_alist_lookup(response, "_ctrl");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (_ctrl == NULL)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister fatal("_ctrl section missing");
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence nonce = 0;
b3e77535185043f089b346166440402d092030c3David Lawrence if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister nonce = 0;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence isc_stdtime_get(&now);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister now, now + 60, &request));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister data = isccc_alist_lookup(request, "_data");
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (data == NULL)
b3e77535185043f089b346166440402d092030c3David Lawrence fatal("_data section missing");
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (isccc_cc_definestring(data, "type", args) == NULL)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence fatal("out of memory");
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (nonce != 0) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence _ctrl = isccc_alist_lookup(request, "_ctrl");
b3e77535185043f089b346166440402d092030c3David Lawrence if (_ctrl == NULL)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence fatal("_ctrl section missing");
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
b3e77535185043f089b346166440402d092030c3David Lawrence fatal("out of memory");
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister message.rstart = databuf + 4;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister message.rend = databuf + sizeof(databuf);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister DO("render message",
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_cc_towire(request, &message, algorithm, &secret));
b3e77535185043f089b346166440402d092030c3David Lawrence len = sizeof(databuf) - REGION_SIZE(message);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_buffer_init(&b, databuf, 4);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_buffer_putuint32(&b, len - 4);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence r.length = len;
b3e77535185043f089b346166440402d092030c3David Lawrence r.base = databuf;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_ccmsg_cancelread(&ccmsg);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister rndc_recvdone, NULL));
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister recvs++;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister NULL));
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister sends++;
b3e77535185043f089b346166440402d092030c3David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_event_free(&event);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isccc_sexpr_free(&response);
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister return;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
b3e77535185043f089b346166440402d092030c3David Lawrence
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencestatic void
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Bristerrndc_connected(isc_task_t *task, isc_event_t *event) {
b3e77535185043f089b346166440402d092030c3David Lawrence char socktext[ISC_SOCKADDR_FORMATSIZE];
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_socketevent_t *sevent = (isc_socketevent_t *)event;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_sexpr_t *request = NULL;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_sexpr_t *data;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_time_t now;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isccc_region_t message;
b3e77535185043f089b346166440402d092030c3David Lawrence isc_region_t r;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_uint32_t len;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_buffer_t b;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_result_t result;
b3e77535185043f089b346166440402d092030c3David Lawrence
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister connects--;
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister
b3e77535185043f089b346166440402d092030c3David Lawrence if (sevent->result != ISC_R_SUCCESS) {
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister sizeof(socktext));
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (sevent->result != ISC_R_CANCELED &&
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington ++currentaddr < nserveraddrs)
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington {
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington notify("connection failed: %s: %s", socktext,
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isc_result_totext(sevent->result));
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isc_socket_detach(&sock);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isc_event_free(&event);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington rndc_startconnect(&serveraddrs[currentaddr], task);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington return;
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington } else
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington fatal("connect failed: %s: %s", socktext,
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isc_result_totext(sevent->result));
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington }
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isc_stdtime_get(&now);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington now, now + 60, &request));
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington data = isccc_alist_lookup(request, "_data");
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington if (data == NULL)
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington fatal("_data section missing");
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington if (isccc_cc_definestring(data, "type", "null") == NULL)
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington fatal("out of memory");
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington message.rstart = databuf + 4;
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington message.rend = databuf + sizeof(databuf);
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington DO("render message",
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington isccc_cc_towire(request, &message, algorithm, &secret));
d25dd5b0567f67ecf40b7ed1cb20e0dce7b41c49Brian Wellington len = sizeof(databuf) - REGION_SIZE(message);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_buffer_init(&b, databuf, 4);
3e42bdfdc901b6b921b02028bd51ca2af8e84adcMark Andrews isc_buffer_putuint32(&b, len - 4);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister r.length = len;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence r.base = databuf;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isccc_ccmsg_init(mctx, sock, &ccmsg);
b3e77535185043f089b346166440402d092030c3David Lawrence isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
b3e77535185043f089b346166440402d092030c3David Lawrence rndc_recvnonce, NULL));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence recvs++;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister NULL));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister sends++;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_event_free(&event);
3e42bdfdc901b6b921b02028bd51ca2af8e84adcMark Andrews}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrencerndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
b3e77535185043f089b346166440402d092030c3David Lawrence isc_result_t result;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int pf;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_sockettype_t type;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister char socktext[ISC_SOCKADDR_FORMATSIZE];
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_sockaddr_format(addr, socktext, sizeof(socktext));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister notify("using server %s (%s)", servername, socktext);
b3e77535185043f089b346166440402d092030c3David Lawrence
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister pf = isc_sockaddr_pf(addr);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (pf == AF_INET || pf == AF_INET6)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister type = isc_sockettype_tcp;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence else
b3e77535185043f089b346166440402d092030c3David Lawrence type = isc_sockettype_unix;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence switch (isc_sockaddr_pf(addr)) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister case AF_INET:
b3e77535185043f089b346166440402d092030c3David Lawrence DO("bind socket", isc_socket_bind(sock, &local4, 0));
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence break;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister case AF_INET6:
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("bind socket", isc_socket_bind(sock, &local6, 0));
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister break;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister default:
b3e77535185043f089b346166440402d092030c3David Lawrence break;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister }
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence NULL));
b3e77535185043f089b346166440402d092030c3David Lawrence connects++;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerrndc_start(isc_task_t *task, isc_event_t *event) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_event_free(&event);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister currentaddr = 0;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister rndc_startconnect(&serveraddrs[currentaddr], task);
b3e77535185043f089b346166440402d092030c3David Lawrence}
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic void
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerparse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister cfg_parser_t **pctxp, cfg_obj_t **configp)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister{
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_result_t result;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence const char *conffile = admin_conffile;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *addresses = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *defkey = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *options = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *servers = NULL;
b3e77535185043f089b346166440402d092030c3David Lawrence const cfg_obj_t *server = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *keys = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *key = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *defport = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *secretobj = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *algorithmobj = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister cfg_obj_t *config = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_obj_t *address = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_listelt_t *elt;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const char *secretstr;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const char *algorithmstr;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence static char secretarray[1024];
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister const cfg_type_t *conftype = &cfg_type_rndcconf;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_boolean_t key_only = ISC_FALSE;
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington const cfg_listelt_t *element;
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (! isc_file_exists(conffile)) {
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington conffile = admin_keyfile;
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington conftype = &cfg_type_rndckey;
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (c_flag)
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington fatal("%s does not exist", admin_conffile);
15c5b240a6122795212c1aff03634e7156951e91Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (! isc_file_exists(conffile))
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington fatal("neither %s nor %s was found",
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington admin_conffile, admin_keyfile);
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington key_only = ISC_TRUE;
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington } else if (! c_flag && isc_file_exists(admin_keyfile)) {
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington fprintf(stderr, "WARNING: key file (%s) exists, but using "
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington "default configuration file (%s)\n",
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington admin_keyfile, admin_conffile);
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington }
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington DO("create parser", cfg_parser_create(mctx, log, pctxp));
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington /*
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington * The parser will output its own errors, so DO() is not used.
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington */
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington result = cfg_parse_file(*pctxp, conffile, conftype, &config);
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (result != ISC_R_SUCCESS)
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington fatal("could not load rndc configuration");
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (!key_only)
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington (void)cfg_map_get(config, "options", &options);
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington if (key_only && servername == NULL)
590f840d3484114576d9f8a7f7d73fbe31228888Brian Wellington servername = "127.0.0.1";
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 else if (servername == NULL && options != NULL) {
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 const cfg_obj_t *defserverobj = NULL;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 (void)cfg_map_get(options, "default-server", &defserverobj);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (defserverobj != NULL)
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 servername = cfg_obj_asstring(defserverobj);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 }
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (servername == NULL)
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 fatal("no server specified and no default");
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (!key_only) {
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 (void)cfg_map_get(config, "server", &servers);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (servers != NULL) {
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 for (elt = cfg_list_first(servers);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 elt != NULL;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 elt = cfg_list_next(elt))
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 {
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 const char *name;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 server = cfg_listelt_value(elt);
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 name = cfg_obj_asstring(cfg_map_getname(server));
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 if (strcasecmp(name, servername) == 0)
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 break;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 server = NULL;
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 }
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 }
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 }
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 /*
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 * Look for the name of the key to use.
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 */
600cbd1fcea3c9cc9706dc1ff8fc0d0034ebdeacTatuya JINMEI 神明達哉 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 > ISC_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 = ISC_TRUE;
}
}
if (!local4set && options != NULL) {
address = NULL;
cfg_map_get(options, "default-source-address", &address);
if (address != NULL) {
local4 = *cfg_obj_assockaddr(address);
local4set = ISC_TRUE;
}
}
if (!local6set && server != NULL) {
address = NULL;
cfg_map_get(server, "source-address-v6", &address);
if (address != NULL) {
local6 = *cfg_obj_assockaddr(address);
local6set = ISC_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 = ISC_TRUE;
}
}
*configp = config;
}
int
main(int argc, char **argv) {
isc_boolean_t show_final_mem = ISC_FALSE;
isc_result_t result = ISC_R_SUCCESS;
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)
memcpy(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 = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:s:Vy:"))
!= -1) {
switch (ch) {
case 'b':
if (inet_pton(AF_INET, isc_commandline_argument,
&in) == 1) {
isc_sockaddr_fromin(&local4, &in, 0);
local4set = ISC_TRUE;
} else if (inet_pton(AF_INET6, isc_commandline_argument,
&in6) == 1) {
isc_sockaddr_fromin6(&local6, &in6, 0);
local6set = ISC_TRUE;
}
break;
case 'c':
admin_conffile = isc_commandline_argument;
c_flag = ISC_TRUE;
break;
case 'k':
admin_keyfile = isc_commandline_argument;
break;
case 'M':
isc_mem_debugging = ISC_MEM_DEBUGTRACE;
break;
case 'm':
show_final_mem = ISC_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 's':
servername = isc_commandline_argument;
break;
case 'V':
verbose = ISC_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);
isc_random_get(&serial);
DO("create memory context", isc_mem_create(0, 0, &mctx));
DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr));
DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr));
DO("create task", isc_task_create(taskmgr, 0, &task));
DO("create logging context", isc_log_create(mctx, &log, &logconfig));
isc_log_setcontext(log);
DO("setting log tag", isc_log_settag(logconfig, progname));
logdest.file.stream = stderr;
logdest.file.name = NULL;
logdest.file.versions = ISC_LOG_ROLLNEVER;
logdest.file.maximum_size = 0;
DO("creating log channel",
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(mctx, log, keyname, &pctx, &config);
isccc_result_register();
command = *argv;
/*
* 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(mctx, argslen);
if (args == NULL)
DO("isc_mem_get", ISC_R_NOMEMORY);
p = args;
for (i = 0; i < argc; i++) {
size_t len = strlen(argv[i]);
memcpy(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)
get_addresses(servername, (in_port_t) remoteport);
DO("post event", isc_app_onrun(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 (connects > 0 || sends > 0 || recvs > 0)
isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
isc_task_detach(&task);
isc_taskmgr_destroy(&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(mctx, args, argslen);
isccc_ccmsg_invalidate(&ccmsg);
dns_name_destroy();
if (show_final_mem)
isc_mem_stats(mctx, stderr);
isc_mem_destroy(&mctx);
if (failed)
return (1);
return (0);
}