2 * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: rndc.c,v 1.126.66.4 2010/07/11 00:12:18 each Exp $ */
23 * Principal Author: DCL
31 #include <isc/buffer.h>
32 #include <isc/commandline.h>
37 #include <isc/random.h>
38 #include <isc/socket.h>
39 #include <isc/stdtime.h>
40 #include <isc/string.h>
42 #include <isc/thread.h>
45 #include <isccfg/namedconf.h>
47 #include <isccc/alist.h>
48 #include <isccc/base64.h>
50 #include <isccc/ccmsg.h>
51 #include <isccc/result.h>
52 #include <isccc/sexpr.h>
53 #include <isccc/types.h>
54 #include <isccc/util.h>
58 #include <bind9/getaddresses.h>
62 #define SERVERADDRS 10
65 isc_boolean_t verbose;
67 static const char *admin_conffile;
68 static const char *admin_keyfile;
69 static const char *version = VERSION;
70 static const char *servername = NULL;
71 static isc_sockaddr_t serveraddrs[SERVERADDRS];
72 static isc_sockaddr_t local4, local6;
73 static isc_boolean_t local4set = ISC_FALSE, local6set = ISC_FALSE;
74 static int nserveraddrs;
75 static int currentaddr = 0;
76 static unsigned int remoteport = 0;
77 static isc_socketmgr_t *socketmgr = NULL;
78 static unsigned char databuf[2048];
79 static isccc_ccmsg_t ccmsg;
80 static isccc_region_t secret;
81 static isc_boolean_t failed = ISC_FALSE;
82 static isc_boolean_t c_flag = ISC_FALSE;
83 static isc_mem_t *mctx;
84 static int sends, recvs, connects;
87 static char program[256];
88 static isc_socket_t *sock = NULL;
89 static isc_uint32_t serial;
91 static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
93 ISC_PLATFORM_NORETURN_PRE static void
94 usage(int status) ISC_PLATFORM_NORETURN_POST;
99 Usage: %s [-c config] [-s server] [-p port]\n\
100 [-k key-file ] [-y key] [-V] command\n\
102 command is one of the following:\n\
104 reload Reload configuration file and zones.\n\
105 reload zone [class [view]]\n\
106 Reload a single zone.\n\
107 refresh zone [class [view]]\n\
108 Schedule immediate maintenance for a zone.\n\
109 retransfer zone [class [view]]\n\
110 Retransfer a single zone without checking serial number.\n\
111 freeze Suspend updates to all dynamic zones.\n\
112 freeze zone [class [view]]\n\
113 Suspend updates to a dynamic zone.\n\
114 thaw Enable updates to all dynamic zones and reload them.\n\
115 thaw zone [class [view]]\n\
116 Enable updates to a frozen dynamic zone and reload it.\n\
117 notify zone [class [view]]\n\
118 Resend NOTIFY messages for the zone.\n\
119 reconfig Reload configuration file and new zones only.\n\
120 sign zone [class [view]]\n\
121 Update zone keys, and sign as needed.\n\
122 stats Write server statistics to the statistics file.\n\
123 querylog Toggle query logging.\n\
124 dumpdb [-all|-cache|-zones] [view ...]\n\
125 Dump cache(s) to the dump file (named_dump.db).\n\
126 secroots [view ...]\n\
127 Write security roots to the secroots file.\n\
128 stop Save pending updates to master files and stop the server.\n\
129 stop -p Save pending updates to master files and stop the server\n\
130 reporting process id.\n\
131 halt Stop the server without saving pending updates.\n\
132 halt -p Stop the server without saving pending updates reporting\n\
134 trace Increment debugging level by one.\n\
135 trace level Change the debugging level.\n\
136 notrace Set debugging level to 0.\n\
137 flush Flushes all of the server's caches.\n\
138 flush [view] Flushes the server's cache for a view.\n\
139 flushname name [view]\n\
140 Flush the given name from the server's cache(s)\n\
141 status Display status of the server.\n\
142 recursing Dump the queries that are currently recursing (named.recursing)\n\
143 validation newstate [view]\n\
144 Enable / disable DNSSEC validation.\n\
145 *restart Restart the server.\n\
146 addzone [\"file\"] zone [class [view]] { zone-options }\n\
147 Add zone to given view. Requires new-zone-file option.\n\
148 delzone [\"file\"] zone [class [view]]\n\
149 Removes zone from given view. Requires new-zone-file option.\n\
151 * == not yet implemented\n\
159 get_addresses(const char *host, in_port_t port) {
161 int found = 0, count;
164 result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs],
166 if (result == ISC_R_SUCCESS)
169 count = SERVERADDRS - nserveraddrs;
170 result = bind9_getaddresses(host, port,
171 &serveraddrs[nserveraddrs],
173 nserveraddrs += found;
175 if (result != ISC_R_SUCCESS)
176 fatal("couldn't get address for '%s': %s",
177 host, isc_result_totext(result));
178 INSIST(nserveraddrs > 0);
182 rndc_senddone(isc_task_t *task, isc_event_t *event) {
183 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
188 if (sevent->result != ISC_R_SUCCESS)
189 fatal("send failed: %s", isc_result_totext(sevent->result));
190 isc_event_free(&event);
191 if (sends == 0 && recvs == 0) {
192 isc_socket_detach(&sock);
193 isc_task_shutdown(task);
194 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
199 rndc_recvdone(isc_task_t *task, isc_event_t *event) {
200 isccc_sexpr_t *response = NULL;
202 isccc_region_t source;
203 char *errormsg = NULL;
204 char *textmsg = NULL;
209 if (ccmsg.result == ISC_R_EOF)
210 fatal("connection to remote host closed\n"
211 "This may indicate that\n"
212 "* the remote server is using an older version of"
213 " the command protocol,\n"
214 "* this host is not authorized to connect,\n"
215 "* the clocks are not synchronized, or\n"
216 "* the key is invalid.");
218 if (ccmsg.result != ISC_R_SUCCESS)
219 fatal("recv failed: %s", isc_result_totext(ccmsg.result));
221 source.rstart = isc_buffer_base(&ccmsg.buffer);
222 source.rend = isc_buffer_used(&ccmsg.buffer);
224 DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
226 data = isccc_alist_lookup(response, "_data");
228 fatal("no data section in response");
229 result = isccc_cc_lookupstring(data, "err", &errormsg);
230 if (result == ISC_R_SUCCESS) {
232 fprintf(stderr, "%s: '%s' failed: %s\n",
233 progname, command, errormsg);
235 else if (result != ISC_R_NOTFOUND)
236 fprintf(stderr, "%s: parsing response failed: %s\n",
237 progname, isc_result_totext(result));
239 result = isccc_cc_lookupstring(data, "text", &textmsg);
240 if (result == ISC_R_SUCCESS)
241 printf("%s\n", textmsg);
242 else if (result != ISC_R_NOTFOUND)
243 fprintf(stderr, "%s: parsing response failed: %s\n",
244 progname, isc_result_totext(result));
246 isc_event_free(&event);
247 isccc_sexpr_free(&response);
248 if (sends == 0 && recvs == 0) {
249 isc_socket_detach(&sock);
250 isc_task_shutdown(task);
251 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
256 rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
257 isccc_sexpr_t *response = NULL;
258 isccc_sexpr_t *_ctrl;
259 isccc_region_t source;
262 isccc_sexpr_t *request = NULL;
266 isccc_region_t message;
272 if (ccmsg.result == ISC_R_EOF)
273 fatal("connection to remote host closed\n"
274 "This may indicate that\n"
275 "* the remote server is using an older version of"
276 " the command protocol,\n"
277 "* this host is not authorized to connect,\n"
278 "* the clocks are not synchronized, or\n"
279 "* the key is invalid.");
281 if (ccmsg.result != ISC_R_SUCCESS)
282 fatal("recv failed: %s", isc_result_totext(ccmsg.result));
284 source.rstart = isc_buffer_base(&ccmsg.buffer);
285 source.rend = isc_buffer_used(&ccmsg.buffer);
287 DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
289 _ctrl = isccc_alist_lookup(response, "_ctrl");
291 fatal("_ctrl section missing");
293 if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
296 isc_stdtime_get(&now);
298 DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
299 now, now + 60, &request));
300 data = isccc_alist_lookup(request, "_data");
302 fatal("_data section missing");
303 if (isccc_cc_definestring(data, "type", args) == NULL)
304 fatal("out of memory");
306 _ctrl = isccc_alist_lookup(request, "_ctrl");
308 fatal("_ctrl section missing");
309 if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
310 fatal("out of memory");
312 message.rstart = databuf + 4;
313 message.rend = databuf + sizeof(databuf);
314 DO("render message", isccc_cc_towire(request, &message, &secret));
315 len = sizeof(databuf) - REGION_SIZE(message);
316 isc_buffer_init(&b, databuf, 4);
317 isc_buffer_putuint32(&b, len - 4);
321 isccc_ccmsg_cancelread(&ccmsg);
322 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
323 rndc_recvdone, NULL));
325 DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
329 isc_event_free(&event);
330 isccc_sexpr_free(&response);
335 rndc_connected(isc_task_t *task, isc_event_t *event) {
336 char socktext[ISC_SOCKADDR_FORMATSIZE];
337 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
338 isccc_sexpr_t *request = NULL;
341 isccc_region_t message;
349 if (sevent->result != ISC_R_SUCCESS) {
350 isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
352 if (sevent->result != ISC_R_CANCELED &&
353 ++currentaddr < nserveraddrs)
355 notify("connection failed: %s: %s", socktext,
356 isc_result_totext(sevent->result));
357 isc_socket_detach(&sock);
358 isc_event_free(&event);
359 rndc_startconnect(&serveraddrs[currentaddr], task);
362 fatal("connect failed: %s: %s", socktext,
363 isc_result_totext(sevent->result));
366 isc_stdtime_get(&now);
367 DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
368 now, now + 60, &request));
369 data = isccc_alist_lookup(request, "_data");
371 fatal("_data section missing");
372 if (isccc_cc_definestring(data, "type", "null") == NULL)
373 fatal("out of memory");
374 message.rstart = databuf + 4;
375 message.rend = databuf + sizeof(databuf);
376 DO("render message", isccc_cc_towire(request, &message, &secret));
377 len = sizeof(databuf) - REGION_SIZE(message);
378 isc_buffer_init(&b, databuf, 4);
379 isc_buffer_putuint32(&b, len - 4);
383 isccc_ccmsg_init(mctx, sock, &ccmsg);
384 isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
386 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
387 rndc_recvnonce, NULL));
389 DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
392 isc_event_free(&event);
396 rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
399 isc_sockettype_t type;
401 char socktext[ISC_SOCKADDR_FORMATSIZE];
403 isc_sockaddr_format(addr, socktext, sizeof(socktext));
405 notify("using server %s (%s)", servername, socktext);
407 pf = isc_sockaddr_pf(addr);
408 if (pf == AF_INET || pf == AF_INET6)
409 type = isc_sockettype_tcp;
411 type = isc_sockettype_unix;
412 DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
413 switch (isc_sockaddr_pf(addr)) {
415 DO("bind socket", isc_socket_bind(sock, &local4, 0));
418 DO("bind socket", isc_socket_bind(sock, &local6, 0));
423 DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
429 rndc_start(isc_task_t *task, isc_event_t *event) {
430 isc_event_free(&event);
433 rndc_startconnect(&serveraddrs[currentaddr], task);
437 parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
438 cfg_parser_t **pctxp, cfg_obj_t **configp)
441 const char *conffile = admin_conffile;
442 const cfg_obj_t *addresses = NULL;
443 const cfg_obj_t *defkey = NULL;
444 const cfg_obj_t *options = NULL;
445 const cfg_obj_t *servers = NULL;
446 const cfg_obj_t *server = NULL;
447 const cfg_obj_t *keys = NULL;
448 const cfg_obj_t *key = NULL;
449 const cfg_obj_t *defport = NULL;
450 const cfg_obj_t *secretobj = NULL;
451 const cfg_obj_t *algorithmobj = NULL;
452 cfg_obj_t *config = NULL;
453 const cfg_obj_t *address = NULL;
454 const cfg_listelt_t *elt;
455 const char *secretstr;
456 const char *algorithm;
457 static char secretarray[1024];
458 const cfg_type_t *conftype = &cfg_type_rndcconf;
459 isc_boolean_t key_only = ISC_FALSE;
460 const cfg_listelt_t *element;
462 if (! isc_file_exists(conffile)) {
463 conffile = admin_keyfile;
464 conftype = &cfg_type_rndckey;
466 if (! isc_file_exists(conffile))
467 fatal("neither %s nor %s was found",
468 admin_conffile, admin_keyfile);
470 } else if (! c_flag && isc_file_exists(admin_keyfile)) {
471 fprintf(stderr, "WARNING: key file (%s) exists, but using "
472 "default configuration file (%s)\n",
473 admin_keyfile, admin_conffile);
476 DO("create parser", cfg_parser_create(mctx, log, pctxp));
479 * The parser will output its own errors, so DO() is not used.
481 result = cfg_parse_file(*pctxp, conffile, conftype, &config);
482 if (result != ISC_R_SUCCESS)
483 fatal("could not load rndc configuration");
486 (void)cfg_map_get(config, "options", &options);
488 if (key_only && servername == NULL)
489 servername = "127.0.0.1";
490 else if (servername == NULL && options != NULL) {
491 const cfg_obj_t *defserverobj = NULL;
492 (void)cfg_map_get(options, "default-server", &defserverobj);
493 if (defserverobj != NULL)
494 servername = cfg_obj_asstring(defserverobj);
497 if (servername == NULL)
498 fatal("no server specified and no default");
501 (void)cfg_map_get(config, "server", &servers);
502 if (servers != NULL) {
503 for (elt = cfg_list_first(servers);
505 elt = cfg_list_next(elt))
508 server = cfg_listelt_value(elt);
509 name = cfg_obj_asstring(cfg_map_getname(server));
510 if (strcasecmp(name, servername) == 0)
518 * Look for the name of the key to use.
521 ; /* Was set on command line, do nothing. */
522 else if (server != NULL) {
523 DO("get key for server", cfg_map_get(server, "key", &defkey));
524 keyname = cfg_obj_asstring(defkey);
525 } else if (options != NULL) {
526 DO("get default key", cfg_map_get(options, "default-key",
528 keyname = cfg_obj_asstring(defkey);
529 } else if (!key_only)
530 fatal("no key for server and no default");
533 * Get the key's definition.
536 DO("get key", cfg_map_get(config, "key", &key));
538 DO("get config key list", cfg_map_get(config, "key", &keys));
539 for (elt = cfg_list_first(keys);
541 elt = cfg_list_next(elt))
543 key = cfg_listelt_value(elt);
544 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
549 fatal("no key definition for name %s", keyname);
551 (void)cfg_map_get(key, "secret", &secretobj);
552 (void)cfg_map_get(key, "algorithm", &algorithmobj);
553 if (secretobj == NULL || algorithmobj == NULL)
554 fatal("key must have algorithm and secret");
556 secretstr = cfg_obj_asstring(secretobj);
557 algorithm = cfg_obj_asstring(algorithmobj);
559 if (strcasecmp(algorithm, "hmac-md5") != 0)
560 fatal("unsupported algorithm: %s", algorithm);
562 secret.rstart = (unsigned char *)secretarray;
563 secret.rend = (unsigned char *)secretarray + sizeof(secretarray);
564 DO("decode base64 secret", isccc_base64_decode(secretstr, &secret));
565 secret.rend = secret.rstart;
566 secret.rstart = (unsigned char *)secretarray;
569 * Find the port to connect to.
572 ; /* Was set on command line, do nothing. */
575 (void)cfg_map_get(server, "port", &defport);
576 if (defport == NULL && options != NULL)
577 (void)cfg_map_get(options, "default-port", &defport);
579 if (defport != NULL) {
580 remoteport = cfg_obj_asuint32(defport);
581 if (remoteport > 65535 || remoteport == 0)
582 fatal("port %u out of range", remoteport);
583 } else if (remoteport == 0)
584 remoteport = NS_CONTROL_PORT;
587 result = cfg_map_get(server, "addresses", &addresses);
589 result = ISC_R_NOTFOUND;
590 if (result == ISC_R_SUCCESS) {
591 for (element = cfg_list_first(addresses);
593 element = cfg_list_next(element))
597 address = cfg_listelt_value(element);
598 if (!cfg_obj_issockaddr(address)) {
601 const cfg_obj_t *obj;
603 obj = cfg_tuple_get(address, "name");
604 name = cfg_obj_asstring(obj);
605 obj = cfg_tuple_get(address, "port");
606 if (cfg_obj_isuint32(obj)) {
607 myport = cfg_obj_asuint32(obj);
608 if (myport > ISC_UINT16_MAX ||
610 fatal("port %u out of range",
614 if (nserveraddrs < SERVERADDRS)
615 get_addresses(name, (in_port_t) myport);
617 fprintf(stderr, "too many address: "
618 "%s: dropped\n", name);
621 sa = *cfg_obj_assockaddr(address);
622 if (isc_sockaddr_getport(&sa) == 0)
623 isc_sockaddr_setport(&sa, remoteport);
624 if (nserveraddrs < SERVERADDRS)
625 serveraddrs[nserveraddrs++] = sa;
627 char socktext[ISC_SOCKADDR_FORMATSIZE];
629 isc_sockaddr_format(&sa, socktext,
632 "too many address: %s: dropped\n",
638 if (!local4set && server != NULL) {
640 cfg_map_get(server, "source-address", &address);
641 if (address != NULL) {
642 local4 = *cfg_obj_assockaddr(address);
643 local4set = ISC_TRUE;
646 if (!local4set && options != NULL) {
648 cfg_map_get(options, "default-source-address", &address);
649 if (address != NULL) {
650 local4 = *cfg_obj_assockaddr(address);
651 local4set = ISC_TRUE;
655 if (!local6set && server != NULL) {
657 cfg_map_get(server, "source-address-v6", &address);
658 if (address != NULL) {
659 local6 = *cfg_obj_assockaddr(address);
660 local6set = ISC_TRUE;
663 if (!local6set && options != NULL) {
665 cfg_map_get(options, "default-source-address-v6", &address);
666 if (address != NULL) {
667 local6 = *cfg_obj_assockaddr(address);
668 local6set = ISC_TRUE;
676 main(int argc, char **argv) {
677 isc_boolean_t show_final_mem = ISC_FALSE;
678 isc_result_t result = ISC_R_SUCCESS;
679 isc_taskmgr_t *taskmgr = NULL;
680 isc_task_t *task = NULL;
681 isc_log_t *log = NULL;
682 isc_logconfig_t *logconfig = NULL;
683 isc_logdestination_t logdest;
684 cfg_parser_t *pctx = NULL;
685 cfg_obj_t *config = NULL;
686 const char *keyname = NULL;
694 result = isc_file_progname(*argv, program, sizeof(program));
695 if (result != ISC_R_SUCCESS)
696 memcpy(program, "rndc", 5);
699 admin_conffile = RNDC_CONFFILE;
700 admin_keyfile = RNDC_KEYFILE;
702 isc_sockaddr_any(&local4);
703 isc_sockaddr_any6(&local6);
705 result = isc_app_start();
706 if (result != ISC_R_SUCCESS)
707 fatal("isc_app_start() failed: %s", isc_result_totext(result));
709 isc_commandline_errprint = ISC_FALSE;
711 while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:s:Vy:"))
715 if (inet_pton(AF_INET, isc_commandline_argument,
717 isc_sockaddr_fromin(&local4, &in, 0);
718 local4set = ISC_TRUE;
719 } else if (inet_pton(AF_INET6, isc_commandline_argument,
721 isc_sockaddr_fromin6(&local6, &in6, 0);
722 local6set = ISC_TRUE;
727 admin_conffile = isc_commandline_argument;
732 admin_keyfile = isc_commandline_argument;
736 isc_mem_debugging = ISC_MEM_DEBUGTRACE;
740 show_final_mem = ISC_TRUE;
744 remoteport = atoi(isc_commandline_argument);
745 if (remoteport > 65535 || remoteport == 0)
746 fatal("port '%s' out of range",
747 isc_commandline_argument);
751 servername = isc_commandline_argument;
759 keyname = isc_commandline_argument;
763 if (isc_commandline_option != '?') {
764 fprintf(stderr, "%s: invalid argument -%c\n",
765 program, isc_commandline_option);
772 fprintf(stderr, "%s: unhandled option -%c\n",
773 program, isc_commandline_option);
778 argc -= isc_commandline_index;
779 argv += isc_commandline_index;
784 isc_random_get(&serial);
786 DO("create memory context", isc_mem_create(0, 0, &mctx));
787 DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr));
788 DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr));
789 DO("create task", isc_task_create(taskmgr, 0, &task));
791 DO("create logging context", isc_log_create(mctx, &log, &logconfig));
792 isc_log_setcontext(log);
793 DO("setting log tag", isc_log_settag(logconfig, progname));
794 logdest.file.stream = stderr;
795 logdest.file.name = NULL;
796 logdest.file.versions = ISC_LOG_ROLLNEVER;
797 logdest.file.maximum_size = 0;
798 DO("creating log channel",
799 isc_log_createchannel(logconfig, "stderr",
800 ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
801 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
802 DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
805 parse_config(mctx, log, keyname, &pctx, &config);
807 isccc_result_register();
812 * Convert argc/argv into a space-delimited command string
813 * similar to what the user might enter in interactive mode
814 * (if that were implemented).
817 for (i = 0; i < argc; i++)
818 argslen += strlen(argv[i]) + 1;
820 args = isc_mem_get(mctx, argslen);
822 DO("isc_mem_get", ISC_R_NOMEMORY);
825 for (i = 0; i < argc; i++) {
826 size_t len = strlen(argv[i]);
827 memcpy(p, argv[i], len);
834 INSIST(p == args + argslen);
836 notify("%s", command);
838 if (strcmp(command, "restart") == 0)
839 fatal("'%s' is not implemented", command);
841 if (nserveraddrs == 0)
842 get_addresses(servername, (in_port_t) remoteport);
844 DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL));
846 result = isc_app_run();
847 if (result != ISC_R_SUCCESS)
848 fatal("isc_app_run() failed: %s", isc_result_totext(result));
850 if (connects > 0 || sends > 0 || recvs > 0)
851 isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
853 isc_task_detach(&task);
854 isc_taskmgr_destroy(&taskmgr);
855 isc_socketmgr_destroy(&socketmgr);
856 isc_log_destroy(&log);
857 isc_log_setcontext(NULL);
859 cfg_obj_destroy(pctx, &config);
860 cfg_parser_destroy(&pctx);
862 isc_mem_put(mctx, args, argslen);
863 isccc_ccmsg_invalidate(&ccmsg);
868 isc_mem_stats(mctx, stderr);
870 isc_mem_destroy(&mctx);