2 * Copyright (C) 2004-2006, 2008 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.96.18.17.42.3 2008/07/23 23:16:43 marka 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_mem_t
*mctx
;
83 static int sends
, recvs
, connects
;
86 static char program
[256];
87 static isc_socket_t
*sock
= NULL
;
88 static isc_uint32_t serial
;
90 static void rndc_startconnect(isc_sockaddr_t
*addr
, isc_task_t
*task
);
95 Usage: %s [-c config] [-s server] [-p port]\n\
96 [-k key-file ] [-y key] [-V] command\n\
98 command is one of the following:\n\
100 reload Reload configuration file and zones.\n\
101 reload zone [class [view]]\n\
102 Reload a single zone.\n\
103 refresh zone [class [view]]\n\
104 Schedule immediate maintenance for a zone.\n\
105 retransfer zone [class [view]]\n\
106 Retransfer a single zone without checking serial number.\n\
107 freeze Suspend updates to all dynamic zones.\n\
108 freeze zone [class [view]]\n\
109 Suspend updates to a dynamic zone.\n\
110 thaw Enable updates to all dynamic zones and reload them.\n\
111 thaw zone [class [view]]\n\
112 Enable updates to a frozen dynamic zone and reload it.\n\
113 notify zone [class [view]]\n\
114 Resend NOTIFY messages for the zone.\n\
115 reconfig Reload configuration file and new zones only.\n\
116 stats Write server statistics to the statistics file.\n\
117 querylog Toggle query logging.\n\
118 dumpdb [-all|-cache|-zones] [view ...]\n\
119 Dump cache(s) to the dump file (named_dump.db).\n\
120 stop Save pending updates to master files and stop the server.\n\
121 stop -p Save pending updates to master files and stop the server\n\
122 reporting process id.\n\
123 halt Stop the server without saving pending updates.\n\
124 halt -p Stop the server without saving pending updates reporting\n\
126 trace Increment debugging level by one.\n\
127 trace level Change the debugging level.\n\
128 notrace Set debugging level to 0.\n\
129 flush Flushes all of the server's caches.\n\
130 flush [view] Flushes the server's cache for a view.\n\
131 flushname name [view]\n\
132 Flush the given name from the server's cache(s)\n\
133 status Display status of the server.\n\
134 recursing Dump the queries that are currently recursing (named.recursing)\n\
135 validation newstate [view]\n\
136 Enable / disable DNSSEC validation.\n\
137 *restart Restart the server.\n\
139 * == not yet implemented\n\
147 get_addresses(const char *host
, in_port_t port
) {
149 int found
= 0, count
;
152 result
= isc_sockaddr_frompath(&serveraddrs
[nserveraddrs
],
154 if (result
== ISC_R_SUCCESS
)
157 count
= SERVERADDRS
- nserveraddrs
;
158 result
= bind9_getaddresses(host
, port
,
159 &serveraddrs
[nserveraddrs
],
161 nserveraddrs
+= found
;
163 if (result
!= ISC_R_SUCCESS
)
164 fatal("couldn't get address for '%s': %s",
165 host
, isc_result_totext(result
));
166 INSIST(nserveraddrs
> 0);
170 rndc_senddone(isc_task_t
*task
, isc_event_t
*event
) {
171 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
176 if (sevent
->result
!= ISC_R_SUCCESS
)
177 fatal("send failed: %s", isc_result_totext(sevent
->result
));
178 isc_event_free(&event
);
179 if (sends
== 0 && recvs
== 0) {
180 isc_socket_detach(&sock
);
181 isc_task_shutdown(task
);
182 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS
);
187 rndc_recvdone(isc_task_t
*task
, isc_event_t
*event
) {
188 isccc_sexpr_t
*response
= NULL
;
190 isccc_region_t source
;
191 char *errormsg
= NULL
;
192 char *textmsg
= NULL
;
197 if (ccmsg
.result
== ISC_R_EOF
)
198 fatal("connection to remote host closed\n"
199 "This may indicate that\n"
200 "* the remote server is using an older version of"
201 " the command protocol,\n"
202 "* this host is not authorized to connect,\n"
203 "* the clocks are not syncronized, or\n"
204 "* the key is invalid.");
206 if (ccmsg
.result
!= ISC_R_SUCCESS
)
207 fatal("recv failed: %s", isc_result_totext(ccmsg
.result
));
209 source
.rstart
= isc_buffer_base(&ccmsg
.buffer
);
210 source
.rend
= isc_buffer_used(&ccmsg
.buffer
);
212 DO("parse message", isccc_cc_fromwire(&source
, &response
, &secret
));
214 data
= isccc_alist_lookup(response
, "_data");
216 fatal("no data section in response");
217 result
= isccc_cc_lookupstring(data
, "err", &errormsg
);
218 if (result
== ISC_R_SUCCESS
) {
220 fprintf(stderr
, "%s: '%s' failed: %s\n",
221 progname
, command
, errormsg
);
223 else if (result
!= ISC_R_NOTFOUND
)
224 fprintf(stderr
, "%s: parsing response failed: %s\n",
225 progname
, isc_result_totext(result
));
227 result
= isccc_cc_lookupstring(data
, "text", &textmsg
);
228 if (result
== ISC_R_SUCCESS
)
229 printf("%s\n", textmsg
);
230 else if (result
!= ISC_R_NOTFOUND
)
231 fprintf(stderr
, "%s: parsing response failed: %s\n",
232 progname
, isc_result_totext(result
));
234 isc_event_free(&event
);
235 isccc_sexpr_free(&response
);
236 if (sends
== 0 && recvs
== 0) {
237 isc_socket_detach(&sock
);
238 isc_task_shutdown(task
);
239 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS
);
244 rndc_recvnonce(isc_task_t
*task
, isc_event_t
*event
) {
245 isccc_sexpr_t
*response
= NULL
;
246 isccc_sexpr_t
*_ctrl
;
247 isccc_region_t source
;
250 isccc_sexpr_t
*request
= NULL
;
254 isccc_region_t message
;
260 if (ccmsg
.result
== ISC_R_EOF
)
261 fatal("connection to remote host closed\n"
262 "This may indicate that\n"
263 "* the remote server is using an older version of"
264 " the command protocol,\n"
265 "* this host is not authorized to connect,\n"
266 "* the clocks are not syncronized, or\n"
267 "* the key is invalid.");
269 if (ccmsg
.result
!= ISC_R_SUCCESS
)
270 fatal("recv failed: %s", isc_result_totext(ccmsg
.result
));
272 source
.rstart
= isc_buffer_base(&ccmsg
.buffer
);
273 source
.rend
= isc_buffer_used(&ccmsg
.buffer
);
275 DO("parse message", isccc_cc_fromwire(&source
, &response
, &secret
));
277 _ctrl
= isccc_alist_lookup(response
, "_ctrl");
279 fatal("_ctrl section missing");
281 if (isccc_cc_lookupuint32(_ctrl
, "_nonce", &nonce
) != ISC_R_SUCCESS
)
284 isc_stdtime_get(&now
);
286 DO("create message", isccc_cc_createmessage(1, NULL
, NULL
, ++serial
,
287 now
, now
+ 60, &request
));
288 data
= isccc_alist_lookup(request
, "_data");
290 fatal("_data section missing");
291 if (isccc_cc_definestring(data
, "type", args
) == NULL
)
292 fatal("out of memory");
294 _ctrl
= isccc_alist_lookup(request
, "_ctrl");
296 fatal("_ctrl section missing");
297 if (isccc_cc_defineuint32(_ctrl
, "_nonce", nonce
) == NULL
)
298 fatal("out of memory");
300 message
.rstart
= databuf
+ 4;
301 message
.rend
= databuf
+ sizeof(databuf
);
302 DO("render message", isccc_cc_towire(request
, &message
, &secret
));
303 len
= sizeof(databuf
) - REGION_SIZE(message
);
304 isc_buffer_init(&b
, databuf
, 4);
305 isc_buffer_putuint32(&b
, len
- 4);
309 isccc_ccmsg_cancelread(&ccmsg
);
310 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg
, task
,
311 rndc_recvdone
, NULL
));
313 DO("send message", isc_socket_send(sock
, &r
, task
, rndc_senddone
,
317 isc_event_free(&event
);
318 isccc_sexpr_free(&response
);
323 rndc_connected(isc_task_t
*task
, isc_event_t
*event
) {
324 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
325 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
326 isccc_sexpr_t
*request
= NULL
;
329 isccc_region_t message
;
337 if (sevent
->result
!= ISC_R_SUCCESS
) {
338 isc_sockaddr_format(&serveraddrs
[currentaddr
], socktext
,
340 if (sevent
->result
!= ISC_R_CANCELED
&&
341 ++currentaddr
< nserveraddrs
)
343 notify("connection failed: %s: %s", socktext
,
344 isc_result_totext(sevent
->result
));
345 isc_socket_detach(&sock
);
346 isc_event_free(&event
);
347 rndc_startconnect(&serveraddrs
[currentaddr
], task
);
350 fatal("connect failed: %s: %s", socktext
,
351 isc_result_totext(sevent
->result
));
354 isc_stdtime_get(&now
);
355 DO("create message", isccc_cc_createmessage(1, NULL
, NULL
, ++serial
,
356 now
, now
+ 60, &request
));
357 data
= isccc_alist_lookup(request
, "_data");
359 fatal("_data section missing");
360 if (isccc_cc_definestring(data
, "type", "null") == NULL
)
361 fatal("out of memory");
362 message
.rstart
= databuf
+ 4;
363 message
.rend
= databuf
+ sizeof(databuf
);
364 DO("render message", isccc_cc_towire(request
, &message
, &secret
));
365 len
= sizeof(databuf
) - REGION_SIZE(message
);
366 isc_buffer_init(&b
, databuf
, 4);
367 isc_buffer_putuint32(&b
, len
- 4);
371 isccc_ccmsg_init(mctx
, sock
, &ccmsg
);
372 isccc_ccmsg_setmaxsize(&ccmsg
, 1024);
374 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg
, task
,
375 rndc_recvnonce
, NULL
));
377 DO("send message", isc_socket_send(sock
, &r
, task
, rndc_senddone
,
380 isc_event_free(&event
);
384 rndc_startconnect(isc_sockaddr_t
*addr
, isc_task_t
*task
) {
387 isc_sockettype_t type
;
389 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
391 isc_sockaddr_format(addr
, socktext
, sizeof(socktext
));
393 notify("using server %s (%s)", servername
, socktext
);
395 pf
= isc_sockaddr_pf(addr
);
396 if (pf
== AF_INET
|| pf
== AF_INET6
)
397 type
= isc_sockettype_tcp
;
399 type
= isc_sockettype_unix
;
400 DO("create socket", isc_socket_create(socketmgr
, pf
, type
, &sock
));
401 switch (isc_sockaddr_pf(addr
)) {
403 DO("bind socket", isc_socket_bind(sock
, &local4
, 0));
406 DO("bind socket", isc_socket_bind(sock
, &local6
, 0));
411 DO("connect", isc_socket_connect(sock
, addr
, task
, rndc_connected
,
417 rndc_start(isc_task_t
*task
, isc_event_t
*event
) {
418 isc_event_free(&event
);
421 rndc_startconnect(&serveraddrs
[currentaddr
], task
);
425 parse_config(isc_mem_t
*mctx
, isc_log_t
*log
, const char *keyname
,
426 cfg_parser_t
**pctxp
, cfg_obj_t
**configp
)
429 const char *conffile
= admin_conffile
;
430 const cfg_obj_t
*addresses
= NULL
;
431 const cfg_obj_t
*defkey
= NULL
;
432 const cfg_obj_t
*options
= NULL
;
433 const cfg_obj_t
*servers
= NULL
;
434 const cfg_obj_t
*server
= NULL
;
435 const cfg_obj_t
*keys
= NULL
;
436 const cfg_obj_t
*key
= NULL
;
437 const cfg_obj_t
*defport
= NULL
;
438 const cfg_obj_t
*secretobj
= NULL
;
439 const cfg_obj_t
*algorithmobj
= NULL
;
440 cfg_obj_t
*config
= NULL
;
441 const cfg_obj_t
*address
= NULL
;
442 const cfg_listelt_t
*elt
;
443 const char *secretstr
;
444 const char *algorithm
;
445 static char secretarray
[1024];
446 const cfg_type_t
*conftype
= &cfg_type_rndcconf
;
447 isc_boolean_t key_only
= ISC_FALSE
;
448 const cfg_listelt_t
*element
;
450 if (! isc_file_exists(conffile
)) {
451 conffile
= admin_keyfile
;
452 conftype
= &cfg_type_rndckey
;
454 if (! isc_file_exists(conffile
))
455 fatal("neither %s nor %s was found",
456 admin_conffile
, admin_keyfile
);
460 DO("create parser", cfg_parser_create(mctx
, log
, pctxp
));
463 * The parser will output its own errors, so DO() is not used.
465 result
= cfg_parse_file(*pctxp
, conffile
, conftype
, &config
);
466 if (result
!= ISC_R_SUCCESS
)
467 fatal("could not load rndc configuration");
470 (void)cfg_map_get(config
, "options", &options
);
472 if (key_only
&& servername
== NULL
)
473 servername
= "127.0.0.1";
474 else if (servername
== NULL
&& options
!= NULL
) {
475 const cfg_obj_t
*defserverobj
= NULL
;
476 (void)cfg_map_get(options
, "default-server", &defserverobj
);
477 if (defserverobj
!= NULL
)
478 servername
= cfg_obj_asstring(defserverobj
);
481 if (servername
== NULL
)
482 fatal("no server specified and no default");
485 (void)cfg_map_get(config
, "server", &servers
);
486 if (servers
!= NULL
) {
487 for (elt
= cfg_list_first(servers
);
489 elt
= cfg_list_next(elt
))
492 server
= cfg_listelt_value(elt
);
493 name
= cfg_obj_asstring(cfg_map_getname(server
));
494 if (strcasecmp(name
, servername
) == 0)
502 * Look for the name of the key to use.
505 ; /* Was set on command line, do nothing. */
506 else if (server
!= NULL
) {
507 DO("get key for server", cfg_map_get(server
, "key", &defkey
));
508 keyname
= cfg_obj_asstring(defkey
);
509 } else if (options
!= NULL
) {
510 DO("get default key", cfg_map_get(options
, "default-key",
512 keyname
= cfg_obj_asstring(defkey
);
513 } else if (!key_only
)
514 fatal("no key for server and no default");
517 * Get the key's definition.
520 DO("get key", cfg_map_get(config
, "key", &key
));
522 DO("get config key list", cfg_map_get(config
, "key", &keys
));
523 for (elt
= cfg_list_first(keys
);
525 elt
= cfg_list_next(elt
))
527 key
= cfg_listelt_value(elt
);
528 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key
)),
533 fatal("no key definition for name %s", keyname
);
535 (void)cfg_map_get(key
, "secret", &secretobj
);
536 (void)cfg_map_get(key
, "algorithm", &algorithmobj
);
537 if (secretobj
== NULL
|| algorithmobj
== NULL
)
538 fatal("key must have algorithm and secret");
540 secretstr
= cfg_obj_asstring(secretobj
);
541 algorithm
= cfg_obj_asstring(algorithmobj
);
543 if (strcasecmp(algorithm
, "hmac-md5") != 0)
544 fatal("unsupported algorithm: %s", algorithm
);
546 secret
.rstart
= (unsigned char *)secretarray
;
547 secret
.rend
= (unsigned char *)secretarray
+ sizeof(secretarray
);
548 DO("decode base64 secret", isccc_base64_decode(secretstr
, &secret
));
549 secret
.rend
= secret
.rstart
;
550 secret
.rstart
= (unsigned char *)secretarray
;
553 * Find the port to connect to.
556 ; /* Was set on command line, do nothing. */
559 (void)cfg_map_get(server
, "port", &defport
);
560 if (defport
== NULL
&& options
!= NULL
)
561 (void)cfg_map_get(options
, "default-port", &defport
);
563 if (defport
!= NULL
) {
564 remoteport
= cfg_obj_asuint32(defport
);
565 if (remoteport
> 65535 || remoteport
== 0)
566 fatal("port %u out of range", remoteport
);
567 } else if (remoteport
== 0)
568 remoteport
= NS_CONTROL_PORT
;
571 result
= cfg_map_get(server
, "addresses", &addresses
);
573 result
= ISC_R_NOTFOUND
;
574 if (result
== ISC_R_SUCCESS
) {
575 for (element
= cfg_list_first(addresses
);
577 element
= cfg_list_next(element
))
581 address
= cfg_listelt_value(element
);
582 if (!cfg_obj_issockaddr(address
)) {
585 const cfg_obj_t
*obj
;
587 obj
= cfg_tuple_get(address
, "name");
588 name
= cfg_obj_asstring(obj
);
589 obj
= cfg_tuple_get(address
, "port");
590 if (cfg_obj_isuint32(obj
)) {
591 myport
= cfg_obj_asuint32(obj
);
592 if (myport
> ISC_UINT16_MAX
||
594 fatal("port %u out of range",
598 if (nserveraddrs
< SERVERADDRS
)
599 get_addresses(name
, (in_port_t
) myport
);
601 fprintf(stderr
, "too many address: "
602 "%s: dropped\n", name
);
605 sa
= *cfg_obj_assockaddr(address
);
606 if (isc_sockaddr_getport(&sa
) == 0)
607 isc_sockaddr_setport(&sa
, remoteport
);
608 if (nserveraddrs
< SERVERADDRS
)
609 serveraddrs
[nserveraddrs
++] = sa
;
611 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
613 isc_sockaddr_format(&sa
, socktext
,
616 "too many address: %s: dropped\n",
622 if (!local4set
&& server
!= NULL
) {
624 cfg_map_get(server
, "source-address", &address
);
625 if (address
!= NULL
) {
626 local4
= *cfg_obj_assockaddr(address
);
627 local4set
= ISC_TRUE
;
630 if (!local4set
&& options
!= NULL
) {
632 cfg_map_get(options
, "default-source-address", &address
);
633 if (address
!= NULL
) {
634 local4
= *cfg_obj_assockaddr(address
);
635 local4set
= ISC_TRUE
;
639 if (!local6set
&& server
!= NULL
) {
641 cfg_map_get(server
, "source-address-v6", &address
);
642 if (address
!= NULL
) {
643 local6
= *cfg_obj_assockaddr(address
);
644 local6set
= ISC_TRUE
;
647 if (!local6set
&& options
!= NULL
) {
649 cfg_map_get(options
, "default-source-address-v6", &address
);
650 if (address
!= NULL
) {
651 local6
= *cfg_obj_assockaddr(address
);
652 local6set
= ISC_TRUE
;
660 main(int argc
, char **argv
) {
661 isc_boolean_t show_final_mem
= ISC_FALSE
;
662 isc_result_t result
= ISC_R_SUCCESS
;
663 isc_taskmgr_t
*taskmgr
= NULL
;
664 isc_task_t
*task
= NULL
;
665 isc_log_t
*log
= NULL
;
666 isc_logconfig_t
*logconfig
= NULL
;
667 isc_logdestination_t logdest
;
668 cfg_parser_t
*pctx
= NULL
;
669 cfg_obj_t
*config
= NULL
;
670 const char *keyname
= NULL
;
678 result
= isc_file_progname(*argv
, program
, sizeof(program
));
679 if (result
!= ISC_R_SUCCESS
)
680 memcpy(program
, "rndc", 5);
683 admin_conffile
= RNDC_CONFFILE
;
684 admin_keyfile
= RNDC_KEYFILE
;
686 isc_sockaddr_any(&local4
);
687 isc_sockaddr_any6(&local6
);
689 result
= isc_app_start();
690 if (result
!= ISC_R_SUCCESS
)
691 fatal("isc_app_start() failed: %s", isc_result_totext(result
));
693 while ((ch
= isc_commandline_parse(argc
, argv
, "b:c:k:Mmp:s:Vy:"))
697 if (inet_pton(AF_INET
, isc_commandline_argument
,
699 isc_sockaddr_fromin(&local4
, &in
, 0);
700 local4set
= ISC_TRUE
;
701 } else if (inet_pton(AF_INET6
, isc_commandline_argument
,
703 isc_sockaddr_fromin6(&local6
, &in6
, 0);
704 local6set
= ISC_TRUE
;
709 admin_conffile
= isc_commandline_argument
;
713 admin_keyfile
= isc_commandline_argument
;
717 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
;
721 show_final_mem
= ISC_TRUE
;
725 remoteport
= atoi(isc_commandline_argument
);
726 if (remoteport
> 65535 || remoteport
== 0)
727 fatal("port '%s' out of range",
728 isc_commandline_argument
);
732 servername
= isc_commandline_argument
;
740 keyname
= isc_commandline_argument
;
748 fatal("unexpected error parsing command arguments: "
754 argc
-= isc_commandline_index
;
755 argv
+= isc_commandline_index
;
760 isc_random_get(&serial
);
762 DO("create memory context", isc_mem_create(0, 0, &mctx
));
763 DO("create socket manager", isc_socketmgr_create(mctx
, &socketmgr
));
764 DO("create task manager", isc_taskmgr_create(mctx
, 1, 0, &taskmgr
));
765 DO("create task", isc_task_create(taskmgr
, 0, &task
));
767 DO("create logging context", isc_log_create(mctx
, &log
, &logconfig
));
768 isc_log_setcontext(log
);
769 DO("setting log tag", isc_log_settag(logconfig
, progname
));
770 logdest
.file
.stream
= stderr
;
771 logdest
.file
.name
= NULL
;
772 logdest
.file
.versions
= ISC_LOG_ROLLNEVER
;
773 logdest
.file
.maximum_size
= 0;
774 DO("creating log channel",
775 isc_log_createchannel(logconfig
, "stderr",
776 ISC_LOG_TOFILEDESC
, ISC_LOG_INFO
, &logdest
,
777 ISC_LOG_PRINTTAG
|ISC_LOG_PRINTLEVEL
));
778 DO("enabling log channel", isc_log_usechannel(logconfig
, "stderr",
781 parse_config(mctx
, log
, keyname
, &pctx
, &config
);
783 isccc_result_register();
788 * Convert argc/argv into a space-delimited command string
789 * similar to what the user might enter in interactive mode
790 * (if that were implemented).
793 for (i
= 0; i
< argc
; i
++)
794 argslen
+= strlen(argv
[i
]) + 1;
796 args
= isc_mem_get(mctx
, argslen
);
798 DO("isc_mem_get", ISC_R_NOMEMORY
);
801 for (i
= 0; i
< argc
; i
++) {
802 size_t len
= strlen(argv
[i
]);
803 memcpy(p
, argv
[i
], len
);
810 INSIST(p
== args
+ argslen
);
812 notify("%s", command
);
814 if (strcmp(command
, "restart") == 0)
815 fatal("'%s' is not implemented", command
);
817 if (nserveraddrs
== 0)
818 get_addresses(servername
, (in_port_t
) remoteport
);
820 DO("post event", isc_app_onrun(mctx
, task
, rndc_start
, NULL
));
822 result
= isc_app_run();
823 if (result
!= ISC_R_SUCCESS
)
824 fatal("isc_app_run() failed: %s", isc_result_totext(result
));
826 if (connects
> 0 || sends
> 0 || recvs
> 0)
827 isc_socket_cancel(sock
, task
, ISC_SOCKCANCEL_ALL
);
829 isc_task_detach(&task
);
830 isc_taskmgr_destroy(&taskmgr
);
831 isc_socketmgr_destroy(&socketmgr
);
832 isc_log_destroy(&log
);
833 isc_log_setcontext(NULL
);
835 cfg_obj_destroy(pctx
, &config
);
836 cfg_parser_destroy(&pctx
);
838 isc_mem_put(mctx
, args
, argslen
);
839 isccc_ccmsg_invalidate(&ccmsg
);
844 isc_mem_stats(mctx
, stderr
);
846 isc_mem_destroy(&mctx
);