00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025
00026 #include <stdlib.h>
00027
00028 #include <isc/app.h>
00029 #include <isc/buffer.h>
00030 #include <isc/commandline.h>
00031 #include <isc/file.h>
00032 #include <isc/log.h>
00033 #include <isc/net.h>
00034 #include <isc/mem.h>
00035 #include <isc/random.h>
00036 #include <isc/socket.h>
00037 #include <isc/stdtime.h>
00038 #include <isc/string.h>
00039 #include <isc/task.h>
00040 #include <isc/thread.h>
00041 #include <isc/util.h>
00042
00043 #include <isccfg/namedconf.h>
00044
00045 #include <isccc/alist.h>
00046 #include <isccc/base64.h>
00047 #include <isccc/cc.h>
00048 #include <isccc/ccmsg.h>
00049 #include <isccc/result.h>
00050 #include <isccc/sexpr.h>
00051 #include <isccc/types.h>
00052 #include <isccc/util.h>
00053
00054 #include <dns/name.h>
00055
00056 #include <bind9/getaddresses.h>
00057
00058 #include "util.h"
00059
00060 #define SERVERADDRS 10
00061
00062 const char *progname;
00063 isc_boolean_t verbose;
00064
00065 static const char *admin_conffile;
00066 static const char *admin_keyfile;
00067 static const char *version = VERSION;
00068 static const char *servername = NULL;
00069 static isc_sockaddr_t serveraddrs[SERVERADDRS];
00070 static isc_sockaddr_t local4, local6;
00071 static isc_boolean_t local4set = ISC_FALSE, local6set = ISC_FALSE;
00072 static int nserveraddrs;
00073 static int currentaddr = 0;
00074 static unsigned int remoteport = 0;
00075 static isc_socketmgr_t *socketmgr = NULL;
00076 static isc_buffer_t *databuf;
00077 static isccc_ccmsg_t ccmsg;
00078 static isc_uint32_t algorithm;
00079 static isccc_region_t secret;
00080 static isc_boolean_t failed = ISC_FALSE;
00081 static isc_boolean_t c_flag = ISC_FALSE;
00082 static isc_mem_t *rndc_mctx;
00083 static int sends, recvs, connects;
00084 static char *command;
00085 static char *args;
00086 static char program[256];
00087 static isc_socket_t *sock = NULL;
00088 static isc_uint32_t serial;
00089 static isc_boolean_t quiet = ISC_FALSE;
00090
00091 static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
00092
00093 ISC_PLATFORM_NORETURN_PRE static void
00094 usage(int status) ISC_PLATFORM_NORETURN_POST;
00095
00096 static void
00097 usage(int status) {
00098 fprintf(stderr, "\
00099 Usage: %s [-b address] [-c config] [-s server] [-p port]\n\
00100 [-k key-file ] [-y key] [-V] command\n\
00101 \n\
00102 command is one of the following:\n\
00103 \n\
00104 addzone zone [class [view]] { zone-options }\n\
00105 Add zone to given view. Requires new-zone-file option.\n\
00106 delzone [-clean] zone [class [view]]\n\
00107 Removes zone from given view. Requires new-zone-file option.\n\
00108 dumpdb [-all|-cache|-zones] [view ...]\n\
00109 Dump cache(s) to the dump file (named_dump.db).\n\
00110 flush Flushes all of the server's caches.\n\
00111 flush [view] Flushes the server's cache for a view.\n\
00112 flushname name [view]\n\
00113 Flush the given name from the server's cache(s)\n\
00114 flushtree name [view]\n\
00115 Flush all names under the given name from the server's cache(s)\n\
00116 freeze Suspend updates to all dynamic zones.\n\
00117 freeze zone [class [view]]\n\
00118 Suspend updates to a dynamic zone.\n\
00119 halt Stop the server without saving pending updates.\n\
00120 halt -p Stop the server without saving pending updates reporting\n\
00121 process id.\n\
00122 loadkeys zone [class [view]]\n\
00123 Update keys without signing immediately.\n\
00124 notify zone [class [view]]\n\
00125 Resend NOTIFY messages for the zone.\n\
00126 notrace Set debugging level to 0.\n\
00127 nta -dump\n\
00128 List all negative trust anchors.\n\
00129 nta [-lifetime duration] [-force] domain [view]\n\
00130 Set a negative trust anchor, disabling DNSSEC validation\n\
00131 for the given domain.\n\
00132 Using -lifetime specifies the duration of the NTA, up\n\
00133 to one day.\n\
00134 Using -force prevents the NTA from expiring before its\n\
00135 full lifetime, even if the domain can validate sooner.\n\
00136 nta -remove domain [view]\n\
00137 Remove a negative trust anchor, re-enabling validation\n\
00138 for the given domain.\n\
00139 querylog newstate\n\
00140 Enable / disable query logging.\n\
00141 reconfig Reload configuration file and new zones only.\n\
00142 recursing Dump the queries that are currently recursing (named.recursing)\n\
00143 refresh zone [class [view]]\n\
00144 Schedule immediate maintenance for a zone.\n\
00145 reload Reload configuration file and zones.\n\
00146 reload zone [class [view]]\n\
00147 Reload a single zone.\n\
00148 retransfer zone [class [view]]\n\
00149 Retransfer a single zone without checking serial number.\n\
00150 scan Scan available network interfaces for changes.\n\
00151 secroots [view ...]\n\
00152 Write security roots to the secroots file.\n\
00153 sign zone [class [view]]\n\
00154 Update zone keys, and sign as needed.\n\
00155 signing -clear all zone [class [view]]\n\
00156 Remove the private records for all keys that have\n\
00157 finished signing the given zone.\n\
00158 signing -clear <keyid>/<algorithm> zone [class [view]]\n\
00159 Remove the private record that indicating the given key\n\
00160 has finished signing the given zone.\n\
00161 signing -list zone [class [view]]\n\
00162 List the private records showing the state of DNSSEC\n\
00163 signing in the given zone.\n\
00164 signing -nsec3param hash flags iterations salt zone [class [view]]\n\
00165 Add NSEC3 chain to zone if already signed.\n\
00166 Prime zone with NSEC3 chain if not yet signed.\n\
00167 signing -nsec3param none zone [class [view]]\n\
00168 Remove NSEC3 chains from zone.\n\
00169 stats Write server statistics to the statistics file.\n\
00170 status Display status of the server.\n\
00171 stop Save pending updates to master files and stop the server.\n\
00172 stop -p Save pending updates to master files and stop the server\n\
00173 reporting process id.\n\
00174 sync [-clean] Dump changes to all dynamic zones to disk, and optionally\n\
00175 remove their journal files.\n\
00176 sync [-clean] zone [class [view]]\n\
00177 Dump a single zone's changes to disk, and optionally\n\
00178 remove its journal file.\n\
00179 thaw Enable updates to all dynamic zones and reload them.\n\
00180 thaw zone [class [view]]\n\
00181 Enable updates to a frozen dynamic zone and reload it.\n\
00182 trace Increment debugging level by one.\n\
00183 trace level Change the debugging level.\n\
00184 tsig-delete keyname [view]\n\
00185 Delete a TKEY-negotiated TSIG key.\n\
00186 tsig-list List all currently active TSIG keys, including both statically\n\
00187 configured and TKEY-negotiated keys.\n\
00188 validation newstate [view]\n\
00189 Enable / disable DNSSEC validation.\n\
00190 zonestatus zone [class [view]]\n\
00191 Display the current status of a zone.\n\
00192 \n\
00193 Version: %s\n",
00194 progname, version);
00195
00196 exit(status);
00197 }
00198
00199 static void
00200 get_addresses(const char *host, in_port_t port) {
00201 isc_result_t result;
00202 int found = 0, count;
00203
00204 if (*host == '/') {
00205 result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs],
00206 host);
00207 if (result == ISC_R_SUCCESS)
00208 nserveraddrs++;
00209 } else {
00210 count = SERVERADDRS - nserveraddrs;
00211 result = bind9_getaddresses(host, port,
00212 &serveraddrs[nserveraddrs],
00213 count, &found);
00214 nserveraddrs += found;
00215 }
00216 if (result != ISC_R_SUCCESS)
00217 fatal("couldn't get address for '%s': %s",
00218 host, isc_result_totext(result));
00219 INSIST(nserveraddrs > 0);
00220 }
00221
00222 static void
00223 rndc_senddone(isc_task_t *task, isc_event_t *event) {
00224 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
00225
00226 UNUSED(task);
00227
00228 sends--;
00229 if (sevent->result != ISC_R_SUCCESS)
00230 fatal("send failed: %s", isc_result_totext(sevent->result));
00231 isc_event_free(&event);
00232 if (sends == 0 && recvs == 0) {
00233 isc_socket_detach(&sock);
00234 isc_task_shutdown(task);
00235 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
00236 }
00237 }
00238
00239 static void
00240 rndc_recvdone(isc_task_t *task, isc_event_t *event) {
00241 isccc_sexpr_t *response = NULL;
00242 isccc_sexpr_t *data;
00243 isccc_region_t source;
00244 char *errormsg = NULL;
00245 char *textmsg = NULL;
00246 isc_result_t result;
00247
00248 recvs--;
00249
00250 if (ccmsg.result == ISC_R_EOF)
00251 fatal("connection to remote host closed\n"
00252 "This may indicate that\n"
00253 "* the remote server is using an older version of"
00254 " the command protocol,\n"
00255 "* this host is not authorized to connect,\n"
00256 "* the clocks are not synchronized, or\n"
00257 "* the key is invalid.");
00258
00259 if (ccmsg.result != ISC_R_SUCCESS)
00260 fatal("recv failed: %s", isc_result_totext(ccmsg.result));
00261
00262 source.rstart = isc_buffer_base(&ccmsg.buffer);
00263 source.rend = isc_buffer_used(&ccmsg.buffer);
00264
00265 DO("parse message",
00266 isccc_cc_fromwire(&source, &response, algorithm, &secret));
00267
00268 data = isccc_alist_lookup(response, "_data");
00269 if (data == NULL)
00270 fatal("no data section in response");
00271 result = isccc_cc_lookupstring(data, "err", &errormsg);
00272 if (result == ISC_R_SUCCESS) {
00273 failed = ISC_TRUE;
00274 fprintf(stderr, "%s: '%s' failed: %s\n",
00275 progname, command, errormsg);
00276 }
00277 else if (result != ISC_R_NOTFOUND)
00278 fprintf(stderr, "%s: parsing response failed: %s\n",
00279 progname, isc_result_totext(result));
00280
00281 result = isccc_cc_lookupstring(data, "text", &textmsg);
00282 if (result == ISC_R_SUCCESS) {
00283 if ((!quiet || failed) && strlen(textmsg) != 0U)
00284 fprintf(failed ? stderr : stdout, "%s\n", textmsg);
00285 } else if (result != ISC_R_NOTFOUND)
00286 fprintf(stderr, "%s: parsing response failed: %s\n",
00287 progname, isc_result_totext(result));
00288
00289 isc_event_free(&event);
00290 isccc_sexpr_free(&response);
00291 if (sends == 0 && recvs == 0) {
00292 isc_socket_detach(&sock);
00293 isc_task_shutdown(task);
00294 RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
00295 }
00296 }
00297
00298 static void
00299 rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
00300 isccc_sexpr_t *response = NULL;
00301 isccc_sexpr_t *_ctrl;
00302 isccc_region_t source;
00303 isc_result_t result;
00304 isc_uint32_t nonce;
00305 isccc_sexpr_t *request = NULL;
00306 isccc_time_t now;
00307 isc_region_t r;
00308 isccc_sexpr_t *data;
00309 isc_buffer_t b;
00310
00311 recvs--;
00312
00313 if (ccmsg.result == ISC_R_EOF)
00314 fatal("connection to remote host closed\n"
00315 "This may indicate that\n"
00316 "* the remote server is using an older version of"
00317 " the command protocol,\n"
00318 "* this host is not authorized to connect,\n"
00319 "* the clocks are not synchronized,\n"
00320 "* the the key signing algorithm is incorrect, or\n"
00321 "* the key is invalid.");
00322
00323 if (ccmsg.result != ISC_R_SUCCESS)
00324 fatal("recv failed: %s", isc_result_totext(ccmsg.result));
00325
00326 source.rstart = isc_buffer_base(&ccmsg.buffer);
00327 source.rend = isc_buffer_used(&ccmsg.buffer);
00328
00329 DO("parse message",
00330 isccc_cc_fromwire(&source, &response, algorithm, &secret));
00331
00332 _ctrl = isccc_alist_lookup(response, "_ctrl");
00333 if (_ctrl == NULL)
00334 fatal("_ctrl section missing");
00335 nonce = 0;
00336 if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
00337 nonce = 0;
00338
00339 isc_stdtime_get(&now);
00340
00341 DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
00342 now, now + 60, &request));
00343 data = isccc_alist_lookup(request, "_data");
00344 if (data == NULL)
00345 fatal("_data section missing");
00346 if (isccc_cc_definestring(data, "type", args) == NULL)
00347 fatal("out of memory");
00348 if (nonce != 0) {
00349 _ctrl = isccc_alist_lookup(request, "_ctrl");
00350 if (_ctrl == NULL)
00351 fatal("_ctrl section missing");
00352 if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
00353 fatal("out of memory");
00354 }
00355
00356 isc_buffer_clear(databuf);
00357
00358 isc_buffer_add(databuf, 4);
00359
00360 DO("render message",
00361 isccc_cc_towire(request, &databuf, algorithm, &secret));
00362
00363 isc_buffer_init(&b, databuf->base, 4);
00364 isc_buffer_putuint32(&b, databuf->used - 4);
00365
00366 r.base = databuf->base;
00367 r.length = databuf->used;
00368
00369 isccc_ccmsg_cancelread(&ccmsg);
00370 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
00371 rndc_recvdone, NULL));
00372 recvs++;
00373 DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
00374 NULL));
00375 sends++;
00376
00377 isc_event_free(&event);
00378 isccc_sexpr_free(&response);
00379 return;
00380 }
00381
00382 static void
00383 rndc_connected(isc_task_t *task, isc_event_t *event) {
00384 char socktext[ISC_SOCKADDR_FORMATSIZE];
00385 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
00386 isccc_sexpr_t *request = NULL;
00387 isccc_sexpr_t *data;
00388 isccc_time_t now;
00389 isc_region_t r;
00390 isc_buffer_t b;
00391 isc_result_t result;
00392
00393 connects--;
00394
00395 if (sevent->result != ISC_R_SUCCESS) {
00396 isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
00397 sizeof(socktext));
00398 if (sevent->result != ISC_R_CANCELED &&
00399 ++currentaddr < nserveraddrs)
00400 {
00401 notify("connection failed: %s: %s", socktext,
00402 isc_result_totext(sevent->result));
00403 isc_socket_detach(&sock);
00404 isc_event_free(&event);
00405 rndc_startconnect(&serveraddrs[currentaddr], task);
00406 return;
00407 } else
00408 fatal("connect failed: %s: %s", socktext,
00409 isc_result_totext(sevent->result));
00410 }
00411
00412 isc_stdtime_get(&now);
00413 DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
00414 now, now + 60, &request));
00415 data = isccc_alist_lookup(request, "_data");
00416 if (data == NULL)
00417 fatal("_data section missing");
00418 if (isccc_cc_definestring(data, "type", "null") == NULL)
00419 fatal("out of memory");
00420
00421 isc_buffer_clear(databuf);
00422
00423 isc_buffer_add(databuf, 4);
00424
00425 DO("render message",
00426 isccc_cc_towire(request, &databuf, algorithm, &secret));
00427
00428 isc_buffer_init(&b, databuf->base, 4);
00429 isc_buffer_putuint32(&b, databuf->used - 4);
00430
00431 r.base = databuf->base;
00432 r.length = databuf->used;
00433
00434 isccc_ccmsg_init(rndc_mctx, sock, &ccmsg);
00435 isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
00436
00437 DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
00438 rndc_recvnonce, NULL));
00439 recvs++;
00440 DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
00441 NULL));
00442 sends++;
00443 isc_event_free(&event);
00444 }
00445
00446 static void
00447 rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
00448 isc_result_t result;
00449 int pf;
00450 isc_sockettype_t type;
00451
00452 char socktext[ISC_SOCKADDR_FORMATSIZE];
00453
00454 isc_sockaddr_format(addr, socktext, sizeof(socktext));
00455
00456 notify("using server %s (%s)", servername, socktext);
00457
00458 pf = isc_sockaddr_pf(addr);
00459 if (pf == AF_INET || pf == AF_INET6)
00460 type = isc_sockettype_tcp;
00461 else
00462 type = isc_sockettype_unix;
00463 DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
00464 switch (isc_sockaddr_pf(addr)) {
00465 case AF_INET:
00466 DO("bind socket", isc_socket_bind(sock, &local4, 0));
00467 break;
00468 case AF_INET6:
00469 DO("bind socket", isc_socket_bind(sock, &local6, 0));
00470 break;
00471 default:
00472 break;
00473 }
00474 DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
00475 NULL));
00476 connects++;
00477 }
00478
00479 static void
00480 rndc_start(isc_task_t *task, isc_event_t *event) {
00481 isc_event_free(&event);
00482
00483 currentaddr = 0;
00484 rndc_startconnect(&serveraddrs[currentaddr], task);
00485 }
00486
00487 static void
00488 parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
00489 cfg_parser_t **pctxp, cfg_obj_t **configp)
00490 {
00491 isc_result_t result;
00492 const char *conffile = admin_conffile;
00493 const cfg_obj_t *addresses = NULL;
00494 const cfg_obj_t *defkey = NULL;
00495 const cfg_obj_t *options = NULL;
00496 const cfg_obj_t *servers = NULL;
00497 const cfg_obj_t *server = NULL;
00498 const cfg_obj_t *keys = NULL;
00499 const cfg_obj_t *key = NULL;
00500 const cfg_obj_t *defport = NULL;
00501 const cfg_obj_t *secretobj = NULL;
00502 const cfg_obj_t *algorithmobj = NULL;
00503 cfg_obj_t *config = NULL;
00504 const cfg_obj_t *address = NULL;
00505 const cfg_listelt_t *elt;
00506 const char *secretstr;
00507 const char *algorithmstr;
00508 static char secretarray[1024];
00509 const cfg_type_t *conftype = &cfg_type_rndcconf;
00510 isc_boolean_t key_only = ISC_FALSE;
00511 const cfg_listelt_t *element;
00512
00513 if (! isc_file_exists(conffile)) {
00514 conffile = admin_keyfile;
00515 conftype = &cfg_type_rndckey;
00516
00517 if (c_flag)
00518 fatal("%s does not exist", admin_conffile);
00519
00520 if (! isc_file_exists(conffile))
00521 fatal("neither %s nor %s was found",
00522 admin_conffile, admin_keyfile);
00523 key_only = ISC_TRUE;
00524 } else if (! c_flag && isc_file_exists(admin_keyfile)) {
00525 fprintf(stderr, "WARNING: key file (%s) exists, but using "
00526 "default configuration file (%s)\n",
00527 admin_keyfile, admin_conffile);
00528 }
00529
00530 DO("create parser", cfg_parser_create(mctx, log, pctxp));
00531
00532
00533
00534
00535 result = cfg_parse_file(*pctxp, conffile, conftype, &config);
00536 if (result != ISC_R_SUCCESS)
00537 fatal("could not load rndc configuration");
00538
00539 if (!key_only)
00540 (void)cfg_map_get(config, "options", &options);
00541
00542 if (key_only && servername == NULL)
00543 servername = "127.0.0.1";
00544 else if (servername == NULL && options != NULL) {
00545 const cfg_obj_t *defserverobj = NULL;
00546 (void)cfg_map_get(options, "default-server", &defserverobj);
00547 if (defserverobj != NULL)
00548 servername = cfg_obj_asstring(defserverobj);
00549 }
00550
00551 if (servername == NULL)
00552 fatal("no server specified and no default");
00553
00554 if (!key_only) {
00555 (void)cfg_map_get(config, "server", &servers);
00556 if (servers != NULL) {
00557 for (elt = cfg_list_first(servers);
00558 elt != NULL;
00559 elt = cfg_list_next(elt))
00560 {
00561 const char *name;
00562 server = cfg_listelt_value(elt);
00563 name = cfg_obj_asstring(cfg_map_getname(server));
00564 if (strcasecmp(name, servername) == 0)
00565 break;
00566 server = NULL;
00567 }
00568 }
00569 }
00570
00571
00572
00573
00574 if (keyname != NULL)
00575 ;
00576 else if (server != NULL) {
00577 DO("get key for server", cfg_map_get(server, "key", &defkey));
00578 keyname = cfg_obj_asstring(defkey);
00579 } else if (options != NULL) {
00580 DO("get default key", cfg_map_get(options, "default-key",
00581 &defkey));
00582 keyname = cfg_obj_asstring(defkey);
00583 } else if (!key_only)
00584 fatal("no key for server and no default");
00585
00586
00587
00588
00589 if (key_only)
00590 DO("get key", cfg_map_get(config, "key", &key));
00591 else {
00592 DO("get config key list", cfg_map_get(config, "key", &keys));
00593 for (elt = cfg_list_first(keys);
00594 elt != NULL;
00595 elt = cfg_list_next(elt))
00596 {
00597 key = cfg_listelt_value(elt);
00598 if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
00599 keyname) == 0)
00600 break;
00601 }
00602 if (elt == NULL)
00603 fatal("no key definition for name %s", keyname);
00604 }
00605 (void)cfg_map_get(key, "secret", &secretobj);
00606 (void)cfg_map_get(key, "algorithm", &algorithmobj);
00607 if (secretobj == NULL || algorithmobj == NULL)
00608 fatal("key must have algorithm and secret");
00609
00610 secretstr = cfg_obj_asstring(secretobj);
00611 algorithmstr = cfg_obj_asstring(algorithmobj);
00612
00613 if (strcasecmp(algorithmstr, "hmac-md5") == 0)
00614 algorithm = ISCCC_ALG_HMACMD5;
00615 else if (strcasecmp(algorithmstr, "hmac-sha1") == 0)
00616 algorithm = ISCCC_ALG_HMACSHA1;
00617 else if (strcasecmp(algorithmstr, "hmac-sha224") == 0)
00618 algorithm = ISCCC_ALG_HMACSHA224;
00619 else if (strcasecmp(algorithmstr, "hmac-sha256") == 0)
00620 algorithm = ISCCC_ALG_HMACSHA256;
00621 else if (strcasecmp(algorithmstr, "hmac-sha384") == 0)
00622 algorithm = ISCCC_ALG_HMACSHA384;
00623 else if (strcasecmp(algorithmstr, "hmac-sha512") == 0)
00624 algorithm = ISCCC_ALG_HMACSHA512;
00625 else
00626 fatal("unsupported algorithm: %s", algorithmstr);
00627
00628 secret.rstart = (unsigned char *)secretarray;
00629 secret.rend = (unsigned char *)secretarray + sizeof(secretarray);
00630 DO("decode base64 secret", isccc_base64_decode(secretstr, &secret));
00631 secret.rend = secret.rstart;
00632 secret.rstart = (unsigned char *)secretarray;
00633
00634
00635
00636
00637 if (remoteport != 0)
00638 ;
00639 else {
00640 if (server != NULL)
00641 (void)cfg_map_get(server, "port", &defport);
00642 if (defport == NULL && options != NULL)
00643 (void)cfg_map_get(options, "default-port", &defport);
00644 }
00645 if (defport != NULL) {
00646 remoteport = cfg_obj_asuint32(defport);
00647 if (remoteport > 65535 || remoteport == 0)
00648 fatal("port %u out of range", remoteport);
00649 } else if (remoteport == 0)
00650 remoteport = NS_CONTROL_PORT;
00651
00652 if (server != NULL)
00653 result = cfg_map_get(server, "addresses", &addresses);
00654 else
00655 result = ISC_R_NOTFOUND;
00656 if (result == ISC_R_SUCCESS) {
00657 for (element = cfg_list_first(addresses);
00658 element != NULL;
00659 element = cfg_list_next(element))
00660 {
00661 isc_sockaddr_t sa;
00662
00663 address = cfg_listelt_value(element);
00664 if (!cfg_obj_issockaddr(address)) {
00665 unsigned int myport;
00666 const char *name;
00667 const cfg_obj_t *obj;
00668
00669 obj = cfg_tuple_get(address, "name");
00670 name = cfg_obj_asstring(obj);
00671 obj = cfg_tuple_get(address, "port");
00672 if (cfg_obj_isuint32(obj)) {
00673 myport = cfg_obj_asuint32(obj);
00674 if (myport > ISC_UINT16_MAX ||
00675 myport == 0)
00676 fatal("port %u out of range",
00677 myport);
00678 } else
00679 myport = remoteport;
00680 if (nserveraddrs < SERVERADDRS)
00681 get_addresses(name, (in_port_t) myport);
00682 else
00683 fprintf(stderr, "too many address: "
00684 "%s: dropped\n", name);
00685 continue;
00686 }
00687 sa = *cfg_obj_assockaddr(address);
00688 if (isc_sockaddr_getport(&sa) == 0)
00689 isc_sockaddr_setport(&sa, remoteport);
00690 if (nserveraddrs < SERVERADDRS)
00691 serveraddrs[nserveraddrs++] = sa;
00692 else {
00693 char socktext[ISC_SOCKADDR_FORMATSIZE];
00694
00695 isc_sockaddr_format(&sa, socktext,
00696 sizeof(socktext));
00697 fprintf(stderr,
00698 "too many address: %s: dropped\n",
00699 socktext);
00700 }
00701 }
00702 }
00703
00704 if (!local4set && server != NULL) {
00705 address = NULL;
00706 cfg_map_get(server, "source-address", &address);
00707 if (address != NULL) {
00708 local4 = *cfg_obj_assockaddr(address);
00709 local4set = ISC_TRUE;
00710 }
00711 }
00712 if (!local4set && options != NULL) {
00713 address = NULL;
00714 cfg_map_get(options, "default-source-address", &address);
00715 if (address != NULL) {
00716 local4 = *cfg_obj_assockaddr(address);
00717 local4set = ISC_TRUE;
00718 }
00719 }
00720
00721 if (!local6set && server != NULL) {
00722 address = NULL;
00723 cfg_map_get(server, "source-address-v6", &address);
00724 if (address != NULL) {
00725 local6 = *cfg_obj_assockaddr(address);
00726 local6set = ISC_TRUE;
00727 }
00728 }
00729 if (!local6set && options != NULL) {
00730 address = NULL;
00731 cfg_map_get(options, "default-source-address-v6", &address);
00732 if (address != NULL) {
00733 local6 = *cfg_obj_assockaddr(address);
00734 local6set = ISC_TRUE;
00735 }
00736 }
00737
00738 *configp = config;
00739 }
00740
00741 int
00742 main(int argc, char **argv) {
00743 isc_result_t result = ISC_R_SUCCESS;
00744 isc_boolean_t show_final_mem = ISC_FALSE;
00745 isc_taskmgr_t *taskmgr = NULL;
00746 isc_task_t *task = NULL;
00747 isc_log_t *log = NULL;
00748 isc_logconfig_t *logconfig = NULL;
00749 isc_logdestination_t logdest;
00750 cfg_parser_t *pctx = NULL;
00751 cfg_obj_t *config = NULL;
00752 const char *keyname = NULL;
00753 struct in_addr in;
00754 struct in6_addr in6;
00755 char *p;
00756 size_t argslen;
00757 int ch;
00758 int i;
00759
00760 result = isc_file_progname(*argv, program, sizeof(program));
00761 if (result != ISC_R_SUCCESS)
00762 memmove(program, "rndc", 5);
00763 progname = program;
00764
00765 admin_conffile = RNDC_CONFFILE;
00766 admin_keyfile = RNDC_KEYFILE;
00767
00768 isc_sockaddr_any(&local4);
00769 isc_sockaddr_any6(&local6);
00770
00771 result = isc_app_start();
00772 if (result != ISC_R_SUCCESS)
00773 fatal("isc_app_start() failed: %s", isc_result_totext(result));
00774
00775 isc_commandline_errprint = ISC_FALSE;
00776
00777 while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:qs:Vy:"))
00778 != -1) {
00779 switch (ch) {
00780 case 'b':
00781 if (inet_pton(AF_INET, isc_commandline_argument,
00782 &in) == 1) {
00783 isc_sockaddr_fromin(&local4, &in, 0);
00784 local4set = ISC_TRUE;
00785 } else if (inet_pton(AF_INET6, isc_commandline_argument,
00786 &in6) == 1) {
00787 isc_sockaddr_fromin6(&local6, &in6, 0);
00788 local6set = ISC_TRUE;
00789 }
00790 break;
00791
00792 case 'c':
00793 admin_conffile = isc_commandline_argument;
00794 c_flag = ISC_TRUE;
00795 break;
00796
00797 case 'k':
00798 admin_keyfile = isc_commandline_argument;
00799 break;
00800
00801 case 'M':
00802 isc_mem_debugging = ISC_MEM_DEBUGTRACE;
00803 break;
00804
00805 case 'm':
00806 show_final_mem = ISC_TRUE;
00807 break;
00808
00809 case 'p':
00810 remoteport = atoi(isc_commandline_argument);
00811 if (remoteport > 65535 || remoteport == 0)
00812 fatal("port '%s' out of range",
00813 isc_commandline_argument);
00814 break;
00815
00816 case 'q':
00817 quiet = ISC_TRUE;
00818 break;
00819
00820 case 's':
00821 servername = isc_commandline_argument;
00822 break;
00823
00824 case 'V':
00825 verbose = ISC_TRUE;
00826 break;
00827
00828 case 'y':
00829 keyname = isc_commandline_argument;
00830 break;
00831
00832 case '?':
00833 if (isc_commandline_option != '?') {
00834 fprintf(stderr, "%s: invalid argument -%c\n",
00835 program, isc_commandline_option);
00836 usage(1);
00837 }
00838
00839 case 'h':
00840 usage(0);
00841 break;
00842 default:
00843 fprintf(stderr, "%s: unhandled option -%c\n",
00844 program, isc_commandline_option);
00845 exit(1);
00846 }
00847 }
00848
00849 argc -= isc_commandline_index;
00850 argv += isc_commandline_index;
00851
00852 if (argc < 1)
00853 usage(1);
00854
00855 isc_random_get(&serial);
00856
00857 DO("create memory context", isc_mem_create(0, 0, &rndc_mctx));
00858 DO("create socket manager", isc_socketmgr_create(rndc_mctx, &socketmgr));
00859 DO("create task manager", isc_taskmgr_create(rndc_mctx, 1, 0, &taskmgr));
00860 DO("create task", isc_task_create(taskmgr, 0, &task));
00861
00862 DO("create logging context", isc_log_create(rndc_mctx, &log, &logconfig));
00863 isc_log_setcontext(log);
00864 DO("setting log tag", isc_log_settag(logconfig, progname));
00865 logdest.file.stream = stderr;
00866 logdest.file.name = NULL;
00867 logdest.file.versions = ISC_LOG_ROLLNEVER;
00868 logdest.file.maximum_size = 0;
00869 DO("creating log channel",
00870 isc_log_createchannel(logconfig, "stderr",
00871 ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
00872 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
00873 DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
00874 NULL, NULL));
00875
00876 parse_config(rndc_mctx, log, keyname, &pctx, &config);
00877
00878 isccc_result_register();
00879
00880 command = *argv;
00881
00882 DO("allocate data buffer",
00883 isc_buffer_allocate(rndc_mctx, &databuf, 2048));
00884
00885
00886
00887
00888
00889
00890 argslen = 0;
00891 for (i = 0; i < argc; i++)
00892 argslen += strlen(argv[i]) + 1;
00893
00894 args = isc_mem_get(rndc_mctx, argslen);
00895 if (args == NULL)
00896 DO("isc_mem_get", ISC_R_NOMEMORY);
00897
00898 p = args;
00899 for (i = 0; i < argc; i++) {
00900 size_t len = strlen(argv[i]);
00901 memmove(p, argv[i], len);
00902 p += len;
00903 *p++ = ' ';
00904 }
00905
00906 p--;
00907 *p++ = '\0';
00908 INSIST(p == args + argslen);
00909
00910 notify("%s", command);
00911
00912 if (strcmp(command, "restart") == 0)
00913 fatal("'%s' is not implemented", command);
00914
00915 if (nserveraddrs == 0)
00916 get_addresses(servername, (in_port_t) remoteport);
00917
00918 DO("post event", isc_app_onrun(rndc_mctx, task, rndc_start, NULL));
00919
00920 result = isc_app_run();
00921 if (result != ISC_R_SUCCESS)
00922 fatal("isc_app_run() failed: %s", isc_result_totext(result));
00923
00924 if (connects > 0 || sends > 0 || recvs > 0)
00925 isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
00926
00927 isc_task_detach(&task);
00928 isc_taskmgr_destroy(&taskmgr);
00929 isc_socketmgr_destroy(&socketmgr);
00930 isc_log_destroy(&log);
00931 isc_log_setcontext(NULL);
00932
00933 cfg_obj_destroy(pctx, &config);
00934 cfg_parser_destroy(&pctx);
00935
00936 isc_mem_put(rndc_mctx, args, argslen);
00937 isccc_ccmsg_invalidate(&ccmsg);
00938
00939 dns_name_destroy();
00940
00941 isc_buffer_free(&databuf);
00942
00943 if (show_final_mem)
00944 isc_mem_stats(rndc_mctx, stderr);
00945
00946 isc_mem_destroy(&rndc_mctx);
00947
00948 if (failed)
00949 return (1);
00950
00951 return (0);
00952 }