00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <ctype.h>
00023 #include <errno.h>
00024 #include <limits.h>
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027
00028 #include <isc/app.h>
00029 #include <isc/base64.h>
00030 #include <isc/buffer.h>
00031 #include <isc/commandline.h>
00032 #include <isc/entropy.h>
00033 #include <isc/event.h>
00034 #include <isc/file.h>
00035 #include <isc/hash.h>
00036 #include <isc/lex.h>
00037 #include <isc/log.h>
00038 #include <isc/mem.h>
00039 #include <isc/parseint.h>
00040 #include <isc/print.h>
00041 #include <isc/random.h>
00042 #include <isc/region.h>
00043 #include <isc/sockaddr.h>
00044 #include <isc/socket.h>
00045 #include <isc/stdio.h>
00046 #include <isc/string.h>
00047 #include <isc/task.h>
00048 #include <isc/timer.h>
00049 #include <isc/types.h>
00050 #include <isc/util.h>
00051
00052 #include <isccfg/namedconf.h>
00053
00054 #include <dns/callbacks.h>
00055 #include <dns/dispatch.h>
00056 #include <dns/dnssec.h>
00057 #include <dns/events.h>
00058 #include <dns/fixedname.h>
00059 #include <dns/log.h>
00060 #include <dns/masterdump.h>
00061 #include <dns/message.h>
00062 #include <dns/name.h>
00063 #include <dns/rcode.h>
00064 #include <dns/rdata.h>
00065 #include <dns/rdataclass.h>
00066 #include <dns/rdatalist.h>
00067 #include <dns/rdataset.h>
00068 #include <dns/rdatastruct.h>
00069 #include <dns/rdatatype.h>
00070 #include <dns/request.h>
00071 #include <dns/result.h>
00072 #include <dns/tkey.h>
00073 #include <dns/tsig.h>
00074
00075 #include <dst/dst.h>
00076
00077 #include <lwres/lwres.h>
00078 #include <lwres/net.h>
00079
00080 #ifdef GSSAPI
00081 #include <dst/gssapi.h>
00082 #ifdef WIN32
00083 #include <krb5/krb5.h>
00084 #else
00085 #include ISC_PLATFORM_KRB5HEADER
00086 #endif
00087 #endif
00088 #include <bind9/getaddresses.h>
00089
00090 #if defined(HAVE_READLINE)
00091 #include <readline/readline.h>
00092 #include <readline/history.h>
00093 #endif
00094
00095 #ifdef HAVE_ADDRINFO
00096 #ifdef HAVE_GETADDRINFO
00097 #ifdef HAVE_GAISTRERROR
00098 #define USE_GETADDRINFO
00099 #endif
00100 #endif
00101 #endif
00102
00103 #ifndef USE_GETADDRINFO
00104 #ifndef ISC_PLATFORM_NONSTDHERRNO
00105 extern int h_errno;
00106 #endif
00107 #endif
00108
00109 #define MAXCMD (128 * 1024)
00110 #define MAXWIRE (64 * 1024)
00111 #define PACKETSIZE ((64 * 1024) - 1)
00112 #define INITTEXT (2 * 1024)
00113 #define MAXTEXT (128 * 1024)
00114 #define FIND_TIMEOUT 5
00115 #define TTL_MAX 2147483647U
00116
00117 #define DNSDEFAULTPORT 53
00118
00119
00120 #define MAX_SERVERADDRS 4
00121
00122 static isc_uint16_t dnsport = DNSDEFAULTPORT;
00123
00124 #ifndef RESOLV_CONF
00125 #define RESOLV_CONF "/etc/resolv.conf"
00126 #endif
00127
00128 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
00129 static isc_boolean_t memdebugging = ISC_FALSE;
00130 static isc_boolean_t have_ipv4 = ISC_FALSE;
00131 static isc_boolean_t have_ipv6 = ISC_FALSE;
00132 static isc_boolean_t is_dst_up = ISC_FALSE;
00133 static isc_boolean_t usevc = ISC_FALSE;
00134 static isc_boolean_t usegsstsig = ISC_FALSE;
00135 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
00136 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
00137 static isc_boolean_t local_only = ISC_FALSE;
00138 static isc_taskmgr_t *taskmgr = NULL;
00139 static isc_task_t *global_task = NULL;
00140 static isc_event_t *global_event = NULL;
00141 static isc_log_t *glctx = NULL;
00142 static isc_mem_t *gmctx = NULL;
00143 static dns_dispatchmgr_t *dispatchmgr = NULL;
00144 static dns_requestmgr_t *requestmgr = NULL;
00145 static isc_socketmgr_t *socketmgr = NULL;
00146 static isc_timermgr_t *timermgr = NULL;
00147 static dns_dispatch_t *dispatchv4 = NULL;
00148 static dns_dispatch_t *dispatchv6 = NULL;
00149 static dns_message_t *updatemsg = NULL;
00150 static dns_fixedname_t fuserzone;
00151 static dns_name_t *userzone = NULL;
00152 static dns_name_t *zname = NULL;
00153 static dns_name_t tmpzonename;
00154 static dns_name_t restart_master;
00155 static dns_tsig_keyring_t *gssring = NULL;
00156 static dns_tsigkey_t *tsigkey = NULL;
00157 static dst_key_t *sig0key = NULL;
00158 static lwres_context_t *lwctx = NULL;
00159 static lwres_conf_t *lwconf;
00160 static isc_sockaddr_t *servers = NULL;
00161 static isc_sockaddr_t *master_servers = NULL;
00162 static isc_boolean_t default_servers = ISC_TRUE;
00163 static int ns_inuse = 0;
00164 static int master_inuse = 0;
00165 static int ns_total = 0;
00166 static int master_total = 0;
00167 static isc_sockaddr_t *localaddr4 = NULL;
00168 static isc_sockaddr_t *localaddr6 = NULL;
00169 static const char *keyfile = NULL;
00170 static char *keystr = NULL;
00171 static isc_entropy_t *entropy = NULL;
00172 static isc_boolean_t shuttingdown = ISC_FALSE;
00173 static FILE *input;
00174 static isc_boolean_t interactive = ISC_TRUE;
00175 static isc_boolean_t seenerror = ISC_FALSE;
00176 static const dns_master_style_t *style;
00177 static int requests = 0;
00178 static unsigned int logdebuglevel = 0;
00179 static unsigned int timeout = 300;
00180 static unsigned int udp_timeout = 3;
00181 static unsigned int udp_retries = 3;
00182 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
00183 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
00184 static dns_message_t *answer = NULL;
00185 static isc_uint32_t default_ttl = 0;
00186 static isc_boolean_t default_ttl_set = ISC_FALSE;
00187 static isc_boolean_t checknames = ISC_TRUE;
00188
00189 typedef struct nsu_requestinfo {
00190 dns_message_t *msg;
00191 isc_sockaddr_t *addr;
00192 } nsu_requestinfo_t;
00193
00194 static void
00195 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
00196 dns_request_t **request);
00197 static void
00198 send_update(dns_name_t *zonename, isc_sockaddr_t *master);
00199
00200 ISC_PLATFORM_NORETURN_PRE static void
00201 fatal(const char *format, ...)
00202 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
00203
00204 static void
00205 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
00206
00207 static void
00208 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
00209
00210 #ifdef GSSAPI
00211 static dns_fixedname_t fkname;
00212 static isc_sockaddr_t *kserver = NULL;
00213 static char *realm = NULL;
00214 static char servicename[DNS_NAME_FORMATSIZE];
00215 static dns_name_t *keyname;
00216 typedef struct nsu_gssinfo {
00217 dns_message_t *msg;
00218 isc_sockaddr_t *addr;
00219 gss_ctx_id_t context;
00220 } nsu_gssinfo_t;
00221
00222 static void
00223 start_gssrequest(dns_name_t *master);
00224 static void
00225 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
00226 dns_request_t **request, gss_ctx_id_t context);
00227 static void
00228 recvgss(isc_task_t *task, isc_event_t *event);
00229 #endif
00230
00231 static void
00232 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
00233
00234 #define STATUS_MORE (isc_uint16_t)0
00235 #define STATUS_SEND (isc_uint16_t)1
00236 #define STATUS_QUIT (isc_uint16_t)2
00237 #define STATUS_SYNTAX (isc_uint16_t)3
00238
00239 typedef struct entropysource entropysource_t;
00240
00241 struct entropysource {
00242 isc_entropysource_t *source;
00243 isc_mem_t *mctx;
00244 ISC_LINK(entropysource_t) link;
00245 };
00246
00247 static ISC_LIST(entropysource_t) sources;
00248
00249 static void
00250 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
00251 isc_result_t result;
00252 isc_entropysource_t *source = NULL;
00253 entropysource_t *elt;
00254 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
00255
00256 REQUIRE(ectx != NULL);
00257
00258 if (*ectx == NULL) {
00259 result = isc_entropy_create(mctx, ectx);
00260 if (result != ISC_R_SUCCESS)
00261 fatal("could not create entropy object");
00262 ISC_LIST_INIT(sources);
00263 }
00264
00265 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
00266 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
00267 randomfile = NULL;
00268 }
00269
00270 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
00271 usekeyboard);
00272
00273 if (result != ISC_R_SUCCESS)
00274 fatal("could not initialize entropy source: %s",
00275 isc_result_totext(result));
00276
00277 if (source != NULL) {
00278 elt = isc_mem_get(mctx, sizeof(*elt));
00279 if (elt == NULL)
00280 fatal("out of memory");
00281 elt->source = source;
00282 elt->mctx = mctx;
00283 ISC_LINK_INIT(elt, link);
00284 ISC_LIST_APPEND(sources, elt, link);
00285 }
00286 }
00287
00288 static void
00289 cleanup_entropy(isc_entropy_t **ectx) {
00290 entropysource_t *source;
00291 while (!ISC_LIST_EMPTY(sources)) {
00292 source = ISC_LIST_HEAD(sources);
00293 ISC_LIST_UNLINK(sources, source, link);
00294 isc_entropy_destroysource(&source->source);
00295 isc_mem_put(source->mctx, source, sizeof(*source));
00296 }
00297 isc_entropy_detach(ectx);
00298 }
00299
00300 static void
00301 master_from_servers(void) {
00302
00303 if (master_servers != NULL && master_servers != servers)
00304 isc_mem_put(gmctx, master_servers,
00305 master_total * sizeof(isc_sockaddr_t));
00306 master_servers = servers;
00307 master_total = ns_total;
00308 master_inuse = ns_inuse;
00309 }
00310
00311 static dns_rdataclass_t
00312 getzoneclass(void) {
00313 if (zoneclass == dns_rdataclass_none)
00314 zoneclass = defaultclass;
00315 return (zoneclass);
00316 }
00317
00318 static isc_boolean_t
00319 setzoneclass(dns_rdataclass_t rdclass) {
00320 if (zoneclass == dns_rdataclass_none ||
00321 rdclass == dns_rdataclass_none)
00322 zoneclass = rdclass;
00323 if (zoneclass != rdclass)
00324 return (ISC_FALSE);
00325 return (ISC_TRUE);
00326 }
00327
00328 static void
00329 fatal(const char *format, ...) {
00330 va_list args;
00331
00332 va_start(args, format);
00333 vfprintf(stderr, format, args);
00334 va_end(args);
00335 fprintf(stderr, "\n");
00336 exit(1);
00337 }
00338
00339 static void
00340 error(const char *format, ...) {
00341 va_list args;
00342
00343 va_start(args, format);
00344 vfprintf(stderr, format, args);
00345 va_end(args);
00346 fprintf(stderr, "\n");
00347 }
00348
00349 static void
00350 debug(const char *format, ...) {
00351 va_list args;
00352
00353 if (debugging) {
00354 va_start(args, format);
00355 vfprintf(stderr, format, args);
00356 va_end(args);
00357 fprintf(stderr, "\n");
00358 }
00359 }
00360
00361 static void
00362 ddebug(const char *format, ...) {
00363 va_list args;
00364
00365 if (ddebugging) {
00366 va_start(args, format);
00367 vfprintf(stderr, format, args);
00368 va_end(args);
00369 fprintf(stderr, "\n");
00370 }
00371 }
00372
00373 static inline void
00374 check_result(isc_result_t result, const char *msg) {
00375 if (result != ISC_R_SUCCESS)
00376 fatal("%s: %s", msg, isc_result_totext(result));
00377 }
00378
00379 static void *
00380 mem_alloc(void *arg, size_t size) {
00381 return (isc_mem_get(arg, size));
00382 }
00383
00384 static void
00385 mem_free(void *arg, void *mem, size_t size) {
00386 isc_mem_put(arg, mem, size);
00387 }
00388
00389 static char *
00390 nsu_strsep(char **stringp, const char *delim) {
00391 char *string = *stringp;
00392 char *s;
00393 const char *d;
00394 char sc, dc;
00395
00396 if (string == NULL)
00397 return (NULL);
00398
00399 for (; *string != '\0'; string++) {
00400 sc = *string;
00401 for (d = delim; (dc = *d) != '\0'; d++) {
00402 if (sc == dc)
00403 break;
00404 }
00405 if (dc == 0)
00406 break;
00407 }
00408
00409 for (s = string; *s != '\0'; s++) {
00410 sc = *s;
00411 for (d = delim; (dc = *d) != '\0'; d++) {
00412 if (sc == dc) {
00413 *s++ = '\0';
00414 *stringp = s;
00415 return (string);
00416 }
00417 }
00418 }
00419 *stringp = NULL;
00420 return (string);
00421 }
00422
00423 static void
00424 reset_system(void) {
00425 isc_result_t result;
00426
00427 ddebug("reset_system()");
00428
00429 if (updatemsg != NULL)
00430 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
00431 else {
00432 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
00433 &updatemsg);
00434 check_result(result, "dns_message_create");
00435 }
00436 updatemsg->opcode = dns_opcode_update;
00437 if (usegsstsig) {
00438 if (tsigkey != NULL)
00439 dns_tsigkey_detach(&tsigkey);
00440 if (gssring != NULL)
00441 dns_tsigkeyring_detach(&gssring);
00442 tried_other_gsstsig = ISC_FALSE;
00443 }
00444 }
00445
00446 static isc_uint16_t
00447 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
00448 isc_uint16_t digestbits = 0;
00449 isc_result_t result;
00450 char buf[20];
00451
00452 REQUIRE(hmac != NULL && *hmac == NULL);
00453 REQUIRE(hmacstr != NULL);
00454
00455 if (len >= sizeof(buf))
00456 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
00457
00458 strncpy(buf, hmacstr, len);
00459 buf[len] = 0;
00460
00461 if (strcasecmp(buf, "hmac-md5") == 0) {
00462 *hmac = DNS_TSIG_HMACMD5_NAME;
00463 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
00464 *hmac = DNS_TSIG_HMACMD5_NAME;
00465 result = isc_parse_uint16(&digestbits, &buf[9], 10);
00466 if (result != ISC_R_SUCCESS || digestbits > 128)
00467 fatal("digest-bits out of range [0..128]");
00468 digestbits = (digestbits +7) & ~0x7U;
00469 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
00470 *hmac = DNS_TSIG_HMACSHA1_NAME;
00471 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
00472 *hmac = DNS_TSIG_HMACSHA1_NAME;
00473 result = isc_parse_uint16(&digestbits, &buf[10], 10);
00474 if (result != ISC_R_SUCCESS || digestbits > 160)
00475 fatal("digest-bits out of range [0..160]");
00476 digestbits = (digestbits +7) & ~0x7U;
00477 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
00478 *hmac = DNS_TSIG_HMACSHA224_NAME;
00479 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
00480 *hmac = DNS_TSIG_HMACSHA224_NAME;
00481 result = isc_parse_uint16(&digestbits, &buf[12], 10);
00482 if (result != ISC_R_SUCCESS || digestbits > 224)
00483 fatal("digest-bits out of range [0..224]");
00484 digestbits = (digestbits +7) & ~0x7U;
00485 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
00486 *hmac = DNS_TSIG_HMACSHA256_NAME;
00487 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
00488 *hmac = DNS_TSIG_HMACSHA256_NAME;
00489 result = isc_parse_uint16(&digestbits, &buf[12], 10);
00490 if (result != ISC_R_SUCCESS || digestbits > 256)
00491 fatal("digest-bits out of range [0..256]");
00492 digestbits = (digestbits +7) & ~0x7U;
00493 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
00494 *hmac = DNS_TSIG_HMACSHA384_NAME;
00495 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
00496 *hmac = DNS_TSIG_HMACSHA384_NAME;
00497 result = isc_parse_uint16(&digestbits, &buf[12], 10);
00498 if (result != ISC_R_SUCCESS || digestbits > 384)
00499 fatal("digest-bits out of range [0..384]");
00500 digestbits = (digestbits +7) & ~0x7U;
00501 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
00502 *hmac = DNS_TSIG_HMACSHA512_NAME;
00503 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
00504 *hmac = DNS_TSIG_HMACSHA512_NAME;
00505 result = isc_parse_uint16(&digestbits, &buf[12], 10);
00506 if (result != ISC_R_SUCCESS || digestbits > 512)
00507 fatal("digest-bits out of range [0..512]");
00508 digestbits = (digestbits +7) & ~0x7U;
00509 } else
00510 fatal("unknown key type '%s'", buf);
00511 return (digestbits);
00512 }
00513
00514 static int
00515 basenamelen(const char *file) {
00516 int len = strlen(file);
00517
00518 if (len > 1 && file[len - 1] == '.')
00519 len -= 1;
00520 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
00521 len -= 8;
00522 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
00523 len -= 4;
00524 return (len);
00525 }
00526
00527 static void
00528 setup_keystr(void) {
00529 unsigned char *secret = NULL;
00530 int secretlen;
00531 isc_buffer_t secretbuf;
00532 isc_result_t result;
00533 isc_buffer_t keynamesrc;
00534 char *secretstr;
00535 char *s, *n;
00536 dns_fixedname_t fkeyname;
00537 dns_name_t *mykeyname;
00538 char *name;
00539 dns_name_t *hmacname = NULL;
00540 isc_uint16_t digestbits = 0;
00541
00542 dns_fixedname_init(&fkeyname);
00543 mykeyname = dns_fixedname_name(&fkeyname);
00544
00545 debug("Creating key...");
00546
00547 s = strchr(keystr, ':');
00548 if (s == NULL || s == keystr || s[1] == 0)
00549 fatal("key option must specify [hmac:]keyname:secret");
00550 secretstr = s + 1;
00551 n = strchr(secretstr, ':');
00552 if (n != NULL) {
00553 if (n == secretstr || n[1] == 0)
00554 fatal("key option must specify [hmac:]keyname:secret");
00555 name = secretstr;
00556 secretstr = n + 1;
00557 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
00558 } else {
00559 hmacname = DNS_TSIG_HMACMD5_NAME;
00560 name = keystr;
00561 n = s;
00562 }
00563
00564 isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
00565 isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
00566
00567 debug("namefromtext");
00568 result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0,
00569 NULL);
00570 check_result(result, "dns_name_fromtext");
00571
00572 secretlen = strlen(secretstr) * 3 / 4;
00573 secret = isc_mem_allocate(gmctx, secretlen);
00574 if (secret == NULL)
00575 fatal("out of memory");
00576
00577 isc_buffer_init(&secretbuf, secret, secretlen);
00578 result = isc_base64_decodestring(secretstr, &secretbuf);
00579 if (result != ISC_R_SUCCESS) {
00580 fprintf(stderr, "could not create key from %s: %s\n",
00581 keystr, isc_result_totext(result));
00582 goto failure;
00583 }
00584
00585 secretlen = isc_buffer_usedlength(&secretbuf);
00586
00587 debug("keycreate");
00588 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
00589 ISC_FALSE, NULL, 0, 0, gmctx, NULL,
00590 &tsigkey);
00591 if (result != ISC_R_SUCCESS)
00592 fprintf(stderr, "could not create key from %s: %s\n",
00593 keystr, dns_result_totext(result));
00594 else
00595 dst_key_setbits(tsigkey->key, digestbits);
00596 failure:
00597 if (secret != NULL)
00598 isc_mem_free(gmctx, secret);
00599 }
00600
00601
00602
00603
00604 static isc_result_t
00605 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
00606 cfg_parser_t *pctx = NULL;
00607 cfg_obj_t *sessionkey = NULL;
00608 const cfg_obj_t *key = NULL;
00609 const cfg_obj_t *secretobj = NULL;
00610 const cfg_obj_t *algorithmobj = NULL;
00611 const char *mykeyname;
00612 const char *secretstr;
00613 const char *algorithm;
00614 isc_result_t result;
00615 int len;
00616
00617 if (! isc_file_exists(keyfile))
00618 return (ISC_R_FILENOTFOUND);
00619
00620 result = cfg_parser_create(mctx, lctx, &pctx);
00621 if (result != ISC_R_SUCCESS)
00622 goto cleanup;
00623
00624 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
00625 &sessionkey);
00626 if (result != ISC_R_SUCCESS)
00627 goto cleanup;
00628
00629 result = cfg_map_get(sessionkey, "key", &key);
00630 if (result != ISC_R_SUCCESS)
00631 goto cleanup;
00632
00633 (void) cfg_map_get(key, "secret", &secretobj);
00634 (void) cfg_map_get(key, "algorithm", &algorithmobj);
00635 if (secretobj == NULL || algorithmobj == NULL)
00636 fatal("key must have algorithm and secret");
00637
00638 mykeyname = cfg_obj_asstring(cfg_map_getname(key));
00639 secretstr = cfg_obj_asstring(secretobj);
00640 algorithm = cfg_obj_asstring(algorithmobj);
00641
00642 len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3;
00643 keystr = isc_mem_allocate(mctx, len);
00644 snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr);
00645 setup_keystr();
00646
00647 cleanup:
00648 if (pctx != NULL) {
00649 if (sessionkey != NULL)
00650 cfg_obj_destroy(pctx, &sessionkey);
00651 cfg_parser_destroy(&pctx);
00652 }
00653
00654 if (keystr != NULL)
00655 isc_mem_free(mctx, keystr);
00656
00657 return (result);
00658 }
00659
00660 static void
00661 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
00662 dst_key_t *dstkey = NULL;
00663 isc_result_t result;
00664 dns_name_t *hmacname = NULL;
00665
00666 debug("Creating key...");
00667
00668 if (sig0key != NULL)
00669 dst_key_free(&sig0key);
00670
00671
00672 result = dst_key_fromnamedfile(keyfile, NULL,
00673 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
00674 &dstkey);
00675
00676
00677 if (result != ISC_R_SUCCESS) {
00678 result = read_sessionkey(mctx, lctx);
00679 if (result == ISC_R_SUCCESS)
00680 return;
00681 }
00682
00683 if (result != ISC_R_SUCCESS) {
00684 fprintf(stderr, "could not read key from %.*s.{private,key}: "
00685 "%s\n", basenamelen(keyfile), keyfile,
00686 isc_result_totext(result));
00687 return;
00688 }
00689
00690 switch (dst_key_alg(dstkey)) {
00691 case DST_ALG_HMACMD5:
00692 hmacname = DNS_TSIG_HMACMD5_NAME;
00693 break;
00694 case DST_ALG_HMACSHA1:
00695 hmacname = DNS_TSIG_HMACSHA1_NAME;
00696 break;
00697 case DST_ALG_HMACSHA224:
00698 hmacname = DNS_TSIG_HMACSHA224_NAME;
00699 break;
00700 case DST_ALG_HMACSHA256:
00701 hmacname = DNS_TSIG_HMACSHA256_NAME;
00702 break;
00703 case DST_ALG_HMACSHA384:
00704 hmacname = DNS_TSIG_HMACSHA384_NAME;
00705 break;
00706 case DST_ALG_HMACSHA512:
00707 hmacname = DNS_TSIG_HMACSHA512_NAME;
00708 break;
00709 }
00710 if (hmacname != NULL) {
00711 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
00712 hmacname, dstkey, ISC_FALSE,
00713 NULL, 0, 0, mctx, NULL,
00714 &tsigkey);
00715 dst_key_free(&dstkey);
00716 if (result != ISC_R_SUCCESS) {
00717 fprintf(stderr, "could not create key from %s: %s\n",
00718 keyfile, isc_result_totext(result));
00719 return;
00720 }
00721 } else {
00722 dst_key_attach(dstkey, &sig0key);
00723 dst_key_free(&dstkey);
00724 }
00725 }
00726
00727 static void
00728 doshutdown(void) {
00729 isc_task_detach(&global_task);
00730
00731
00732
00733
00734
00735
00736 if (master_servers != NULL && master_servers != servers)
00737 isc_mem_put(gmctx, master_servers,
00738 master_total * sizeof(isc_sockaddr_t));
00739
00740 if (servers != NULL)
00741 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
00742
00743 if (localaddr4 != NULL)
00744 isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
00745
00746 if (localaddr6 != NULL)
00747 isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t));
00748
00749 if (tsigkey != NULL) {
00750 ddebug("Freeing TSIG key");
00751 dns_tsigkey_detach(&tsigkey);
00752 }
00753
00754 if (sig0key != NULL) {
00755 ddebug("Freeing SIG(0) key");
00756 dst_key_free(&sig0key);
00757 }
00758
00759 if (updatemsg != NULL)
00760 dns_message_destroy(&updatemsg);
00761
00762 if (is_dst_up) {
00763 ddebug("Destroy DST lib");
00764 dst_lib_destroy();
00765 is_dst_up = ISC_FALSE;
00766 }
00767
00768 cleanup_entropy(&entropy);
00769
00770 lwres_conf_clear(lwctx);
00771 lwres_context_destroy(&lwctx);
00772
00773 ddebug("Destroying request manager");
00774 dns_requestmgr_detach(&requestmgr);
00775
00776 ddebug("Freeing the dispatchers");
00777 if (have_ipv4)
00778 dns_dispatch_detach(&dispatchv4);
00779 if (have_ipv6)
00780 dns_dispatch_detach(&dispatchv6);
00781
00782 ddebug("Shutting down dispatch manager");
00783 dns_dispatchmgr_destroy(&dispatchmgr);
00784
00785 }
00786
00787 static void
00788 maybeshutdown(void) {
00789 ddebug("Shutting down request manager");
00790 dns_requestmgr_shutdown(requestmgr);
00791
00792 if (requests != 0)
00793 return;
00794
00795 doshutdown();
00796 }
00797
00798 static void
00799 shutdown_program(isc_task_t *task, isc_event_t *event) {
00800 REQUIRE(task == global_task);
00801 UNUSED(task);
00802
00803 ddebug("shutdown_program()");
00804 isc_event_free(&event);
00805
00806 shuttingdown = ISC_TRUE;
00807 maybeshutdown();
00808 }
00809
00810 static void
00811 setup_system(void) {
00812 isc_result_t result;
00813 isc_sockaddr_t bind_any, bind_any6;
00814 lwres_result_t lwresult;
00815 unsigned int attrs, attrmask;
00816 int i;
00817 isc_logconfig_t *logconfig = NULL;
00818
00819 ddebug("setup_system()");
00820
00821 dns_result_register();
00822
00823 result = isc_net_probeipv4();
00824 if (result == ISC_R_SUCCESS)
00825 have_ipv4 = ISC_TRUE;
00826
00827 result = isc_net_probeipv6();
00828 if (result == ISC_R_SUCCESS)
00829 have_ipv6 = ISC_TRUE;
00830
00831 if (!have_ipv4 && !have_ipv6)
00832 fatal("could not find either IPv4 or IPv6");
00833
00834 result = isc_log_create(gmctx, &glctx, &logconfig);
00835 check_result(result, "isc_log_create");
00836
00837 isc_log_setcontext(glctx);
00838 dns_log_init(glctx);
00839 dns_log_setcontext(glctx);
00840
00841 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
00842 check_result(result, "isc_log_usechannel");
00843
00844 isc_log_setdebuglevel(glctx, logdebuglevel);
00845
00846 lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free, 1);
00847 if (lwresult != LWRES_R_SUCCESS)
00848 fatal("lwres_context_create failed");
00849
00850 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
00851 lwconf = lwres_conf_get(lwctx);
00852
00853 if (servers != NULL) {
00854 if (master_servers == servers)
00855 master_servers = NULL;
00856 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
00857 }
00858
00859 ns_inuse = 0;
00860 if (local_only || lwconf->nsnext <= 0) {
00861 struct in_addr in;
00862 struct in6_addr in6;
00863
00864 if (local_only && keyfile == NULL)
00865 keyfile = SESSION_KEYFILE;
00866
00867 default_servers = !local_only;
00868
00869 ns_total = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
00870 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
00871 if (servers == NULL)
00872 fatal("out of memory");
00873
00874 if (have_ipv4) {
00875 in.s_addr = htonl(INADDR_LOOPBACK);
00876 isc_sockaddr_fromin(&servers[0], &in, dnsport);
00877 }
00878 if (have_ipv6) {
00879 memset(&in6, 0, sizeof(in6));
00880 in6.s6_addr[15] = 1;
00881 isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)],
00882 &in6, dnsport);
00883 }
00884 } else {
00885 ns_total = lwconf->nsnext;
00886 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
00887 if (servers == NULL)
00888 fatal("out of memory");
00889 for (i = 0; i < ns_total; i++) {
00890 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4)
00891 {
00892 struct in_addr in4;
00893 memmove(&in4,
00894 lwconf->nameservers[i].address, 4);
00895 isc_sockaddr_fromin(&servers[i],
00896 &in4, dnsport);
00897 } else {
00898 struct in6_addr in6;
00899 memmove(&in6,
00900 lwconf->nameservers[i].address, 16);
00901 isc_sockaddr_fromin6(&servers[i],
00902 &in6, dnsport);
00903 }
00904 }
00905 }
00906
00907 setup_entropy(gmctx, NULL, &entropy);
00908
00909 result = isc_hash_create(gmctx, entropy, DNS_NAME_MAXWIRE);
00910 check_result(result, "isc_hash_create");
00911 isc_hash_init();
00912
00913 result = dns_dispatchmgr_create(gmctx, entropy, &dispatchmgr);
00914 check_result(result, "dns_dispatchmgr_create");
00915
00916 result = isc_socketmgr_create(gmctx, &socketmgr);
00917 check_result(result, "dns_socketmgr_create");
00918
00919 result = isc_timermgr_create(gmctx, &timermgr);
00920 check_result(result, "dns_timermgr_create");
00921
00922 result = isc_taskmgr_create(gmctx, 1, 0, &taskmgr);
00923 check_result(result, "isc_taskmgr_create");
00924
00925 result = isc_task_create(taskmgr, 0, &global_task);
00926 check_result(result, "isc_task_create");
00927
00928 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
00929 check_result(result, "isc_task_onshutdown");
00930
00931 result = dst_lib_init(gmctx, entropy, 0);
00932 check_result(result, "dst_lib_init");
00933 is_dst_up = ISC_TRUE;
00934
00935 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
00936 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
00937
00938 if (have_ipv6) {
00939 attrs = DNS_DISPATCHATTR_UDP;
00940 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
00941 attrs |= DNS_DISPATCHATTR_IPV6;
00942 isc_sockaddr_any6(&bind_any6);
00943 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
00944 &bind_any6, PACKETSIZE,
00945 4, 2, 3, 5,
00946 attrs, attrmask, &dispatchv6);
00947 check_result(result, "dns_dispatch_getudp (v6)");
00948 }
00949
00950 if (have_ipv4) {
00951 attrs = DNS_DISPATCHATTR_UDP;
00952 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
00953 attrs |= DNS_DISPATCHATTR_IPV4;
00954 isc_sockaddr_any(&bind_any);
00955 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
00956 &bind_any, PACKETSIZE,
00957 4, 2, 3, 5,
00958 attrs, attrmask, &dispatchv4);
00959 check_result(result, "dns_dispatch_getudp (v4)");
00960 }
00961
00962 result = dns_requestmgr_create(gmctx, timermgr,
00963 socketmgr, taskmgr, dispatchmgr,
00964 dispatchv4, dispatchv6, &requestmgr);
00965 check_result(result, "dns_requestmgr_create");
00966
00967 if (keystr != NULL)
00968 setup_keystr();
00969 else if (local_only) {
00970 result = read_sessionkey(gmctx, glctx);
00971 if (result != ISC_R_SUCCESS)
00972 fatal("can't read key from %s: %s\n",
00973 keyfile, isc_result_totext(result));
00974 } else if (keyfile != NULL)
00975 setup_keyfile(gmctx, glctx);
00976 }
00977
00978 static void
00979 get_addresses(char *host, in_port_t port,
00980 isc_sockaddr_t *sockaddr, int naddrs)
00981 {
00982 int count;
00983 isc_result_t result;
00984
00985 isc_app_block();
00986 result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
00987 isc_app_unblock();
00988 if (result != ISC_R_SUCCESS)
00989 fatal("couldn't get address for '%s': %s",
00990 host, isc_result_totext(result));
00991 }
00992
00993 static void
00994 version(void) {
00995 fputs("nsupdate " VERSION "\n", stderr);
00996 }
00997
00998 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:Pr:R::t:Tu:V"
00999
01000 static void
01001 pre_parse_args(int argc, char **argv) {
01002 dns_rdatatype_t t;
01003 int ch;
01004 char buf[100];
01005 isc_boolean_t doexit = ISC_FALSE;
01006
01007 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
01008 switch (ch) {
01009 case 'M':
01010 debugging = ISC_TRUE;
01011 ddebugging = ISC_TRUE;
01012 memdebugging = ISC_TRUE;
01013 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
01014 ISC_MEM_DEBUGRECORD;
01015 break;
01016
01017 case '?':
01018 case 'h':
01019 if (isc_commandline_option != '?')
01020 fprintf(stderr, "%s: invalid argument -%c\n",
01021 argv[0], isc_commandline_option);
01022 fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
01023 "[-g | -o | -y keyname:secret | -k keyfile] "
01024 "[-v] [-V] [filename]\n");
01025 exit(1);
01026
01027 case 'P':
01028 for (t = 0xff00; t <= 0xfffe; t++) {
01029 if (dns_rdatatype_ismeta(t))
01030 continue;
01031 dns_rdatatype_format(t, buf, sizeof(buf));
01032 if (strncmp(buf, "TYPE", 4) != 0)
01033 fprintf(stdout, "%s\n", buf);
01034 }
01035 doexit = ISC_TRUE;
01036 break;
01037
01038 case 'T':
01039 for (t = 1; t <= 0xfeff; t++) {
01040 if (dns_rdatatype_ismeta(t))
01041 continue;
01042 dns_rdatatype_format(t, buf, sizeof(buf));
01043 if (strncmp(buf, "TYPE", 4) != 0)
01044 fprintf(stdout, "%s\n", buf);
01045 }
01046 doexit = ISC_TRUE;
01047 break;
01048
01049 case 'V':
01050 version();
01051 doexit = ISC_TRUE;
01052 break;
01053
01054 default:
01055 break;
01056 }
01057 }
01058 if (doexit)
01059 exit(0);
01060 isc_commandline_reset = ISC_TRUE;
01061 isc_commandline_index = 1;
01062 }
01063
01064 static void
01065 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
01066 int ch;
01067 isc_uint32_t i;
01068 isc_result_t result;
01069
01070 debug("parse_args");
01071 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
01072 switch (ch) {
01073 case 'd':
01074 debugging = ISC_TRUE;
01075 break;
01076 case 'D':
01077 debugging = ISC_TRUE;
01078 ddebugging = ISC_TRUE;
01079 break;
01080 case 'M':
01081 break;
01082 case 'l':
01083 local_only = ISC_TRUE;
01084 break;
01085 case 'L':
01086 result = isc_parse_uint32(&i, isc_commandline_argument,
01087 10);
01088 if (result != ISC_R_SUCCESS) {
01089 fprintf(stderr, "bad library debug value "
01090 "'%s'\n", isc_commandline_argument);
01091 exit(1);
01092 }
01093 logdebuglevel = i;
01094 break;
01095 case 'y':
01096 keystr = isc_commandline_argument;
01097 break;
01098 case 'v':
01099 usevc = ISC_TRUE;
01100 break;
01101 case 'k':
01102 keyfile = isc_commandline_argument;
01103 break;
01104 case 'g':
01105 usegsstsig = ISC_TRUE;
01106 use_win2k_gsstsig = ISC_FALSE;
01107 break;
01108 case 'o':
01109 usegsstsig = ISC_TRUE;
01110 use_win2k_gsstsig = ISC_TRUE;
01111 break;
01112 case 'p':
01113 result = isc_parse_uint16(&dnsport,
01114 isc_commandline_argument, 10);
01115 if (result != ISC_R_SUCCESS) {
01116 fprintf(stderr, "bad port number "
01117 "'%s'\n", isc_commandline_argument);
01118 exit(1);
01119 }
01120 break;
01121 case 't':
01122 result = isc_parse_uint32(&timeout,
01123 isc_commandline_argument, 10);
01124 if (result != ISC_R_SUCCESS) {
01125 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
01126 exit(1);
01127 }
01128 if (timeout == 0)
01129 timeout = UINT_MAX;
01130 break;
01131 case 'u':
01132 result = isc_parse_uint32(&udp_timeout,
01133 isc_commandline_argument, 10);
01134 if (result != ISC_R_SUCCESS) {
01135 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
01136 exit(1);
01137 }
01138 if (udp_timeout == 0)
01139 udp_timeout = UINT_MAX;
01140 break;
01141 case 'r':
01142 result = isc_parse_uint32(&udp_retries,
01143 isc_commandline_argument, 10);
01144 if (result != ISC_R_SUCCESS) {
01145 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
01146 exit(1);
01147 }
01148 break;
01149
01150 case 'R':
01151 setup_entropy(mctx, isc_commandline_argument, ectx);
01152 break;
01153
01154 default:
01155 fprintf(stderr, "%s: unhandled option: %c\n",
01156 argv[0], isc_commandline_option);
01157 exit(1);
01158 }
01159 }
01160 if (keyfile != NULL && keystr != NULL) {
01161 fprintf(stderr, "%s: cannot specify both -k and -y\n",
01162 argv[0]);
01163 exit(1);
01164 }
01165
01166 #ifdef GSSAPI
01167 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
01168 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
01169 argv[0]);
01170 exit(1);
01171 }
01172 #else
01173 if (usegsstsig) {
01174 fprintf(stderr, "%s: cannot specify -g or -o, " \
01175 "program not linked with GSS API Library\n",
01176 argv[0]);
01177 exit(1);
01178 }
01179 #endif
01180
01181 if (argv[isc_commandline_index] != NULL) {
01182 if (strcmp(argv[isc_commandline_index], "-") == 0) {
01183 input = stdin;
01184 } else {
01185 result = isc_stdio_open(argv[isc_commandline_index],
01186 "r", &input);
01187 if (result != ISC_R_SUCCESS) {
01188 fprintf(stderr, "could not open '%s': %s\n",
01189 argv[isc_commandline_index],
01190 isc_result_totext(result));
01191 exit(1);
01192 }
01193 }
01194 interactive = ISC_FALSE;
01195 }
01196 }
01197
01198 static isc_uint16_t
01199 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
01200 isc_result_t result;
01201 char *word;
01202 isc_buffer_t *namebuf = NULL;
01203 isc_buffer_t source;
01204
01205 word = nsu_strsep(cmdlinep, " \t\r\n");
01206 if (word == NULL || *word == 0) {
01207 fprintf(stderr, "could not read owner name\n");
01208 return (STATUS_SYNTAX);
01209 }
01210
01211 result = dns_message_gettempname(msg, namep);
01212 check_result(result, "dns_message_gettempname");
01213 result = isc_buffer_allocate(gmctx, &namebuf, DNS_NAME_MAXWIRE);
01214 check_result(result, "isc_buffer_allocate");
01215 dns_name_init(*namep, NULL);
01216 dns_name_setbuffer(*namep, namebuf);
01217 dns_message_takebuffer(msg, &namebuf);
01218 isc_buffer_init(&source, word, strlen(word));
01219 isc_buffer_add(&source, strlen(word));
01220 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
01221 check_result(result, "dns_name_fromtext");
01222 isc_buffer_invalidate(&source);
01223 return (STATUS_MORE);
01224 }
01225
01226 static isc_uint16_t
01227 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
01228 dns_rdatatype_t rdatatype, dns_message_t *msg,
01229 dns_rdata_t *rdata)
01230 {
01231 char *cmdline = *cmdlinep;
01232 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
01233 isc_region_t r;
01234 isc_lex_t *lex = NULL;
01235 dns_rdatacallbacks_t callbacks;
01236 isc_result_t result;
01237
01238 if (cmdline == NULL) {
01239 rdata->flags = DNS_RDATA_UPDATE;
01240 return (STATUS_MORE);
01241 }
01242
01243 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
01244 cmdline++;
01245
01246 if (*cmdline != 0) {
01247 dns_rdatacallbacks_init(&callbacks);
01248 result = isc_lex_create(gmctx, strlen(cmdline), &lex);
01249 check_result(result, "isc_lex_create");
01250 isc_buffer_init(&source, cmdline, strlen(cmdline));
01251 isc_buffer_add(&source, strlen(cmdline));
01252 result = isc_lex_openbuffer(lex, &source);
01253 check_result(result, "isc_lex_openbuffer");
01254 result = isc_buffer_allocate(gmctx, &buf, MAXWIRE);
01255 check_result(result, "isc_buffer_allocate");
01256 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
01257 dns_rootname, 0, gmctx, buf,
01258 &callbacks);
01259 isc_lex_destroy(&lex);
01260 if (result == ISC_R_SUCCESS) {
01261 isc_buffer_usedregion(buf, &r);
01262 result = isc_buffer_allocate(gmctx, &newbuf, r.length);
01263 check_result(result, "isc_buffer_allocate");
01264 isc_buffer_putmem(newbuf, r.base, r.length);
01265 isc_buffer_usedregion(newbuf, &r);
01266 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
01267 isc_buffer_free(&buf);
01268 dns_message_takebuffer(msg, &newbuf);
01269 } else {
01270 fprintf(stderr, "invalid rdata format: %s\n",
01271 isc_result_totext(result));
01272 isc_buffer_free(&buf);
01273 return (STATUS_SYNTAX);
01274 }
01275 } else {
01276 rdata->flags = DNS_RDATA_UPDATE;
01277 }
01278 *cmdlinep = cmdline;
01279 return (STATUS_MORE);
01280 }
01281
01282 static isc_uint16_t
01283 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
01284 isc_result_t result;
01285 char *word;
01286 dns_name_t *name = NULL;
01287 isc_textregion_t region;
01288 dns_rdataset_t *rdataset = NULL;
01289 dns_rdatalist_t *rdatalist = NULL;
01290 dns_rdataclass_t rdataclass;
01291 dns_rdatatype_t rdatatype;
01292 dns_rdata_t *rdata = NULL;
01293 isc_uint16_t retval;
01294
01295 ddebug("make_prereq()");
01296
01297
01298
01299
01300 retval = parse_name(&cmdline, updatemsg, &name);
01301 if (retval != STATUS_MORE)
01302 return (retval);
01303
01304
01305
01306
01307 if (isrrset) {
01308 word = nsu_strsep(&cmdline, " \t\r\n");
01309 if (word == NULL || *word == 0) {
01310 fprintf(stderr, "could not read class or type\n");
01311 goto failure;
01312 }
01313 region.base = word;
01314 region.length = strlen(word);
01315 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
01316 if (result == ISC_R_SUCCESS) {
01317 if (!setzoneclass(rdataclass)) {
01318 fprintf(stderr, "class mismatch: %s\n", word);
01319 goto failure;
01320 }
01321
01322
01323
01324 word = nsu_strsep(&cmdline, " \t\r\n");
01325 if (word == NULL || *word == 0) {
01326 fprintf(stderr, "could not read type\n");
01327 goto failure;
01328 }
01329 region.base = word;
01330 region.length = strlen(word);
01331 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
01332 if (result != ISC_R_SUCCESS) {
01333 fprintf(stderr, "invalid type: %s\n", word);
01334 goto failure;
01335 }
01336 } else {
01337 rdataclass = getzoneclass();
01338 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
01339 if (result != ISC_R_SUCCESS) {
01340 fprintf(stderr, "invalid type: %s\n", word);
01341 goto failure;
01342 }
01343 }
01344 } else
01345 rdatatype = dns_rdatatype_any;
01346
01347 result = dns_message_gettemprdata(updatemsg, &rdata);
01348 check_result(result, "dns_message_gettemprdata");
01349
01350 dns_rdata_init(rdata);
01351
01352 if (isrrset && ispositive) {
01353 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
01354 updatemsg, rdata);
01355 if (retval != STATUS_MORE)
01356 goto failure;
01357 } else
01358 rdata->flags = DNS_RDATA_UPDATE;
01359
01360 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
01361 check_result(result, "dns_message_gettemprdatalist");
01362 result = dns_message_gettemprdataset(updatemsg, &rdataset);
01363 check_result(result, "dns_message_gettemprdataset");
01364 rdatalist->type = rdatatype;
01365 if (ispositive) {
01366 if (isrrset && rdata->data != NULL)
01367 rdatalist->rdclass = rdataclass;
01368 else
01369 rdatalist->rdclass = dns_rdataclass_any;
01370 } else
01371 rdatalist->rdclass = dns_rdataclass_none;
01372 rdata->rdclass = rdatalist->rdclass;
01373 rdata->type = rdatatype;
01374 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
01375 dns_rdataset_init(rdataset);
01376 dns_rdatalist_tordataset(rdatalist, rdataset);
01377 ISC_LIST_INIT(name->list);
01378 ISC_LIST_APPEND(name->list, rdataset, link);
01379 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
01380 return (STATUS_MORE);
01381
01382 failure:
01383 if (name != NULL)
01384 dns_message_puttempname(updatemsg, &name);
01385 return (STATUS_SYNTAX);
01386 }
01387
01388 static isc_uint16_t
01389 evaluate_prereq(char *cmdline) {
01390 char *word;
01391 isc_boolean_t ispositive, isrrset;
01392
01393 ddebug("evaluate_prereq()");
01394 word = nsu_strsep(&cmdline, " \t\r\n");
01395 if (word == NULL || *word == 0) {
01396 fprintf(stderr, "could not read operation code\n");
01397 return (STATUS_SYNTAX);
01398 }
01399 if (strcasecmp(word, "nxdomain") == 0) {
01400 ispositive = ISC_FALSE;
01401 isrrset = ISC_FALSE;
01402 } else if (strcasecmp(word, "yxdomain") == 0) {
01403 ispositive = ISC_TRUE;
01404 isrrset = ISC_FALSE;
01405 } else if (strcasecmp(word, "nxrrset") == 0) {
01406 ispositive = ISC_FALSE;
01407 isrrset = ISC_TRUE;
01408 } else if (strcasecmp(word, "yxrrset") == 0) {
01409 ispositive = ISC_TRUE;
01410 isrrset = ISC_TRUE;
01411 } else {
01412 fprintf(stderr, "incorrect operation code: %s\n", word);
01413 return (STATUS_SYNTAX);
01414 }
01415 return (make_prereq(cmdline, ispositive, isrrset));
01416 }
01417
01418 static isc_uint16_t
01419 evaluate_server(char *cmdline) {
01420 char *word, *server;
01421 long port;
01422
01423 if (local_only) {
01424 fprintf(stderr, "cannot reset server in localhost-only mode\n");
01425 return (STATUS_SYNTAX);
01426 }
01427
01428 word = nsu_strsep(&cmdline, " \t\r\n");
01429 if (word == NULL || *word == 0) {
01430 fprintf(stderr, "could not read server name\n");
01431 return (STATUS_SYNTAX);
01432 }
01433 server = word;
01434
01435 word = nsu_strsep(&cmdline, " \t\r\n");
01436 if (word == NULL || *word == 0)
01437 port = dnsport;
01438 else {
01439 char *endp;
01440 port = strtol(word, &endp, 10);
01441 if (*endp != 0) {
01442 fprintf(stderr, "port '%s' is not numeric\n", word);
01443 return (STATUS_SYNTAX);
01444 } else if (port < 1 || port > 65535) {
01445 fprintf(stderr, "port '%s' is out of range "
01446 "(1 to 65535)\n", word);
01447 return (STATUS_SYNTAX);
01448 }
01449 }
01450
01451 if (servers != NULL) {
01452 if (master_servers == servers)
01453 master_servers = NULL;
01454 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
01455 }
01456
01457 default_servers = ISC_FALSE;
01458
01459 ns_total = MAX_SERVERADDRS;
01460 ns_inuse = 0;
01461 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
01462 if (servers == NULL)
01463 fatal("out of memory");
01464
01465 memset(servers, 0, ns_total * sizeof(isc_sockaddr_t));
01466 get_addresses(server, (in_port_t)port, servers, ns_total);
01467
01468 return (STATUS_MORE);
01469 }
01470
01471 static isc_uint16_t
01472 evaluate_local(char *cmdline) {
01473 char *word, *local;
01474 long port;
01475 struct in_addr in4;
01476 struct in6_addr in6;
01477
01478 word = nsu_strsep(&cmdline, " \t\r\n");
01479 if (word == NULL || *word == 0) {
01480 fprintf(stderr, "could not read server name\n");
01481 return (STATUS_SYNTAX);
01482 }
01483 local = word;
01484
01485 word = nsu_strsep(&cmdline, " \t\r\n");
01486 if (word == NULL || *word == 0)
01487 port = 0;
01488 else {
01489 char *endp;
01490 port = strtol(word, &endp, 10);
01491 if (*endp != 0) {
01492 fprintf(stderr, "port '%s' is not numeric\n", word);
01493 return (STATUS_SYNTAX);
01494 } else if (port < 1 || port > 65535) {
01495 fprintf(stderr, "port '%s' is out of range "
01496 "(1 to 65535)\n", word);
01497 return (STATUS_SYNTAX);
01498 }
01499 }
01500
01501 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) {
01502 if (localaddr6 == NULL)
01503 localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
01504 if (localaddr6 == NULL)
01505 fatal("out of memory");
01506 isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port);
01507 } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) {
01508 if (localaddr4 == NULL)
01509 localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
01510 if (localaddr4 == NULL)
01511 fatal("out of memory");
01512 isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port);
01513 } else {
01514 fprintf(stderr, "invalid address %s", local);
01515 return (STATUS_SYNTAX);
01516 }
01517
01518 return (STATUS_MORE);
01519 }
01520
01521 static isc_uint16_t
01522 evaluate_key(char *cmdline) {
01523 char *namestr;
01524 char *secretstr;
01525 isc_buffer_t b;
01526 isc_result_t result;
01527 dns_fixedname_t fkeyname;
01528 dns_name_t *mykeyname;
01529 int secretlen;
01530 unsigned char *secret = NULL;
01531 isc_buffer_t secretbuf;
01532 dns_name_t *hmacname = NULL;
01533 isc_uint16_t digestbits = 0;
01534 char *n;
01535
01536 namestr = nsu_strsep(&cmdline, " \t\r\n");
01537 if (namestr == NULL || *namestr == 0) {
01538 fprintf(stderr, "could not read key name\n");
01539 return (STATUS_SYNTAX);
01540 }
01541
01542 dns_fixedname_init(&fkeyname);
01543 mykeyname = dns_fixedname_name(&fkeyname);
01544
01545 n = strchr(namestr, ':');
01546 if (n != NULL) {
01547 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
01548 namestr = n + 1;
01549 } else
01550 hmacname = DNS_TSIG_HMACMD5_NAME;
01551
01552 isc_buffer_init(&b, namestr, strlen(namestr));
01553 isc_buffer_add(&b, strlen(namestr));
01554 result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL);
01555 if (result != ISC_R_SUCCESS) {
01556 fprintf(stderr, "could not parse key name\n");
01557 return (STATUS_SYNTAX);
01558 }
01559
01560 secretstr = nsu_strsep(&cmdline, "\r\n");
01561 if (secretstr == NULL || *secretstr == 0) {
01562 fprintf(stderr, "could not read key secret\n");
01563 return (STATUS_SYNTAX);
01564 }
01565 secretlen = strlen(secretstr) * 3 / 4;
01566 secret = isc_mem_allocate(gmctx, secretlen);
01567 if (secret == NULL)
01568 fatal("out of memory");
01569
01570 isc_buffer_init(&secretbuf, secret, secretlen);
01571 result = isc_base64_decodestring(secretstr, &secretbuf);
01572 if (result != ISC_R_SUCCESS) {
01573 fprintf(stderr, "could not create key from %s: %s\n",
01574 secretstr, isc_result_totext(result));
01575 isc_mem_free(gmctx, secret);
01576 return (STATUS_SYNTAX);
01577 }
01578 secretlen = isc_buffer_usedlength(&secretbuf);
01579
01580 if (tsigkey != NULL)
01581 dns_tsigkey_detach(&tsigkey);
01582 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
01583 ISC_FALSE, NULL, 0, 0, gmctx, NULL,
01584 &tsigkey);
01585 isc_mem_free(gmctx, secret);
01586 if (result != ISC_R_SUCCESS) {
01587 fprintf(stderr, "could not create key from %s %s: %s\n",
01588 namestr, secretstr, dns_result_totext(result));
01589 return (STATUS_SYNTAX);
01590 }
01591 dst_key_setbits(tsigkey->key, digestbits);
01592 return (STATUS_MORE);
01593 }
01594
01595 static isc_uint16_t
01596 evaluate_zone(char *cmdline) {
01597 char *word;
01598 isc_buffer_t b;
01599 isc_result_t result;
01600
01601 word = nsu_strsep(&cmdline, " \t\r\n");
01602 if (word == NULL || *word == 0) {
01603 fprintf(stderr, "could not read zone name\n");
01604 return (STATUS_SYNTAX);
01605 }
01606
01607 dns_fixedname_init(&fuserzone);
01608 userzone = dns_fixedname_name(&fuserzone);
01609 isc_buffer_init(&b, word, strlen(word));
01610 isc_buffer_add(&b, strlen(word));
01611 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
01612 if (result != ISC_R_SUCCESS) {
01613 userzone = NULL;
01614 fprintf(stderr, "could not parse zone name\n");
01615 return (STATUS_SYNTAX);
01616 }
01617
01618 return (STATUS_MORE);
01619 }
01620
01621 static isc_uint16_t
01622 evaluate_realm(char *cmdline) {
01623 #ifdef GSSAPI
01624 char *word;
01625 char buf[1024];
01626 int n;
01627
01628 if (realm != NULL) {
01629 isc_mem_free(gmctx, realm);
01630 realm = NULL;
01631 }
01632
01633 word = nsu_strsep(&cmdline, " \t\r\n");
01634 if (word == NULL || *word == 0)
01635 return (STATUS_MORE);
01636
01637 n = snprintf(buf, sizeof(buf), "@%s", word);
01638 if (n < 0 || (size_t)n >= sizeof(buf))
01639 fatal("realm is too long");
01640 realm = isc_mem_strdup(gmctx, buf);
01641 if (realm == NULL)
01642 fatal("out of memory");
01643 return (STATUS_MORE);
01644 #else
01645 UNUSED(cmdline);
01646 return (STATUS_SYNTAX);
01647 #endif
01648 }
01649
01650 static isc_uint16_t
01651 evaluate_ttl(char *cmdline) {
01652 char *word;
01653 isc_result_t result;
01654 isc_uint32_t ttl;
01655
01656 word = nsu_strsep(&cmdline, " \t\r\n");
01657 if (word == NULL || *word == 0) {
01658 fprintf(stderr, "could not ttl\n");
01659 return (STATUS_SYNTAX);
01660 }
01661
01662 if (!strcasecmp(word, "none")) {
01663 default_ttl = 0;
01664 default_ttl_set = ISC_FALSE;
01665 return (STATUS_MORE);
01666 }
01667
01668 result = isc_parse_uint32(&ttl, word, 10);
01669 if (result != ISC_R_SUCCESS)
01670 return (STATUS_SYNTAX);
01671
01672 if (ttl > TTL_MAX) {
01673 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
01674 word, TTL_MAX);
01675 return (STATUS_SYNTAX);
01676 }
01677 default_ttl = ttl;
01678 default_ttl_set = ISC_TRUE;
01679
01680 return (STATUS_MORE);
01681 }
01682
01683 static isc_uint16_t
01684 evaluate_class(char *cmdline) {
01685 char *word;
01686 isc_textregion_t r;
01687 isc_result_t result;
01688 dns_rdataclass_t rdclass;
01689
01690 word = nsu_strsep(&cmdline, " \t\r\n");
01691 if (word == NULL || *word == 0) {
01692 fprintf(stderr, "could not read class name\n");
01693 return (STATUS_SYNTAX);
01694 }
01695
01696 r.base = word;
01697 r.length = strlen(word);
01698 result = dns_rdataclass_fromtext(&rdclass, &r);
01699 if (result != ISC_R_SUCCESS) {
01700 fprintf(stderr, "could not parse class name: %s\n", word);
01701 return (STATUS_SYNTAX);
01702 }
01703 switch (rdclass) {
01704 case dns_rdataclass_none:
01705 case dns_rdataclass_any:
01706 case dns_rdataclass_reserved0:
01707 fprintf(stderr, "bad default class: %s\n", word);
01708 return (STATUS_SYNTAX);
01709 default:
01710 defaultclass = rdclass;
01711 }
01712
01713 return (STATUS_MORE);
01714 }
01715
01716 static isc_uint16_t
01717 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
01718 isc_result_t result;
01719 dns_name_t *name = NULL;
01720 isc_uint32_t ttl;
01721 char *word;
01722 dns_rdataclass_t rdataclass;
01723 dns_rdatatype_t rdatatype;
01724 dns_rdata_t *rdata = NULL;
01725 dns_rdatalist_t *rdatalist = NULL;
01726 dns_rdataset_t *rdataset = NULL;
01727 isc_textregion_t region;
01728 isc_uint16_t retval;
01729
01730 ddebug("update_addordelete()");
01731
01732
01733
01734
01735 retval = parse_name(&cmdline, updatemsg, &name);
01736 if (retval != STATUS_MORE)
01737 return (retval);
01738
01739 result = dns_message_gettemprdata(updatemsg, &rdata);
01740 check_result(result, "dns_message_gettemprdata");
01741
01742 dns_rdata_init(rdata);
01743
01744
01745
01746
01747
01748 word = nsu_strsep(&cmdline, " \t\r\n");
01749 if (word == NULL || *word == 0) {
01750 if (!isdelete) {
01751 fprintf(stderr, "could not read owner ttl\n");
01752 goto failure;
01753 }
01754 else {
01755 ttl = 0;
01756 rdataclass = dns_rdataclass_any;
01757 rdatatype = dns_rdatatype_any;
01758 rdata->flags = DNS_RDATA_UPDATE;
01759 goto doneparsing;
01760 }
01761 }
01762 result = isc_parse_uint32(&ttl, word, 10);
01763 if (result != ISC_R_SUCCESS) {
01764 if (isdelete) {
01765 ttl = 0;
01766 goto parseclass;
01767 } else if (default_ttl_set) {
01768 ttl = default_ttl;
01769 goto parseclass;
01770 } else {
01771 fprintf(stderr, "ttl '%s': %s\n", word,
01772 isc_result_totext(result));
01773 goto failure;
01774 }
01775 }
01776
01777 if (isdelete)
01778 ttl = 0;
01779 else if (ttl > TTL_MAX) {
01780 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
01781 word, TTL_MAX);
01782 goto failure;
01783 }
01784
01785
01786
01787
01788 word = nsu_strsep(&cmdline, " \t\r\n");
01789 parseclass:
01790 if (word == NULL || *word == 0) {
01791 if (isdelete) {
01792 rdataclass = dns_rdataclass_any;
01793 rdatatype = dns_rdatatype_any;
01794 rdata->flags = DNS_RDATA_UPDATE;
01795 goto doneparsing;
01796 } else {
01797 fprintf(stderr, "could not read class or type\n");
01798 goto failure;
01799 }
01800 }
01801 region.base = word;
01802 region.length = strlen(word);
01803 rdataclass = dns_rdataclass_any;
01804 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
01805 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
01806 if (!setzoneclass(rdataclass)) {
01807 fprintf(stderr, "class mismatch: %s\n", word);
01808 goto failure;
01809 }
01810
01811
01812
01813 word = nsu_strsep(&cmdline, " \t\r\n");
01814 if (word == NULL || *word == 0) {
01815 if (isdelete) {
01816 rdataclass = dns_rdataclass_any;
01817 rdatatype = dns_rdatatype_any;
01818 rdata->flags = DNS_RDATA_UPDATE;
01819 goto doneparsing;
01820 } else {
01821 fprintf(stderr, "could not read type\n");
01822 goto failure;
01823 }
01824 }
01825 region.base = word;
01826 region.length = strlen(word);
01827 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
01828 if (result != ISC_R_SUCCESS) {
01829 fprintf(stderr, "'%s' is not a valid type: %s\n",
01830 word, isc_result_totext(result));
01831 goto failure;
01832 }
01833 } else {
01834 rdataclass = getzoneclass();
01835 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
01836 if (result != ISC_R_SUCCESS) {
01837 fprintf(stderr, "'%s' is not a valid class or type: "
01838 "%s\n", word, isc_result_totext(result));
01839 goto failure;
01840 }
01841 }
01842
01843 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
01844 rdata);
01845 if (retval != STATUS_MORE)
01846 goto failure;
01847
01848 if (isdelete) {
01849 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
01850 rdataclass = dns_rdataclass_any;
01851 else
01852 rdataclass = dns_rdataclass_none;
01853 } else {
01854 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
01855 fprintf(stderr, "could not read rdata\n");
01856 goto failure;
01857 }
01858 }
01859
01860 if (!isdelete && checknames) {
01861 dns_fixedname_t fixed;
01862 dns_name_t *bad;
01863
01864 if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
01865 ISC_TRUE))
01866 {
01867 char namebuf[DNS_NAME_FORMATSIZE];
01868
01869 dns_name_format(name, namebuf, sizeof(namebuf));
01870 fprintf(stderr, "check-names failed: bad owner '%s'\n",
01871 namebuf);
01872 goto failure;
01873 }
01874
01875 dns_fixedname_init(&fixed);
01876 bad = dns_fixedname_name(&fixed);
01877 if (!dns_rdata_checknames(rdata, name, bad)) {
01878 char namebuf[DNS_NAME_FORMATSIZE];
01879
01880 dns_name_format(bad, namebuf, sizeof(namebuf));
01881 fprintf(stderr, "check-names failed: bad name '%s'\n",
01882 namebuf);
01883 goto failure;
01884 }
01885 }
01886
01887 doneparsing:
01888
01889 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
01890 check_result(result, "dns_message_gettemprdatalist");
01891 result = dns_message_gettemprdataset(updatemsg, &rdataset);
01892 check_result(result, "dns_message_gettemprdataset");
01893 rdatalist->type = rdatatype;
01894 rdatalist->rdclass = rdataclass;
01895 rdatalist->covers = rdatatype;
01896 rdatalist->ttl = (dns_ttl_t)ttl;
01897 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
01898 dns_rdataset_init(rdataset);
01899 dns_rdatalist_tordataset(rdatalist, rdataset);
01900 ISC_LIST_INIT(name->list);
01901 ISC_LIST_APPEND(name->list, rdataset, link);
01902 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
01903 return (STATUS_MORE);
01904
01905 failure:
01906 if (name != NULL)
01907 dns_message_puttempname(updatemsg, &name);
01908 dns_message_puttemprdata(updatemsg, &rdata);
01909 return (STATUS_SYNTAX);
01910 }
01911
01912 static isc_uint16_t
01913 evaluate_update(char *cmdline) {
01914 char *word;
01915 isc_boolean_t isdelete;
01916
01917 ddebug("evaluate_update()");
01918 word = nsu_strsep(&cmdline, " \t\r\n");
01919 if (word == NULL || *word == 0) {
01920 fprintf(stderr, "could not read operation code\n");
01921 return (STATUS_SYNTAX);
01922 }
01923 if (strcasecmp(word, "delete") == 0)
01924 isdelete = ISC_TRUE;
01925 else if (strcasecmp(word, "del") == 0)
01926 isdelete = ISC_TRUE;
01927 else if (strcasecmp(word, "add") == 0)
01928 isdelete = ISC_FALSE;
01929 else {
01930 fprintf(stderr, "incorrect operation code: %s\n", word);
01931 return (STATUS_SYNTAX);
01932 }
01933 return (update_addordelete(cmdline, isdelete));
01934 }
01935
01936 static isc_uint16_t
01937 evaluate_checknames(char *cmdline) {
01938 char *word;
01939
01940 ddebug("evaluate_checknames()");
01941 word = nsu_strsep(&cmdline, " \t\r\n");
01942 if (word == NULL || *word == 0) {
01943 fprintf(stderr, "could not read check-names directive\n");
01944 return (STATUS_SYNTAX);
01945 }
01946 if (strcasecmp(word, "yes") == 0 ||
01947 strcasecmp(word, "true") == 0 ||
01948 strcasecmp(word, "on") == 0) {
01949 checknames = ISC_TRUE;
01950 } else if (strcasecmp(word, "no") == 0 ||
01951 strcasecmp(word, "false") == 0 ||
01952 strcasecmp(word, "off") == 0) {
01953 checknames = ISC_FALSE;
01954 } else {
01955 fprintf(stderr, "incorrect check-names directive: %s\n", word);
01956 return (STATUS_SYNTAX);
01957 }
01958 return (STATUS_MORE);
01959 }
01960
01961 static void
01962 setzone(dns_name_t *zonename) {
01963 isc_result_t result;
01964 dns_name_t *name = NULL;
01965 dns_rdataset_t *rdataset = NULL;
01966
01967 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
01968 if (result == ISC_R_SUCCESS) {
01969 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
01970 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
01971 for (rdataset = ISC_LIST_HEAD(name->list);
01972 rdataset != NULL;
01973 rdataset = ISC_LIST_HEAD(name->list)) {
01974 ISC_LIST_UNLINK(name->list, rdataset, link);
01975 dns_rdataset_disassociate(rdataset);
01976 dns_message_puttemprdataset(updatemsg, &rdataset);
01977 }
01978 dns_message_puttempname(updatemsg, &name);
01979 }
01980
01981 if (zonename != NULL) {
01982 result = dns_message_gettempname(updatemsg, &name);
01983 check_result(result, "dns_message_gettempname");
01984 dns_name_init(name, NULL);
01985 dns_name_clone(zonename, name);
01986 result = dns_message_gettemprdataset(updatemsg, &rdataset);
01987 check_result(result, "dns_message_gettemprdataset");
01988 dns_rdataset_makequestion(rdataset, getzoneclass(),
01989 dns_rdatatype_soa);
01990 ISC_LIST_INIT(name->list);
01991 ISC_LIST_APPEND(name->list, rdataset, link);
01992 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
01993 }
01994 }
01995
01996 static void
01997 show_message(FILE *stream, dns_message_t *msg, const char *description) {
01998 isc_result_t result;
01999 isc_buffer_t *buf = NULL;
02000 int bufsz;
02001
02002 ddebug("show_message()");
02003
02004 setzone(userzone);
02005
02006 bufsz = INITTEXT;
02007 do {
02008 if (bufsz > MAXTEXT) {
02009 fprintf(stderr, "could not allocate large enough "
02010 "buffer to display message\n");
02011 exit(1);
02012 }
02013 if (buf != NULL)
02014 isc_buffer_free(&buf);
02015 result = isc_buffer_allocate(gmctx, &buf, bufsz);
02016 check_result(result, "isc_buffer_allocate");
02017 result = dns_message_totext(msg, style, 0, buf);
02018 bufsz *= 2;
02019 } while (result == ISC_R_NOSPACE);
02020 if (result != ISC_R_SUCCESS) {
02021 fprintf(stderr, "could not convert message to text format.\n");
02022 isc_buffer_free(&buf);
02023 return;
02024 }
02025 fprintf(stream, "%s\n%.*s", description,
02026 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
02027 isc_buffer_free(&buf);
02028 }
02029
02030 static isc_uint16_t
02031 do_next_command(char *cmdline) {
02032 char *word;
02033
02034 ddebug("do_next_command()");
02035 word = nsu_strsep(&cmdline, " \t\r\n");
02036
02037 if (word == NULL || *word == 0)
02038 return (STATUS_SEND);
02039 if (word[0] == ';')
02040 return (STATUS_MORE);
02041 if (strcasecmp(word, "quit") == 0)
02042 return (STATUS_QUIT);
02043 if (strcasecmp(word, "prereq") == 0)
02044 return (evaluate_prereq(cmdline));
02045 if (strcasecmp(word, "nxdomain") == 0)
02046 return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE));
02047 if (strcasecmp(word, "yxdomain") == 0)
02048 return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE));
02049 if (strcasecmp(word, "nxrrset") == 0)
02050 return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE));
02051 if (strcasecmp(word, "yxrrset") == 0)
02052 return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE));
02053 if (strcasecmp(word, "update") == 0)
02054 return (evaluate_update(cmdline));
02055 if (strcasecmp(word, "delete") == 0)
02056 return (update_addordelete(cmdline, ISC_TRUE));
02057 if (strcasecmp(word, "del") == 0)
02058 return (update_addordelete(cmdline, ISC_TRUE));
02059 if (strcasecmp(word, "add") == 0)
02060 return (update_addordelete(cmdline, ISC_FALSE));
02061 if (strcasecmp(word, "server") == 0)
02062 return (evaluate_server(cmdline));
02063 if (strcasecmp(word, "local") == 0)
02064 return (evaluate_local(cmdline));
02065 if (strcasecmp(word, "zone") == 0)
02066 return (evaluate_zone(cmdline));
02067 if (strcasecmp(word, "class") == 0)
02068 return (evaluate_class(cmdline));
02069 if (strcasecmp(word, "send") == 0)
02070 return (STATUS_SEND);
02071 if (strcasecmp(word, "debug") == 0) {
02072 if (debugging)
02073 ddebugging = ISC_TRUE;
02074 else
02075 debugging = ISC_TRUE;
02076 return (STATUS_MORE);
02077 }
02078 if (strcasecmp(word, "ttl") == 0)
02079 return (evaluate_ttl(cmdline));
02080 if (strcasecmp(word, "show") == 0) {
02081 show_message(stdout, updatemsg, "Outgoing update query:");
02082 return (STATUS_MORE);
02083 }
02084 if (strcasecmp(word, "answer") == 0) {
02085 if (answer != NULL)
02086 show_message(stdout, answer, "Answer:");
02087 return (STATUS_MORE);
02088 }
02089 if (strcasecmp(word, "key") == 0) {
02090 usegsstsig = ISC_FALSE;
02091 return (evaluate_key(cmdline));
02092 }
02093 if (strcasecmp(word, "realm") == 0)
02094 return (evaluate_realm(cmdline));
02095 if (strcasecmp(word, "check-names") == 0 ||
02096 strcasecmp(word, "checknames") == 0)
02097 return (evaluate_checknames(cmdline));
02098 if (strcasecmp(word, "gsstsig") == 0) {
02099 #ifdef GSSAPI
02100 usegsstsig = ISC_TRUE;
02101 use_win2k_gsstsig = ISC_FALSE;
02102 #else
02103 fprintf(stderr, "gsstsig not supported\n");
02104 #endif
02105 return (STATUS_MORE);
02106 }
02107 if (strcasecmp(word, "oldgsstsig") == 0) {
02108 #ifdef GSSAPI
02109 usegsstsig = ISC_TRUE;
02110 use_win2k_gsstsig = ISC_TRUE;
02111 #else
02112 fprintf(stderr, "gsstsig not supported\n");
02113 #endif
02114 return (STATUS_MORE);
02115 }
02116 if (strcasecmp(word, "help") == 0) {
02117 fprintf(stdout,
02118 "nsupdate " VERSION ":\n"
02119 "local address [port] (set local resolver)\n"
02120 "server address [port] (set master server for zone)\n"
02121 "send (send the update request)\n"
02122 "show (show the update request)\n"
02123 "answer (show the answer to the last request)\n"
02124 "quit (quit, any pending update is not sent\n"
02125 "help (display this message_\n"
02126 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
02127 "gsstsig (use GSS_TSIG to sign the request)\n"
02128 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
02129 "zone name (set the zone to be updated)\n"
02130 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
02131 "check-names { on | off } (enable / disable check-names)\n"
02132 "[prereq] nxdomain name (does this name not exist)\n"
02133 "[prereq] yxdomain name (does this name exist)\n"
02134 "[prereq] nxrrset .... (does this RRset exist)\n"
02135 "[prereq] yxrrset .... (does this RRset not exist)\n"
02136 "[update] add .... (add the given record to the zone)\n"
02137 "[update] del[ete] .... (remove the given record(s) from the zone)\n");
02138 return (STATUS_MORE);
02139 }
02140 if (strcasecmp(word, "version") == 0) {
02141 fprintf(stdout, "nsupdate " VERSION "\n");
02142 return (STATUS_MORE);
02143 }
02144 fprintf(stderr, "incorrect section name: %s\n", word);
02145 return (STATUS_SYNTAX);
02146 }
02147
02148 static isc_uint16_t
02149 get_next_command(void) {
02150 isc_uint16_t result = STATUS_QUIT;
02151 char cmdlinebuf[MAXCMD];
02152 char *cmdline;
02153
02154 isc_app_block();
02155 if (interactive) {
02156 #ifdef HAVE_READLINE
02157 cmdline = readline("> ");
02158 if (cmdline != NULL)
02159 add_history(cmdline);
02160 #else
02161 fprintf(stdout, "> ");
02162 fflush(stdout);
02163 cmdline = fgets(cmdlinebuf, MAXCMD, input);
02164 #endif
02165 } else
02166 cmdline = fgets(cmdlinebuf, MAXCMD, input);
02167 isc_app_unblock();
02168
02169 if (cmdline != NULL) {
02170 char *tmp = cmdline;
02171
02172
02173
02174
02175
02176 (void)nsu_strsep(&tmp, "\r\n");
02177 result = do_next_command(cmdline);
02178 }
02179 #ifdef HAVE_READLINE
02180 if (interactive)
02181 free(cmdline);
02182 #endif
02183 return (result);
02184 }
02185
02186 static isc_boolean_t
02187 user_interaction(void) {
02188 isc_uint16_t result = STATUS_MORE;
02189
02190 ddebug("user_interaction()");
02191 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
02192 result = get_next_command();
02193 if (!interactive && result == STATUS_SYNTAX)
02194 fatal("syntax error");
02195 }
02196 if (result == STATUS_SEND)
02197 return (ISC_TRUE);
02198 return (ISC_FALSE);
02199
02200 }
02201
02202 static void
02203 done_update(void) {
02204 isc_event_t *event = global_event;
02205 ddebug("done_update()");
02206 isc_task_send(global_task, &event);
02207 }
02208
02209 static void
02210 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
02211 isc_result_t result;
02212 dns_rdata_t rdata = DNS_RDATA_INIT;
02213 dns_rdata_any_tsig_t tsig;
02214
02215 result = dns_rdataset_first(rdataset);
02216 check_result(result, "dns_rdataset_first");
02217 dns_rdataset_current(rdataset, &rdata);
02218 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
02219 check_result(result, "dns_rdata_tostruct");
02220 if (tsig.error != 0) {
02221 if (isc_buffer_remaininglength(b) < 1)
02222 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
02223 isc_buffer_putstr(b, "(" );
02224 result = dns_tsigrcode_totext(tsig.error, b);
02225 check_result(result, "dns_tsigrcode_totext");
02226 if (isc_buffer_remaininglength(b) < 1)
02227 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
02228 isc_buffer_putstr(b, ")");
02229 }
02230 }
02231
02232 static isc_boolean_t
02233 next_master(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
02234 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
02235
02236 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
02237 fprintf(stderr, "; Communication with %s failed: %s\n",
02238 addrbuf, isc_result_totext(eresult));
02239 if (++master_inuse >= master_total)
02240 return (ISC_FALSE);
02241 ddebug("%s: trying next server", caller);
02242 return (ISC_TRUE);
02243 }
02244
02245 static void
02246 update_completed(isc_task_t *task, isc_event_t *event) {
02247 dns_requestevent_t *reqev = NULL;
02248 isc_result_t result;
02249 dns_request_t *request;
02250
02251 UNUSED(task);
02252
02253 ddebug("update_completed()");
02254
02255 requests--;
02256
02257 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
02258 reqev = (dns_requestevent_t *)event;
02259 request = reqev->request;
02260
02261 if (shuttingdown) {
02262 dns_request_destroy(&request);
02263 isc_event_free(&event);
02264 maybeshutdown();
02265 return;
02266 }
02267
02268 if (reqev->result != ISC_R_SUCCESS) {
02269 if (!next_master("recvsoa", &master_servers[master_inuse],
02270 reqev->result)) {
02271 seenerror = ISC_TRUE;
02272 goto done;
02273 }
02274
02275 ddebug("Destroying request [%p]", request);
02276 dns_request_destroy(&request);
02277 dns_message_renderreset(updatemsg);
02278 dns_message_settsigkey(updatemsg, NULL);
02279
02280 send_update(zname, &master_servers[master_inuse]);
02281 isc_event_free(&event);
02282 return;
02283 }
02284
02285 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer);
02286 check_result(result, "dns_message_create");
02287 result = dns_request_getresponse(request, answer,
02288 DNS_MESSAGEPARSE_PRESERVEORDER);
02289 switch (result) {
02290 case ISC_R_SUCCESS:
02291 if (answer->verify_attempted)
02292 ddebug("tsig verification successful");
02293 break;
02294 case DNS_R_CLOCKSKEW:
02295 case DNS_R_EXPECTEDTSIG:
02296 case DNS_R_TSIGERRORSET:
02297 case DNS_R_TSIGVERIFYFAILURE:
02298 case DNS_R_UNEXPECTEDTSIG:
02299 case ISC_R_FAILURE:
02300 #if 0
02301 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
02302
02303
02304
02305 break;
02306 }
02307 #endif
02308 fprintf(stderr, "; TSIG error with server: %s\n",
02309 isc_result_totext(result));
02310 seenerror = ISC_TRUE;
02311 break;
02312 default:
02313 check_result(result, "dns_request_getresponse");
02314 }
02315
02316 if (answer->rcode != dns_rcode_noerror) {
02317 seenerror = ISC_TRUE;
02318 if (!debugging) {
02319 char buf[64];
02320 isc_buffer_t b;
02321 dns_rdataset_t *rds;
02322
02323 isc_buffer_init(&b, buf, sizeof(buf) - 1);
02324 result = dns_rcode_totext(answer->rcode, &b);
02325 check_result(result, "dns_rcode_totext");
02326 rds = dns_message_gettsig(answer, NULL);
02327 if (rds != NULL)
02328 check_tsig_error(rds, &b);
02329 fprintf(stderr, "update failed: %.*s\n",
02330 (int)isc_buffer_usedlength(&b), buf);
02331 }
02332 }
02333 if (debugging)
02334 show_message(stderr, answer, "\nReply from update query:");
02335
02336 done:
02337 dns_request_destroy(&request);
02338 if (usegsstsig) {
02339 dns_name_free(&tmpzonename, gmctx);
02340 dns_name_free(&restart_master, gmctx);
02341 }
02342 isc_event_free(&event);
02343 done_update();
02344 }
02345
02346 static void
02347 send_update(dns_name_t *zone, isc_sockaddr_t *master) {
02348 isc_result_t result;
02349 dns_request_t *request = NULL;
02350 unsigned int options = DNS_REQUESTOPT_CASE;
02351 isc_sockaddr_t *srcaddr;
02352
02353 ddebug("send_update()");
02354
02355 setzone(zone);
02356
02357 if (usevc)
02358 options |= DNS_REQUESTOPT_TCP;
02359 if (tsigkey == NULL && sig0key != NULL) {
02360 result = dns_message_setsig0key(updatemsg, sig0key);
02361 check_result(result, "dns_message_setsig0key");
02362 }
02363 if (debugging) {
02364 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
02365
02366 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
02367 fprintf(stderr, "Sending update to %s\n", addrbuf);
02368 }
02369
02370 if (isc_sockaddr_pf(master) == AF_INET6)
02371 srcaddr = localaddr6;
02372 else
02373 srcaddr = localaddr4;
02374
02375
02376 if (updatemsg->tsigname)
02377 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
02378
02379 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
02380 master, options, tsigkey, timeout,
02381 udp_timeout, udp_retries, global_task,
02382 update_completed, NULL, &request);
02383 check_result(result, "dns_request_createvia3");
02384
02385 if (debugging)
02386 show_message(stdout, updatemsg, "Outgoing update query:");
02387
02388 requests++;
02389 }
02390
02391 static void
02392 next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
02393 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
02394
02395 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
02396 fprintf(stderr, "; Communication with %s failed: %s\n",
02397 addrbuf, isc_result_totext(eresult));
02398 if (++ns_inuse >= ns_total)
02399 fatal("could not reach any name server");
02400 else
02401 ddebug("%s: trying next server", caller);
02402 }
02403
02404 static void
02405 recvsoa(isc_task_t *task, isc_event_t *event) {
02406 dns_requestevent_t *reqev = NULL;
02407 dns_request_t *request = NULL;
02408 isc_result_t result, eresult;
02409 dns_message_t *rcvmsg = NULL;
02410 dns_section_t section;
02411 dns_name_t *name = NULL;
02412 dns_rdataset_t *soaset = NULL;
02413 dns_rdata_soa_t soa;
02414 dns_rdata_t soarr = DNS_RDATA_INIT;
02415 int pass = 0;
02416 dns_name_t master;
02417 nsu_requestinfo_t *reqinfo;
02418 dns_message_t *soaquery = NULL;
02419 isc_sockaddr_t *addr;
02420 isc_sockaddr_t *srcaddr;
02421 isc_boolean_t seencname = ISC_FALSE;
02422 dns_name_t tname;
02423 unsigned int nlabels;
02424
02425 UNUSED(task);
02426
02427 ddebug("recvsoa()");
02428
02429 requests--;
02430
02431 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
02432 reqev = (dns_requestevent_t *)event;
02433 request = reqev->request;
02434 eresult = reqev->result;
02435 reqinfo = reqev->ev_arg;
02436 soaquery = reqinfo->msg;
02437 addr = reqinfo->addr;
02438
02439 if (shuttingdown) {
02440 dns_request_destroy(&request);
02441 dns_message_destroy(&soaquery);
02442 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
02443 isc_event_free(&event);
02444 maybeshutdown();
02445 return;
02446 }
02447
02448 if (eresult != ISC_R_SUCCESS) {
02449 next_server("recvsoa", addr, eresult);
02450 ddebug("Destroying request [%p]", request);
02451 dns_request_destroy(&request);
02452 dns_message_renderreset(soaquery);
02453 dns_message_settsigkey(soaquery, NULL);
02454 sendrequest(&servers[ns_inuse], soaquery, &request);
02455 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
02456 isc_event_free(&event);
02457 setzoneclass(dns_rdataclass_none);
02458 return;
02459 }
02460
02461 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
02462 reqinfo = NULL;
02463 isc_event_free(&event);
02464 reqev = NULL;
02465
02466 ddebug("About to create rcvmsg");
02467 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
02468 check_result(result, "dns_message_create");
02469 result = dns_request_getresponse(request, rcvmsg,
02470 DNS_MESSAGEPARSE_PRESERVEORDER);
02471 if (result == DNS_R_TSIGERRORSET && servers != NULL) {
02472 dns_message_destroy(&rcvmsg);
02473 ddebug("Destroying request [%p]", request);
02474 dns_request_destroy(&request);
02475 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
02476 if (reqinfo == NULL)
02477 fatal("out of memory");
02478 reqinfo->msg = soaquery;
02479 reqinfo->addr = addr;
02480 dns_message_renderreset(soaquery);
02481 ddebug("retrying soa request without TSIG");
02482
02483 if (isc_sockaddr_pf(addr) == AF_INET6)
02484 srcaddr = localaddr6;
02485 else
02486 srcaddr = localaddr4;
02487
02488 result = dns_request_createvia3(requestmgr, soaquery, srcaddr,
02489 addr, 0, NULL,
02490 FIND_TIMEOUT * 20,
02491 FIND_TIMEOUT, 3,
02492 global_task, recvsoa, reqinfo,
02493 &request);
02494 check_result(result, "dns_request_createvia");
02495 requests++;
02496 return;
02497 }
02498 check_result(result, "dns_request_getresponse");
02499 section = DNS_SECTION_ANSWER;
02500 POST(section);
02501 if (debugging)
02502 show_message(stderr, rcvmsg, "Reply from SOA query:");
02503
02504 if (rcvmsg->rcode != dns_rcode_noerror &&
02505 rcvmsg->rcode != dns_rcode_nxdomain)
02506 fatal("response to SOA query was unsuccessful");
02507
02508 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
02509 char namebuf[DNS_NAME_FORMATSIZE];
02510 dns_name_format(userzone, namebuf, sizeof(namebuf));
02511 error("specified zone '%s' does not exist (NXDOMAIN)",
02512 namebuf);
02513 dns_message_destroy(&rcvmsg);
02514 dns_request_destroy(&request);
02515 dns_message_destroy(&soaquery);
02516 ddebug("Out of recvsoa");
02517 done_update();
02518 seenerror = ISC_TRUE;
02519 return;
02520 }
02521
02522 lookforsoa:
02523 if (pass == 0)
02524 section = DNS_SECTION_ANSWER;
02525 else if (pass == 1)
02526 section = DNS_SECTION_AUTHORITY;
02527 else
02528 goto droplabel;
02529
02530 result = dns_message_firstname(rcvmsg, section);
02531 if (result != ISC_R_SUCCESS) {
02532 pass++;
02533 goto lookforsoa;
02534 }
02535 while (result == ISC_R_SUCCESS) {
02536 name = NULL;
02537 dns_message_currentname(rcvmsg, section, &name);
02538 soaset = NULL;
02539 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
02540 &soaset);
02541 if (result == ISC_R_SUCCESS)
02542 break;
02543 if (section == DNS_SECTION_ANSWER) {
02544 dns_rdataset_t *tset = NULL;
02545 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
02546 &tset) == ISC_R_SUCCESS ||
02547 dns_message_findtype(name, dns_rdatatype_dname, 0,
02548 &tset) == ISC_R_SUCCESS ) {
02549 seencname = ISC_TRUE;
02550 break;
02551 }
02552 }
02553
02554 result = dns_message_nextname(rcvmsg, section);
02555 }
02556
02557 if (soaset == NULL && !seencname) {
02558 pass++;
02559 goto lookforsoa;
02560 }
02561
02562 if (seencname)
02563 goto droplabel;
02564
02565 if (debugging) {
02566 char namestr[DNS_NAME_FORMATSIZE];
02567 dns_name_format(name, namestr, sizeof(namestr));
02568 fprintf(stderr, "Found zone name: %s\n", namestr);
02569 }
02570
02571 result = dns_rdataset_first(soaset);
02572 check_result(result, "dns_rdataset_first");
02573
02574 dns_rdata_init(&soarr);
02575 dns_rdataset_current(soaset, &soarr);
02576 result = dns_rdata_tostruct(&soarr, &soa, NULL);
02577 check_result(result, "dns_rdata_tostruct");
02578
02579 dns_name_init(&master, NULL);
02580 dns_name_clone(&soa.origin, &master);
02581
02582
02583
02584
02585 if (userzone != NULL)
02586 zname = userzone;
02587 else
02588 zname = name;
02589
02590 if (debugging) {
02591 char namestr[DNS_NAME_FORMATSIZE];
02592 dns_name_format(&master, namestr, sizeof(namestr));
02593 fprintf(stderr, "The master is: %s\n", namestr);
02594 }
02595
02596 if (default_servers) {
02597 char serverstr[DNS_NAME_MAXTEXT+1];
02598 isc_buffer_t buf;
02599 size_t size;
02600
02601 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
02602 result = dns_name_totext(&master, ISC_TRUE, &buf);
02603 check_result(result, "dns_name_totext");
02604 serverstr[isc_buffer_usedlength(&buf)] = 0;
02605
02606 if (master_servers != NULL && master_servers != servers)
02607 isc_mem_put(gmctx, master_servers,
02608 master_total * sizeof(isc_sockaddr_t));
02609 master_total = MAX_SERVERADDRS;
02610 size = master_total * sizeof(isc_sockaddr_t);
02611 master_servers = isc_mem_get(gmctx, size);
02612 if (master_servers == NULL)
02613 fatal("out of memory");
02614
02615 memset(master_servers, 0, size);
02616 get_addresses(serverstr, dnsport, master_servers, master_total);
02617 master_inuse = 0;
02618 } else
02619 master_from_servers();
02620 dns_rdata_freestruct(&soa);
02621
02622 #ifdef GSSAPI
02623 if (usegsstsig) {
02624 dns_name_init(&tmpzonename, NULL);
02625 dns_name_dup(zname, gmctx, &tmpzonename);
02626 dns_name_init(&restart_master, NULL);
02627 dns_name_dup(&master, gmctx, &restart_master);
02628 start_gssrequest(&master);
02629 } else {
02630 send_update(zname, &master_servers[master_inuse]);
02631 setzoneclass(dns_rdataclass_none);
02632 }
02633 #else
02634 send_update(zname, &master_servers[master_inuse]);
02635 setzoneclass(dns_rdataclass_none);
02636 #endif
02637
02638 dns_message_destroy(&soaquery);
02639 dns_request_destroy(&request);
02640
02641 out:
02642 dns_message_destroy(&rcvmsg);
02643 ddebug("Out of recvsoa");
02644 return;
02645
02646 droplabel:
02647 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
02648 INSIST(result == ISC_R_SUCCESS);
02649 name = NULL;
02650 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
02651 nlabels = dns_name_countlabels(name);
02652 if (nlabels == 1)
02653 fatal("could not find enclosing zone");
02654 dns_name_init(&tname, NULL);
02655 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
02656 dns_name_clone(&tname, name);
02657 dns_request_destroy(&request);
02658 dns_message_renderreset(soaquery);
02659 dns_message_settsigkey(soaquery, NULL);
02660 sendrequest(&servers[ns_inuse], soaquery, &request);
02661 goto out;
02662 }
02663
02664 static void
02665 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
02666 dns_request_t **request)
02667 {
02668 isc_result_t result;
02669 nsu_requestinfo_t *reqinfo;
02670 isc_sockaddr_t *srcaddr;
02671
02672 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
02673 if (reqinfo == NULL)
02674 fatal("out of memory");
02675 reqinfo->msg = msg;
02676 reqinfo->addr = destaddr;
02677
02678 if (isc_sockaddr_pf(destaddr) == AF_INET6)
02679 srcaddr = localaddr6;
02680 else
02681 srcaddr = localaddr4;
02682
02683 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
02684 default_servers ? NULL : tsigkey,
02685 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
02686 global_task, recvsoa, reqinfo, request);
02687 check_result(result, "dns_request_createvia");
02688 requests++;
02689 }
02690
02691 #ifdef GSSAPI
02692
02693
02694
02695
02696 static void
02697 get_ticket_realm(isc_mem_t *mctx) {
02698 krb5_context ctx;
02699 krb5_error_code rc;
02700 krb5_ccache ccache;
02701 krb5_principal princ;
02702 char *name, *ticket_realm;
02703
02704 rc = krb5_init_context(&ctx);
02705 if (rc != 0)
02706 return;
02707
02708 rc = krb5_cc_default(ctx, &ccache);
02709 if (rc != 0) {
02710 krb5_free_context(ctx);
02711 return;
02712 }
02713
02714 rc = krb5_cc_get_principal(ctx, ccache, &princ);
02715 if (rc != 0) {
02716 krb5_cc_close(ctx, ccache);
02717 krb5_free_context(ctx);
02718 return;
02719 }
02720
02721 rc = krb5_unparse_name(ctx, princ, &name);
02722 if (rc != 0) {
02723 krb5_free_principal(ctx, princ);
02724 krb5_cc_close(ctx, ccache);
02725 krb5_free_context(ctx);
02726 return;
02727 }
02728
02729 ticket_realm = strrchr(name, '@');
02730 if (ticket_realm != NULL) {
02731 realm = isc_mem_strdup(mctx, ticket_realm);
02732 }
02733
02734 free(name);
02735 krb5_free_principal(ctx, princ);
02736 krb5_cc_close(ctx, ccache);
02737 krb5_free_context(ctx);
02738 if (realm != NULL && debugging)
02739 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
02740 }
02741
02742
02743 static void
02744 start_gssrequest(dns_name_t *master) {
02745 gss_ctx_id_t context;
02746 isc_buffer_t buf;
02747 isc_result_t result;
02748 isc_uint32_t val = 0;
02749 dns_message_t *rmsg;
02750 dns_request_t *request = NULL;
02751 dns_name_t *servname;
02752 dns_fixedname_t fname;
02753 char namestr[DNS_NAME_FORMATSIZE];
02754 char mykeystr[DNS_NAME_FORMATSIZE];
02755 char *err_message = NULL;
02756
02757 debug("start_gssrequest");
02758 usevc = ISC_TRUE;
02759
02760 if (gssring != NULL)
02761 dns_tsigkeyring_detach(&gssring);
02762 gssring = NULL;
02763 result = dns_tsigkeyring_create(gmctx, &gssring);
02764
02765 if (result != ISC_R_SUCCESS)
02766 fatal("dns_tsigkeyring_create failed: %s",
02767 isc_result_totext(result));
02768
02769 dns_name_format(master, namestr, sizeof(namestr));
02770 if (kserver == NULL) {
02771 kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
02772 if (kserver == NULL)
02773 fatal("out of memory");
02774 }
02775 if (servers == NULL)
02776 get_addresses(namestr, dnsport, kserver, 1);
02777 else
02778 memmove(kserver, &servers[ns_inuse], sizeof(isc_sockaddr_t));
02779
02780 dns_fixedname_init(&fname);
02781 servname = dns_fixedname_name(&fname);
02782
02783 if (realm == NULL)
02784 get_ticket_realm(gmctx);
02785
02786 result = isc_string_printf(servicename, sizeof(servicename),
02787 "DNS/%s%s", namestr, realm ? realm : "");
02788 if (result != ISC_R_SUCCESS)
02789 fatal("isc_string_printf(servicename) failed: %s",
02790 isc_result_totext(result));
02791 isc_buffer_init(&buf, servicename, strlen(servicename));
02792 isc_buffer_add(&buf, strlen(servicename));
02793 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
02794 if (result != ISC_R_SUCCESS)
02795 fatal("dns_name_fromtext(servname) failed: %s",
02796 isc_result_totext(result));
02797
02798 dns_fixedname_init(&fkname);
02799 keyname = dns_fixedname_name(&fkname);
02800
02801 isc_random_get(&val);
02802 result = isc_string_printf(mykeystr, sizeof(mykeystr), "%u.sig-%s",
02803 val, namestr);
02804 if (result != ISC_R_SUCCESS)
02805 fatal("isc_string_printf(mykeystr) failed: %s",
02806 isc_result_totext(result));
02807 isc_buffer_init(&buf, mykeystr, strlen(mykeystr));
02808 isc_buffer_add(&buf, strlen(mykeystr));
02809
02810 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
02811 if (result != ISC_R_SUCCESS)
02812 fatal("dns_name_fromtext(keyname) failed: %s",
02813 isc_result_totext(result));
02814
02815
02816 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
02817
02818 rmsg = NULL;
02819 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
02820 if (result != ISC_R_SUCCESS)
02821 fatal("dns_message_create failed: %s",
02822 isc_result_totext(result));
02823
02824
02825 context = GSS_C_NO_CONTEXT;
02826 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
02827 &context, use_win2k_gsstsig,
02828 gmctx, &err_message);
02829 if (result == ISC_R_FAILURE)
02830 fatal("tkey query failed: %s",
02831 err_message != NULL ? err_message : "unknown error");
02832 if (result != ISC_R_SUCCESS)
02833 fatal("dns_tkey_buildgssquery failed: %s",
02834 isc_result_totext(result));
02835
02836 send_gssrequest(kserver, rmsg, &request, context);
02837 }
02838
02839 static void
02840 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
02841 dns_request_t **request, gss_ctx_id_t context)
02842 {
02843 isc_result_t result;
02844 nsu_gssinfo_t *reqinfo;
02845 unsigned int options = 0;
02846 isc_sockaddr_t *srcaddr;
02847
02848 debug("send_gssrequest");
02849 reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
02850 if (reqinfo == NULL)
02851 fatal("out of memory");
02852 reqinfo->msg = msg;
02853 reqinfo->addr = destaddr;
02854 reqinfo->context = context;
02855
02856 options |= DNS_REQUESTOPT_TCP;
02857
02858 if (isc_sockaddr_pf(destaddr) == AF_INET6)
02859 srcaddr = localaddr6;
02860 else
02861 srcaddr = localaddr4;
02862
02863 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
02864 options, tsigkey, FIND_TIMEOUT * 20,
02865 FIND_TIMEOUT, 3, global_task, recvgss,
02866 reqinfo, request);
02867 check_result(result, "dns_request_createvia3");
02868 if (debugging)
02869 show_message(stdout, msg, "Outgoing update query:");
02870 requests++;
02871 }
02872
02873 static void
02874 recvgss(isc_task_t *task, isc_event_t *event) {
02875 dns_requestevent_t *reqev = NULL;
02876 dns_request_t *request = NULL;
02877 isc_result_t result, eresult;
02878 dns_message_t *rcvmsg = NULL;
02879 nsu_gssinfo_t *reqinfo;
02880 dns_message_t *tsigquery = NULL;
02881 isc_sockaddr_t *addr;
02882 gss_ctx_id_t context;
02883 isc_buffer_t buf;
02884 dns_name_t *servname;
02885 dns_fixedname_t fname;
02886 char *err_message = NULL;
02887
02888 UNUSED(task);
02889
02890 ddebug("recvgss()");
02891
02892 requests--;
02893
02894 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
02895 reqev = (dns_requestevent_t *)event;
02896 request = reqev->request;
02897 eresult = reqev->result;
02898 reqinfo = reqev->ev_arg;
02899 tsigquery = reqinfo->msg;
02900 context = reqinfo->context;
02901 addr = reqinfo->addr;
02902
02903 if (shuttingdown) {
02904 dns_request_destroy(&request);
02905 dns_message_destroy(&tsigquery);
02906 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
02907 isc_event_free(&event);
02908 maybeshutdown();
02909 return;
02910 }
02911
02912 if (eresult != ISC_R_SUCCESS) {
02913 next_server("recvgss", addr, eresult);
02914 ddebug("Destroying request [%p]", request);
02915 dns_request_destroy(&request);
02916 dns_message_renderreset(tsigquery);
02917 sendrequest(&servers[ns_inuse], tsigquery, &request);
02918 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
02919 isc_event_free(&event);
02920 return;
02921 }
02922 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
02923
02924 isc_event_free(&event);
02925 reqev = NULL;
02926
02927 ddebug("recvgss creating rcvmsg");
02928 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
02929 check_result(result, "dns_message_create");
02930
02931 result = dns_request_getresponse(request, rcvmsg,
02932 DNS_MESSAGEPARSE_PRESERVEORDER);
02933 check_result(result, "dns_request_getresponse");
02934
02935 if (debugging)
02936 show_message(stderr, rcvmsg,
02937 "recvmsg reply from GSS-TSIG query");
02938
02939 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
02940 ddebug("recvgss trying %s GSS-TSIG",
02941 use_win2k_gsstsig ? "Standard" : "Win2k");
02942 if (use_win2k_gsstsig)
02943 use_win2k_gsstsig = ISC_FALSE;
02944 else
02945 use_win2k_gsstsig = ISC_TRUE;
02946 tried_other_gsstsig = ISC_TRUE;
02947 start_gssrequest(&restart_master);
02948 goto done;
02949 }
02950
02951 if (rcvmsg->rcode != dns_rcode_noerror &&
02952 rcvmsg->rcode != dns_rcode_nxdomain)
02953 fatal("response to GSS-TSIG query was unsuccessful");
02954
02955
02956 dns_fixedname_init(&fname);
02957 servname = dns_fixedname_name(&fname);
02958 isc_buffer_init(&buf, servicename, strlen(servicename));
02959 isc_buffer_add(&buf, strlen(servicename));
02960 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
02961 check_result(result, "dns_name_fromtext");
02962
02963 tsigkey = NULL;
02964 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
02965 &context, &tsigkey, gssring,
02966 use_win2k_gsstsig,
02967 &err_message);
02968 switch (result) {
02969
02970 case DNS_R_CONTINUE:
02971 send_gssrequest(kserver, tsigquery, &request, context);
02972 break;
02973
02974 case ISC_R_SUCCESS:
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991 #if 0
02992
02993
02994
02995 rcvmsg->state = DNS_SECTION_ANY;
02996 dns_message_setquerytsig(rcvmsg, NULL);
02997 result = dns_message_settsigkey(rcvmsg, tsigkey);
02998 check_result(result, "dns_message_settsigkey");
02999 result = dns_message_checksig(rcvmsg, NULL);
03000 ddebug("tsig verification: %s", dns_result_totext(result));
03001 check_result(result, "dns_message_checksig");
03002 #endif
03003
03004 send_update(&tmpzonename, &master_servers[master_inuse]);
03005 setzoneclass(dns_rdataclass_none);
03006 break;
03007
03008 default:
03009 fatal("dns_tkey_negotiategss: %s %s",
03010 isc_result_totext(result),
03011 err_message != NULL ? err_message : "");
03012 }
03013
03014 done:
03015 dns_request_destroy(&request);
03016 dns_message_destroy(&tsigquery);
03017
03018 dns_message_destroy(&rcvmsg);
03019 ddebug("Out of recvgss");
03020 }
03021 #endif
03022
03023 static void
03024 start_update(void) {
03025 isc_result_t result;
03026 dns_rdataset_t *rdataset = NULL;
03027 dns_name_t *name = NULL;
03028 dns_request_t *request = NULL;
03029 dns_message_t *soaquery = NULL;
03030 dns_name_t *firstname;
03031 dns_section_t section = DNS_SECTION_UPDATE;
03032
03033 ddebug("start_update()");
03034
03035 if (answer != NULL)
03036 dns_message_destroy(&answer);
03037
03038
03039
03040
03041
03042
03043 if (userzone != NULL && !default_servers && !usegsstsig) {
03044 master_from_servers();
03045 send_update(userzone, &master_servers[master_inuse]);
03046 setzoneclass(dns_rdataclass_none);
03047 return;
03048 }
03049
03050 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
03051 &soaquery);
03052 check_result(result, "dns_message_create");
03053
03054 if (default_servers)
03055 soaquery->flags |= DNS_MESSAGEFLAG_RD;
03056
03057 result = dns_message_gettempname(soaquery, &name);
03058 check_result(result, "dns_message_gettempname");
03059
03060 result = dns_message_gettemprdataset(soaquery, &rdataset);
03061 check_result(result, "dns_message_gettemprdataset");
03062
03063 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
03064
03065 if (userzone != NULL) {
03066 dns_name_init(name, NULL);
03067 dns_name_clone(userzone, name);
03068 } else {
03069 dns_rdataset_t *tmprdataset;
03070 result = dns_message_firstname(updatemsg, section);
03071 if (result == ISC_R_NOMORE) {
03072 section = DNS_SECTION_PREREQUISITE;
03073 result = dns_message_firstname(updatemsg, section);
03074 }
03075 if (result != ISC_R_SUCCESS) {
03076 dns_message_puttempname(soaquery, &name);
03077 dns_rdataset_disassociate(rdataset);
03078 dns_message_puttemprdataset(soaquery, &rdataset);
03079 dns_message_destroy(&soaquery);
03080 done_update();
03081 return;
03082 }
03083 firstname = NULL;
03084 dns_message_currentname(updatemsg, section, &firstname);
03085 dns_name_init(name, NULL);
03086 dns_name_clone(firstname, name);
03087
03088
03089
03090
03091
03092
03093 tmprdataset = ISC_LIST_HEAD(firstname->list);
03094 if (section == DNS_SECTION_UPDATE &&
03095 !dns_name_equal(firstname, dns_rootname) &&
03096 tmprdataset->type == dns_rdatatype_ds) {
03097 unsigned int labels = dns_name_countlabels(name);
03098 dns_name_getlabelsequence(name, 1, labels - 1, name);
03099 }
03100 }
03101
03102 ISC_LIST_INIT(name->list);
03103 ISC_LIST_APPEND(name->list, rdataset, link);
03104 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
03105
03106 ns_inuse = 0;
03107 sendrequest(&servers[ns_inuse], soaquery, &request);
03108 }
03109
03110 static void
03111 cleanup(void) {
03112 ddebug("cleanup()");
03113
03114 if (answer != NULL)
03115 dns_message_destroy(&answer);
03116
03117 #ifdef GSSAPI
03118 if (tsigkey != NULL) {
03119 ddebug("detach tsigkey x%p", tsigkey);
03120 dns_tsigkey_detach(&tsigkey);
03121 }
03122 if (gssring != NULL) {
03123 ddebug("Detaching GSS-TSIG keyring");
03124 dns_tsigkeyring_detach(&gssring);
03125 }
03126 if (kserver != NULL) {
03127 isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
03128 kserver = NULL;
03129 }
03130 if (realm != NULL) {
03131 isc_mem_free(gmctx, realm);
03132 realm = NULL;
03133 }
03134 #endif
03135
03136 if (sig0key != NULL)
03137 dst_key_free(&sig0key);
03138
03139 ddebug("Shutting down task manager");
03140 isc_taskmgr_destroy(&taskmgr);
03141
03142 ddebug("Destroying event");
03143 isc_event_free(&global_event);
03144
03145 ddebug("Shutting down socket manager");
03146 isc_socketmgr_destroy(&socketmgr);
03147
03148 ddebug("Shutting down timer manager");
03149 isc_timermgr_destroy(&timermgr);
03150
03151 ddebug("Destroying hash context");
03152 isc_hash_destroy();
03153
03154 ddebug("Destroying name state");
03155 dns_name_destroy();
03156
03157 ddebug("Removing log context");
03158 isc_log_destroy(&glctx);
03159
03160 ddebug("Destroying memory context");
03161 if (memdebugging)
03162 isc_mem_stats(gmctx, stderr);
03163 isc_mem_destroy(&gmctx);
03164 }
03165
03166 static void
03167 getinput(isc_task_t *task, isc_event_t *event) {
03168 isc_boolean_t more;
03169
03170 UNUSED(task);
03171
03172 if (shuttingdown) {
03173 maybeshutdown();
03174 return;
03175 }
03176
03177 if (global_event == NULL)
03178 global_event = event;
03179
03180 reset_system();
03181 more = user_interaction();
03182 if (!more) {
03183 isc_app_shutdown();
03184 return;
03185 }
03186 start_update();
03187 return;
03188 }
03189
03190 int
03191 main(int argc, char **argv) {
03192 isc_result_t result;
03193 style = &dns_master_style_debug;
03194
03195 input = stdin;
03196
03197 interactive = ISC_TF(isatty(0));
03198
03199 isc_app_start();
03200
03201 pre_parse_args(argc, argv);
03202
03203 result = isc_mem_create(0, 0, &gmctx);
03204 check_result(result, "isc_mem_create");
03205
03206 parse_args(argc, argv, gmctx, &entropy);
03207
03208 setup_system();
03209
03210 result = isc_app_onrun(gmctx, global_task, getinput, NULL);
03211 check_result(result, "isc_app_onrun");
03212
03213 (void)isc_app_run();
03214
03215 cleanup();
03216
03217 isc_app_finish();
03218
03219 if (seenerror)
03220 return (2);
03221 else
03222 return (0);
03223 }