4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: rndc.c,v 1.126 2009/09/29 15:06:06 fdupont Exp */
25 * Principal Author: DCL
33 #include <isc/buffer.h>
34 #include <isc/commandline.h>
39 #include <isc/random.h>
40 #include <isc/socket.h>
41 #include <isc/stdtime.h>
42 #include <isc/string.h>
44 #include <isc/thread.h>
47 #include <isccfg/namedconf.h>
49 #include <isccc/alist.h>
50 #include <isccc/base64.h>
52 #include <isccc/ccmsg.h>
53 #include <isccc/result.h>
54 #include <isccc/sexpr.h>
55 #include <isccc/types.h>
56 #include <isccc/util.h>
60 #include <bind9/getaddresses.h>
64 #define SERVERADDRS 10
67 isc_boolean_t verbose
;
69 static const char *admin_conffile
;
70 static const char *admin_keyfile
;
71 static const char *version
= VERSION
;
72 static const char *servername
= NULL
;
73 static isc_sockaddr_t serveraddrs
[SERVERADDRS
];
74 static isc_sockaddr_t local4
, local6
;
75 static isc_boolean_t local4set
= ISC_FALSE
, local6set
= ISC_FALSE
;
76 static int nserveraddrs
;
77 static int currentaddr
= 0;
78 static unsigned int remoteport
= 0;
79 static isc_socketmgr_t
*socketmgr
= NULL
;
80 static unsigned char databuf
[2048];
81 static isccc_ccmsg_t ccmsg
;
82 static isccc_region_t secret
;
83 static isc_boolean_t failed
= ISC_FALSE
;
84 static isc_boolean_t c_flag
= ISC_FALSE
;
85 static isc_mem_t
*mctx
;
86 static int sends
, recvs
, connects
;
89 static char program
[256];
90 static isc_socket_t
*sock
= NULL
;
91 static isc_uint32_t serial
;
93 static void rndc_startconnect(isc_sockaddr_t
*addr
, isc_task_t
*task
);
95 ISC_PLATFORM_NORETURN_PRE
static void
96 usage(int status
) ISC_PLATFORM_NORETURN_POST
;
101 Usage: %s [-c config] [-s server] [-p port]\n\
102 [-k key-file ] [-y key] [-V] command\n\
104 command is one of the following:\n\
106 reload Reload configuration file and zones.\n\
107 reload zone [class [view]]\n\
108 Reload a single zone.\n\
109 refresh zone [class [view]]\n\
110 Schedule immediate maintenance for a zone.\n\
111 retransfer zone [class [view]]\n\
112 Retransfer a single zone without checking serial number.\n\
113 freeze Suspend updates to all dynamic zones.\n\
114 freeze zone [class [view]]\n\
115 Suspend updates to a dynamic zone.\n\
116 thaw Enable updates to all dynamic zones and reload them.\n\
117 thaw zone [class [view]]\n\
118 Enable updates to a frozen dynamic zone and reload it.\n\
119 notify zone [class [view]]\n\
120 Resend NOTIFY messages for the zone.\n\
121 reconfig Reload configuration file and new zones only.\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 stop Save pending updates to master files and stop the server.\n\
127 stop -p Save pending updates to master files and stop the server\n\
128 reporting process id.\n\
129 halt Stop the server without saving pending updates.\n\
130 halt -p Stop the server without saving pending updates reporting\n\
132 trace Increment debugging level by one.\n\
133 trace level Change the debugging level.\n\
134 notrace Set debugging level to 0.\n\
135 flush Flushes all of the server's caches.\n\
136 flush [view] Flushes the server's cache for a view.\n\
137 flushname name [view]\n\
138 Flush the given name from the server's cache(s)\n\
139 status Display status of the server.\n\
140 recursing Dump the queries that are currently recursing (named.recursing)\n\
141 validation newstate [view]\n\
142 Enable / disable DNSSEC validation.\n\
143 *restart Restart the server.\n\
145 * == not yet implemented\n\
153 get_addresses(const char *host
, in_port_t port
) {
155 int found
= 0, count
;
158 result
= isc_sockaddr_frompath(&serveraddrs
[nserveraddrs
],
160 if (result
== ISC_R_SUCCESS
)
163 count
= SERVERADDRS
- nserveraddrs
;
164 result
= bind9_getaddresses(host
, port
,
165 &serveraddrs
[nserveraddrs
],
167 nserveraddrs
+= found
;
169 if (result
!= ISC_R_SUCCESS
)
170 fatal("couldn't get address for '%s': %s",
171 host
, isc_result_totext(result
));
172 INSIST(nserveraddrs
> 0);
176 rndc_senddone(isc_task_t
*task
, isc_event_t
*event
) {
177 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
182 if (sevent
->result
!= ISC_R_SUCCESS
)
183 fatal("send failed: %s", isc_result_totext(sevent
->result
));
184 isc_event_free(&event
);
185 if (sends
== 0 && recvs
== 0) {
186 isc_socket_detach(&sock
);
187 isc_task_shutdown(task
);
188 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS
);
193 rndc_recvdone(isc_task_t
*task
, isc_event_t
*event
) {
194 isccc_sexpr_t
*response
= NULL
;
196 isccc_region_t source
;
197 char *errormsg
= NULL
;
198 char *textmsg
= NULL
;
203 if (ccmsg
.result
== ISC_R_EOF
)
204 fatal("connection to remote host closed\n"
205 "This may indicate that\n"
206 "* the remote server is using an older version of"
207 " the command protocol,\n"
208 "* this host is not authorized to connect,\n"
209 "* the clocks are not synchronized, or\n"
210 "* the key is invalid.");
212 if (ccmsg
.result
!= ISC_R_SUCCESS
)
213 fatal("recv failed: %s", isc_result_totext(ccmsg
.result
));
215 source
.rstart
= isc_buffer_base(&ccmsg
.buffer
);
216 source
.rend
= isc_buffer_used(&ccmsg
.buffer
);
218 DO("parse message", isccc_cc_fromwire(&source
, &response
, &secret
));
220 data
= isccc_alist_lookup(response
, "_data");
222 fatal("no data section in response");
223 result
= isccc_cc_lookupstring(data
, "err", &errormsg
);
224 if (result
== ISC_R_SUCCESS
) {
226 fprintf(stderr
, "%s: '%s' failed: %s\n",
227 progname
, command
, errormsg
);
229 else if (result
!= ISC_R_NOTFOUND
)
230 fprintf(stderr
, "%s: parsing response failed: %s\n",
231 progname
, isc_result_totext(result
));
233 result
= isccc_cc_lookupstring(data
, "text", &textmsg
);
234 if (result
== ISC_R_SUCCESS
)
235 printf("%s\n", textmsg
);
236 else if (result
!= ISC_R_NOTFOUND
)
237 fprintf(stderr
, "%s: parsing response failed: %s\n",
238 progname
, isc_result_totext(result
));
240 isc_event_free(&event
);
241 isccc_sexpr_free(&response
);
242 if (sends
== 0 && recvs
== 0) {
243 isc_socket_detach(&sock
);
244 isc_task_shutdown(task
);
245 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS
);
250 rndc_recvnonce(isc_task_t
*task
, isc_event_t
*event
) {
251 isccc_sexpr_t
*response
= NULL
;
252 isccc_sexpr_t
*_ctrl
;
253 isccc_region_t source
;
256 isccc_sexpr_t
*request
= NULL
;
260 isccc_region_t message
;
266 if (ccmsg
.result
== ISC_R_EOF
)
267 fatal("connection to remote host closed\n"
268 "This may indicate that\n"
269 "* the remote server is using an older version of"
270 " the command protocol,\n"
271 "* this host is not authorized to connect,\n"
272 "* the clocks are not synchronized, or\n"
273 "* the key is invalid.");
275 if (ccmsg
.result
!= ISC_R_SUCCESS
)
276 fatal("recv failed: %s", isc_result_totext(ccmsg
.result
));
278 source
.rstart
= isc_buffer_base(&ccmsg
.buffer
);
279 source
.rend
= isc_buffer_used(&ccmsg
.buffer
);
281 DO("parse message", isccc_cc_fromwire(&source
, &response
, &secret
));
283 _ctrl
= isccc_alist_lookup(response
, "_ctrl");
285 fatal("_ctrl section missing");
287 if (isccc_cc_lookupuint32(_ctrl
, "_nonce", &nonce
) != ISC_R_SUCCESS
)
290 isc_stdtime_get(&now
);
292 DO("create message", isccc_cc_createmessage(1, NULL
, NULL
, ++serial
,
293 now
, now
+ 60, &request
));
294 data
= isccc_alist_lookup(request
, "_data");
296 fatal("_data section missing");
297 if (isccc_cc_definestring(data
, "type", args
) == NULL
)
298 fatal("out of memory");
300 _ctrl
= isccc_alist_lookup(request
, "_ctrl");
302 fatal("_ctrl section missing");
303 if (isccc_cc_defineuint32(_ctrl
, "_nonce", nonce
) == NULL
)
304 fatal("out of memory");
306 message
.rstart
= databuf
+ 4;
307 message
.rend
= databuf
+ sizeof(databuf
);
308 DO("render message", isccc_cc_towire(request
, &message
, &secret
));
309 len
= sizeof(databuf
) - REGION_SIZE(message
);
310 isc_buffer_init(&b
, databuf
, 4);
311 isc_buffer_putuint32(&b
, len
- 4);
315 isccc_ccmsg_cancelread(&ccmsg
);
316 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg
, task
,
317 rndc_recvdone
, NULL
));
319 DO("send message", isc_socket_send(sock
, &r
, task
, rndc_senddone
,
323 isc_event_free(&event
);
324 isccc_sexpr_free(&response
);
329 rndc_connected(isc_task_t
*task
, isc_event_t
*event
) {
330 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
331 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
332 isccc_sexpr_t
*request
= NULL
;
335 isccc_region_t message
;
343 if (sevent
->result
!= ISC_R_SUCCESS
) {
344 isc_sockaddr_format(&serveraddrs
[currentaddr
], socktext
,
346 if (sevent
->result
!= ISC_R_CANCELED
&&
347 ++currentaddr
< nserveraddrs
)
349 notify("connection failed: %s: %s", socktext
,
350 isc_result_totext(sevent
->result
));
351 isc_socket_detach(&sock
);
352 isc_event_free(&event
);
353 rndc_startconnect(&serveraddrs
[currentaddr
], task
);
356 fatal("connect failed: %s: %s", socktext
,
357 isc_result_totext(sevent
->result
));
360 isc_stdtime_get(&now
);
361 DO("create message", isccc_cc_createmessage(1, NULL
, NULL
, ++serial
,
362 now
, now
+ 60, &request
));
363 data
= isccc_alist_lookup(request
, "_data");
365 fatal("_data section missing");
366 if (isccc_cc_definestring(data
, "type", "null") == NULL
)
367 fatal("out of memory");
368 message
.rstart
= databuf
+ 4;
369 message
.rend
= databuf
+ sizeof(databuf
);
370 DO("render message", isccc_cc_towire(request
, &message
, &secret
));
371 len
= sizeof(databuf
) - REGION_SIZE(message
);
372 isc_buffer_init(&b
, databuf
, 4);
373 isc_buffer_putuint32(&b
, len
- 4);
377 isccc_ccmsg_init(mctx
, sock
, &ccmsg
);
378 isccc_ccmsg_setmaxsize(&ccmsg
, 1024 * 1024);
380 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg
, task
,
381 rndc_recvnonce
, NULL
));
383 DO("send message", isc_socket_send(sock
, &r
, task
, rndc_senddone
,
386 isc_event_free(&event
);
390 rndc_startconnect(isc_sockaddr_t
*addr
, isc_task_t
*task
) {
393 isc_sockettype_t type
;
395 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
397 isc_sockaddr_format(addr
, socktext
, sizeof(socktext
));
399 notify("using server %s (%s)", servername
, socktext
);
401 pf
= isc_sockaddr_pf(addr
);
402 if (pf
== AF_INET
|| pf
== AF_INET6
)
403 type
= isc_sockettype_tcp
;
405 type
= isc_sockettype_unix
;
406 DO("create socket", isc_socket_create(socketmgr
, pf
, type
, &sock
));
407 switch (isc_sockaddr_pf(addr
)) {
409 DO("bind socket", isc_socket_bind(sock
, &local4
, 0));
412 DO("bind socket", isc_socket_bind(sock
, &local6
, 0));
417 DO("connect", isc_socket_connect(sock
, addr
, task
, rndc_connected
,
423 rndc_start(isc_task_t
*task
, isc_event_t
*event
) {
424 isc_event_free(&event
);
427 rndc_startconnect(&serveraddrs
[currentaddr
], task
);
431 parse_config(isc_mem_t
*mctx
, isc_log_t
*log
, const char *keyname
,
432 cfg_parser_t
**pctxp
, cfg_obj_t
**configp
)
435 const char *conffile
= admin_conffile
;
436 const cfg_obj_t
*addresses
= NULL
;
437 const cfg_obj_t
*defkey
= NULL
;
438 const cfg_obj_t
*options
= NULL
;
439 const cfg_obj_t
*servers
= NULL
;
440 const cfg_obj_t
*server
= NULL
;
441 const cfg_obj_t
*keys
= NULL
;
442 const cfg_obj_t
*key
= NULL
;
443 const cfg_obj_t
*defport
= NULL
;
444 const cfg_obj_t
*secretobj
= NULL
;
445 const cfg_obj_t
*algorithmobj
= NULL
;
446 cfg_obj_t
*config
= NULL
;
447 const cfg_obj_t
*address
= NULL
;
448 const cfg_listelt_t
*elt
;
449 const char *secretstr
;
450 const char *algorithm
;
451 static char secretarray
[1024];
452 const cfg_type_t
*conftype
= &cfg_type_rndcconf
;
453 isc_boolean_t key_only
= ISC_FALSE
;
454 const cfg_listelt_t
*element
;
456 if (! isc_file_exists(conffile
)) {
457 conffile
= admin_keyfile
;
458 conftype
= &cfg_type_rndckey
;
460 if (! isc_file_exists(conffile
))
461 fatal("neither %s nor %s was found",
462 admin_conffile
, admin_keyfile
);
464 } else if (! c_flag
&& isc_file_exists(admin_keyfile
)) {
465 fprintf(stderr
, "WARNING: key file (%s) exists, but using "
466 "default configuration file (%s)\n",
467 admin_keyfile
, admin_conffile
);
470 DO("create parser", cfg_parser_create(mctx
, log
, pctxp
));
473 * The parser will output its own errors, so DO() is not used.
475 result
= cfg_parse_file(*pctxp
, conffile
, conftype
, &config
);
476 if (result
!= ISC_R_SUCCESS
)
477 fatal("could not load rndc configuration");
480 (void)cfg_map_get(config
, "options", &options
);
482 if (key_only
&& servername
== NULL
)
483 servername
= "127.0.0.1";
484 else if (servername
== NULL
&& options
!= NULL
) {
485 const cfg_obj_t
*defserverobj
= NULL
;
486 (void)cfg_map_get(options
, "default-server", &defserverobj
);
487 if (defserverobj
!= NULL
)
488 servername
= cfg_obj_asstring(defserverobj
);
491 if (servername
== NULL
)
492 fatal("no server specified and no default");
495 (void)cfg_map_get(config
, "server", &servers
);
496 if (servers
!= NULL
) {
497 for (elt
= cfg_list_first(servers
);
499 elt
= cfg_list_next(elt
))
502 server
= cfg_listelt_value(elt
);
503 name
= cfg_obj_asstring(cfg_map_getname(server
));
504 if (strcasecmp(name
, servername
) == 0)
512 * Look for the name of the key to use.
515 ; /* Was set on command line, do nothing. */
516 else if (server
!= NULL
) {
517 DO("get key for server", cfg_map_get(server
, "key", &defkey
));
518 keyname
= cfg_obj_asstring(defkey
);
519 } else if (options
!= NULL
) {
520 DO("get default key", cfg_map_get(options
, "default-key",
522 keyname
= cfg_obj_asstring(defkey
);
523 } else if (!key_only
)
524 fatal("no key for server and no default");
527 * Get the key's definition.
530 DO("get key", cfg_map_get(config
, "key", &key
));
532 DO("get config key list", cfg_map_get(config
, "key", &keys
));
533 for (elt
= cfg_list_first(keys
);
535 elt
= cfg_list_next(elt
))
537 key
= cfg_listelt_value(elt
);
538 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key
)),
543 fatal("no key definition for name %s", keyname
);
545 (void)cfg_map_get(key
, "secret", &secretobj
);
546 (void)cfg_map_get(key
, "algorithm", &algorithmobj
);
547 if (secretobj
== NULL
|| algorithmobj
== NULL
)
548 fatal("key must have algorithm and secret");
550 secretstr
= cfg_obj_asstring(secretobj
);
551 algorithm
= cfg_obj_asstring(algorithmobj
);
553 if (strcasecmp(algorithm
, "hmac-md5") != 0)
554 fatal("unsupported algorithm: %s", algorithm
);
556 secret
.rstart
= (unsigned char *)secretarray
;
557 secret
.rend
= (unsigned char *)secretarray
+ sizeof(secretarray
);
558 DO("decode base64 secret", isccc_base64_decode(secretstr
, &secret
));
559 secret
.rend
= secret
.rstart
;
560 secret
.rstart
= (unsigned char *)secretarray
;
563 * Find the port to connect to.
566 ; /* Was set on command line, do nothing. */
569 (void)cfg_map_get(server
, "port", &defport
);
570 if (defport
== NULL
&& options
!= NULL
)
571 (void)cfg_map_get(options
, "default-port", &defport
);
573 if (defport
!= NULL
) {
574 remoteport
= cfg_obj_asuint32(defport
);
575 if (remoteport
> 65535 || remoteport
== 0)
576 fatal("port %u out of range", remoteport
);
577 } else if (remoteport
== 0)
578 remoteport
= NS_CONTROL_PORT
;
581 result
= cfg_map_get(server
, "addresses", &addresses
);
583 result
= ISC_R_NOTFOUND
;
584 if (result
== ISC_R_SUCCESS
) {
585 for (element
= cfg_list_first(addresses
);
587 element
= cfg_list_next(element
))
591 address
= cfg_listelt_value(element
);
592 if (!cfg_obj_issockaddr(address
)) {
595 const cfg_obj_t
*obj
;
597 obj
= cfg_tuple_get(address
, "name");
598 name
= cfg_obj_asstring(obj
);
599 obj
= cfg_tuple_get(address
, "port");
600 if (cfg_obj_isuint32(obj
)) {
601 myport
= cfg_obj_asuint32(obj
);
602 if (myport
> ISC_UINT16_MAX
||
604 fatal("port %u out of range",
608 if (nserveraddrs
< SERVERADDRS
)
609 get_addresses(name
, (in_port_t
) myport
);
611 fprintf(stderr
, "too many address: "
612 "%s: dropped\n", name
);
615 sa
= *cfg_obj_assockaddr(address
);
616 if (isc_sockaddr_getport(&sa
) == 0)
617 isc_sockaddr_setport(&sa
, remoteport
);
618 if (nserveraddrs
< SERVERADDRS
)
619 serveraddrs
[nserveraddrs
++] = sa
;
621 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
623 isc_sockaddr_format(&sa
, socktext
,
626 "too many address: %s: dropped\n",
632 if (!local4set
&& server
!= NULL
) {
634 cfg_map_get(server
, "source-address", &address
);
635 if (address
!= NULL
) {
636 local4
= *cfg_obj_assockaddr(address
);
637 local4set
= ISC_TRUE
;
640 if (!local4set
&& options
!= NULL
) {
642 cfg_map_get(options
, "default-source-address", &address
);
643 if (address
!= NULL
) {
644 local4
= *cfg_obj_assockaddr(address
);
645 local4set
= ISC_TRUE
;
649 if (!local6set
&& server
!= NULL
) {
651 cfg_map_get(server
, "source-address-v6", &address
);
652 if (address
!= NULL
) {
653 local6
= *cfg_obj_assockaddr(address
);
654 local6set
= ISC_TRUE
;
657 if (!local6set
&& options
!= NULL
) {
659 cfg_map_get(options
, "default-source-address-v6", &address
);
660 if (address
!= NULL
) {
661 local6
= *cfg_obj_assockaddr(address
);
662 local6set
= ISC_TRUE
;
670 main(int argc
, char **argv
) {
671 isc_boolean_t show_final_mem
= ISC_FALSE
;
672 isc_result_t result
= ISC_R_SUCCESS
;
673 isc_taskmgr_t
*taskmgr
= NULL
;
674 isc_task_t
*task
= NULL
;
675 isc_log_t
*log
= NULL
;
676 isc_logconfig_t
*logconfig
= NULL
;
677 isc_logdestination_t logdest
;
678 cfg_parser_t
*pctx
= NULL
;
679 cfg_obj_t
*config
= NULL
;
680 const char *keyname
= NULL
;
688 result
= isc_file_progname(*argv
, program
, sizeof(program
));
689 if (result
!= ISC_R_SUCCESS
)
690 memcpy(program
, "rndc", 5);
693 admin_conffile
= RNDC_CONFFILE
;
694 admin_keyfile
= RNDC_KEYFILE
;
696 isc_sockaddr_any(&local4
);
697 isc_sockaddr_any6(&local6
);
699 result
= isc_app_start();
700 if (result
!= ISC_R_SUCCESS
)
701 fatal("isc_app_start() failed: %s", isc_result_totext(result
));
703 isc_commandline_errprint
= ISC_FALSE
;
705 while ((ch
= isc_commandline_parse(argc
, argv
, "b:c:hk:Mmp:s:Vy:"))
709 if (inet_pton(AF_INET
, isc_commandline_argument
,
711 isc_sockaddr_fromin(&local4
, &in
, 0);
712 local4set
= ISC_TRUE
;
713 } else if (inet_pton(AF_INET6
, isc_commandline_argument
,
715 isc_sockaddr_fromin6(&local6
, &in6
, 0);
716 local6set
= ISC_TRUE
;
721 admin_conffile
= isc_commandline_argument
;
726 admin_keyfile
= isc_commandline_argument
;
730 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
;
734 show_final_mem
= ISC_TRUE
;
738 remoteport
= atoi(isc_commandline_argument
);
739 if (remoteport
> 65535 || remoteport
== 0)
740 fatal("port '%s' out of range",
741 isc_commandline_argument
);
745 servername
= isc_commandline_argument
;
753 keyname
= isc_commandline_argument
;
757 if (isc_commandline_option
!= '?') {
758 fprintf(stderr
, "%s: invalid argument -%c\n",
759 program
, isc_commandline_option
);
766 fprintf(stderr
, "%s: unhandled option -%c\n",
767 program
, isc_commandline_option
);
772 argc
-= isc_commandline_index
;
773 argv
+= isc_commandline_index
;
778 isc_random_get(&serial
);
780 DO("create memory context", isc_mem_create(0, 0, &mctx
));
781 DO("create socket manager", isc_socketmgr_create(mctx
, &socketmgr
));
782 DO("create task manager", isc_taskmgr_create(mctx
, 1, 0, &taskmgr
));
783 DO("create task", isc_task_create(taskmgr
, 0, &task
));
785 DO("create logging context", isc_log_create(mctx
, &log
, &logconfig
));
786 isc_log_setcontext(log
);
787 DO("setting log tag", isc_log_settag(logconfig
, progname
));
788 logdest
.file
.stream
= stderr
;
789 logdest
.file
.name
= NULL
;
790 logdest
.file
.versions
= ISC_LOG_ROLLNEVER
;
791 logdest
.file
.maximum_size
= 0;
792 DO("creating log channel",
793 isc_log_createchannel(logconfig
, "stderr",
794 ISC_LOG_TOFILEDESC
, ISC_LOG_INFO
, &logdest
,
795 ISC_LOG_PRINTTAG
|ISC_LOG_PRINTLEVEL
));
796 DO("enabling log channel", isc_log_usechannel(logconfig
, "stderr",
799 parse_config(mctx
, log
, keyname
, &pctx
, &config
);
801 isccc_result_register();
806 * Convert argc/argv into a space-delimited command string
807 * similar to what the user might enter in interactive mode
808 * (if that were implemented).
811 for (i
= 0; i
< argc
; i
++)
812 argslen
+= strlen(argv
[i
]) + 1;
814 args
= isc_mem_get(mctx
, argslen
);
816 DO("isc_mem_get", ISC_R_NOMEMORY
);
819 for (i
= 0; i
< argc
; i
++) {
820 size_t len
= strlen(argv
[i
]);
821 memcpy(p
, argv
[i
], len
);
828 INSIST(p
== args
+ argslen
);
830 notify("%s", command
);
832 if (strcmp(command
, "restart") == 0)
833 fatal("'%s' is not implemented", command
);
835 if (nserveraddrs
== 0)
836 get_addresses(servername
, (in_port_t
) remoteport
);
838 DO("post event", isc_app_onrun(mctx
, task
, rndc_start
, NULL
));
840 result
= isc_app_run();
841 if (result
!= ISC_R_SUCCESS
)
842 fatal("isc_app_run() failed: %s", isc_result_totext(result
));
844 if (connects
> 0 || sends
> 0 || recvs
> 0)
845 isc_socket_cancel(sock
, task
, ISC_SOCKCANCEL_ALL
);
847 isc_task_detach(&task
);
848 isc_taskmgr_destroy(&taskmgr
);
849 isc_socketmgr_destroy(&socketmgr
);
850 isc_log_destroy(&log
);
851 isc_log_setcontext(NULL
);
853 cfg_obj_destroy(pctx
, &config
);
854 cfg_parser_destroy(&pctx
);
856 isc_mem_put(mctx
, args
, argslen
);
857 isccc_ccmsg_invalidate(&ccmsg
);
862 isc_mem_stats(mctx
, stderr
);
864 isc_mem_destroy(&mctx
);