2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
31 #include <isc/base64.h>
32 #include <isc/buffer.h>
33 #include <isc/commandline.h>
34 #include <isc/entropy.h>
35 #include <isc/event.h>
41 #include <isc/parseint.h>
42 #include <isc/print.h>
43 #include <isc/random.h>
44 #include <isc/region.h>
45 #include <isc/sockaddr.h>
46 #include <isc/socket.h>
47 #include <isc/stdio.h>
48 #include <isc/string.h>
50 #include <isc/timer.h>
51 #include <isc/types.h>
54 #include <isccfg/namedconf.h>
56 #include <dns/callbacks.h>
57 #include <dns/dispatch.h>
58 #include <dns/dnssec.h>
59 #include <dns/events.h>
60 #include <dns/fixedname.h>
62 #include <dns/masterdump.h>
63 #include <dns/message.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatastruct.h>
71 #include <dns/rdatatype.h>
72 #include <dns/request.h>
73 #include <dns/result.h>
79 #include <lwres/lwres.h>
80 #include <lwres/net.h>
83 #include <dst/gssapi.h>
85 #include <krb5/krb5.h>
87 #include ISC_PLATFORM_KRB5HEADER
90 #include <bind9/getaddresses.h>
92 #if defined(HAVE_READLINE)
93 #include <readline/readline.h>
94 #include <readline/history.h>
98 #ifdef HAVE_GETADDRINFO
99 #ifdef HAVE_GAISTRERROR
100 #define USE_GETADDRINFO
105 #ifndef USE_GETADDRINFO
106 #ifndef ISC_PLATFORM_NONSTDHERRNO
111 #define MAXCMD (4 * 1024)
112 #define MAXWIRE (64 * 1024)
113 #define PACKETSIZE ((64 * 1024) - 1)
114 #define INITTEXT (2 * 1024)
115 #define MAXTEXT (128 * 1024)
116 #define FIND_TIMEOUT 5
117 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
119 #define DNSDEFAULTPORT 53
121 static isc_uint16_t dnsport = DNSDEFAULTPORT;
124 #define RESOLV_CONF "/etc/resolv.conf"
127 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
128 static isc_boolean_t memdebugging = ISC_FALSE;
129 static isc_boolean_t have_ipv4 = ISC_FALSE;
130 static isc_boolean_t have_ipv6 = ISC_FALSE;
131 static isc_boolean_t is_dst_up = ISC_FALSE;
132 static isc_boolean_t usevc = ISC_FALSE;
133 static isc_boolean_t usegsstsig = ISC_FALSE;
134 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
135 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
136 static isc_boolean_t local_only = ISC_FALSE;
137 static isc_taskmgr_t *taskmgr = NULL;
138 static isc_task_t *global_task = NULL;
139 static isc_event_t *global_event = NULL;
140 static isc_log_t *lctx = NULL;
141 static isc_mem_t *mctx = NULL;
142 static dns_dispatchmgr_t *dispatchmgr = NULL;
143 static dns_requestmgr_t *requestmgr = NULL;
144 static isc_socketmgr_t *socketmgr = NULL;
145 static isc_timermgr_t *timermgr = NULL;
146 static dns_dispatch_t *dispatchv4 = NULL;
147 static dns_dispatch_t *dispatchv6 = NULL;
148 static dns_message_t *updatemsg = NULL;
149 static dns_fixedname_t fuserzone;
150 static dns_name_t *userzone = NULL;
151 static dns_name_t *zonename = NULL;
152 static dns_name_t tmpzonename;
153 static dns_name_t restart_master;
154 static dns_tsig_keyring_t *gssring = NULL;
155 static dns_tsigkey_t *tsigkey = NULL;
156 static dst_key_t *sig0key = NULL;
157 static lwres_context_t *lwctx = NULL;
158 static lwres_conf_t *lwconf;
159 static isc_sockaddr_t *servers;
160 static int ns_inuse = 0;
161 static int ns_total = 0;
162 static isc_sockaddr_t *userserver = NULL;
163 static isc_sockaddr_t *localaddr = NULL;
164 static isc_sockaddr_t *serveraddr = NULL;
165 static isc_sockaddr_t tempaddr;
166 static const char *keyfile = NULL;
167 static char *keystr = NULL;
168 static isc_entropy_t *entropy = NULL;
169 static isc_boolean_t shuttingdown = ISC_FALSE;
171 static isc_boolean_t interactive = ISC_TRUE;
172 static isc_boolean_t seenerror = ISC_FALSE;
173 static const dns_master_style_t *style;
174 static int requests = 0;
175 static unsigned int logdebuglevel = 0;
176 static unsigned int timeout = 300;
177 static unsigned int udp_timeout = 3;
178 static unsigned int udp_retries = 3;
179 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
180 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
181 static dns_message_t *answer = NULL;
182 static isc_uint32_t default_ttl = 0;
183 static isc_boolean_t default_ttl_set = ISC_FALSE;
185 typedef struct nsu_requestinfo {
187 isc_sockaddr_t *addr;
191 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
192 dns_message_t *msg, dns_request_t **request);
194 ISC_PLATFORM_NORETURN_PRE static void
195 fatal(const char *format, ...)
196 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
199 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
202 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
205 static dns_fixedname_t fkname;
206 static isc_sockaddr_t *kserver = NULL;
207 static char *realm = NULL;
208 static char servicename[DNS_NAME_FORMATSIZE];
209 static dns_name_t *keyname;
210 typedef struct nsu_gssinfo {
212 isc_sockaddr_t *addr;
213 gss_ctx_id_t context;
217 start_gssrequest(dns_name_t *master);
219 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
220 dns_message_t *msg, dns_request_t **request,
221 gss_ctx_id_t context);
223 recvgss(isc_task_t *task, isc_event_t *event);
227 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
229 #define STATUS_MORE (isc_uint16_t)0
230 #define STATUS_SEND (isc_uint16_t)1
231 #define STATUS_QUIT (isc_uint16_t)2
232 #define STATUS_SYNTAX (isc_uint16_t)3
234 typedef struct entropysource entropysource_t;
236 struct entropysource {
237 isc_entropysource_t *source;
239 ISC_LINK(entropysource_t) link;
242 static ISC_LIST(entropysource_t) sources;
245 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
248 isc_entropysource_t *source = NULL;
249 entropysource_t *elt;
250 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
252 REQUIRE(ectx != NULL);
255 result = isc_entropy_create(mctx, ectx);
256 if (result != ISC_R_SUCCESS)
257 fatal("could not create entropy object");
258 ISC_LIST_INIT(sources);
261 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
262 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
266 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
269 if (result != ISC_R_SUCCESS)
270 fatal("could not initialize entropy source: %s",
271 isc_result_totext(result));
273 if (source != NULL) {
274 elt = isc_mem_get(mctx, sizeof(*elt));
276 fatal("out of memory");
277 elt->source = source;
279 ISC_LINK_INIT(elt, link);
280 ISC_LIST_APPEND(sources, elt, link);
285 cleanup_entropy(isc_entropy_t **ectx) {
286 entropysource_t *source;
287 while (!ISC_LIST_EMPTY(sources)) {
288 source = ISC_LIST_HEAD(sources);
289 ISC_LIST_UNLINK(sources, source, link);
290 isc_entropy_destroysource(&source->source);
291 isc_mem_put(source->mctx, source, sizeof(*source));
293 isc_entropy_detach(ectx);
297 static dns_rdataclass_t
299 if (zoneclass == dns_rdataclass_none)
300 zoneclass = defaultclass;
305 setzoneclass(dns_rdataclass_t rdclass) {
306 if (zoneclass == dns_rdataclass_none ||
307 rdclass == dns_rdataclass_none)
309 if (zoneclass != rdclass)
315 fatal(const char *format, ...) {
318 va_start(args, format);
319 vfprintf(stderr, format, args);
321 fprintf(stderr, "\n");
326 error(const char *format, ...) {
329 va_start(args, format);
330 vfprintf(stderr, format, args);
332 fprintf(stderr, "\n");
336 debug(const char *format, ...) {
340 va_start(args, format);
341 vfprintf(stderr, format, args);
343 fprintf(stderr, "\n");
348 ddebug(const char *format, ...) {
352 va_start(args, format);
353 vfprintf(stderr, format, args);
355 fprintf(stderr, "\n");
360 check_result(isc_result_t result, const char *msg) {
361 if (result != ISC_R_SUCCESS)
362 fatal("%s: %s", msg, isc_result_totext(result));
366 mem_alloc(void *arg, size_t size) {
367 return (isc_mem_get(arg, size));
371 mem_free(void *arg, void *mem, size_t size) {
372 isc_mem_put(arg, mem, size);
376 nsu_strsep(char **stringp, const char *delim) {
377 char *string = *stringp;
385 for (; *string != '\0'; string++) {
387 for (d = delim; (dc = *d) != '\0'; d++) {
395 for (s = string; *s != '\0'; s++) {
397 for (d = delim; (dc = *d) != '\0'; d++) {
413 ddebug("reset_system()");
414 /* If the update message is still around, destroy it */
415 if (updatemsg != NULL)
416 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
418 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
420 check_result(result, "dns_message_create");
422 updatemsg->opcode = dns_opcode_update;
425 dns_tsigkey_detach(&tsigkey);
427 dns_tsigkeyring_detach(&gssring);
428 tried_other_gsstsig = ISC_FALSE;
433 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
434 isc_uint16_t digestbits = 0;
438 REQUIRE(hmac != NULL && *hmac == NULL);
439 REQUIRE(hmacstr != NULL);
441 if (len >= sizeof(buf))
442 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
444 strncpy(buf, hmacstr, len);
447 if (strcasecmp(buf, "hmac-md5") == 0) {
448 *hmac = DNS_TSIG_HMACMD5_NAME;
449 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
450 *hmac = DNS_TSIG_HMACMD5_NAME;
451 result = isc_parse_uint16(&digestbits, &buf[9], 10);
452 if (result != ISC_R_SUCCESS || digestbits > 128)
453 fatal("digest-bits out of range [0..128]");
454 digestbits = (digestbits +7) & ~0x7U;
455 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
456 *hmac = DNS_TSIG_HMACSHA1_NAME;
457 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
458 *hmac = DNS_TSIG_HMACSHA1_NAME;
459 result = isc_parse_uint16(&digestbits, &buf[10], 10);
460 if (result != ISC_R_SUCCESS || digestbits > 160)
461 fatal("digest-bits out of range [0..160]");
462 digestbits = (digestbits +7) & ~0x7U;
463 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
464 *hmac = DNS_TSIG_HMACSHA224_NAME;
465 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
466 *hmac = DNS_TSIG_HMACSHA224_NAME;
467 result = isc_parse_uint16(&digestbits, &buf[12], 10);
468 if (result != ISC_R_SUCCESS || digestbits > 224)
469 fatal("digest-bits out of range [0..224]");
470 digestbits = (digestbits +7) & ~0x7U;
471 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
472 *hmac = DNS_TSIG_HMACSHA256_NAME;
473 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
474 *hmac = DNS_TSIG_HMACSHA256_NAME;
475 result = isc_parse_uint16(&digestbits, &buf[12], 10);
476 if (result != ISC_R_SUCCESS || digestbits > 256)
477 fatal("digest-bits out of range [0..256]");
478 digestbits = (digestbits +7) & ~0x7U;
479 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
480 *hmac = DNS_TSIG_HMACSHA384_NAME;
481 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
482 *hmac = DNS_TSIG_HMACSHA384_NAME;
483 result = isc_parse_uint16(&digestbits, &buf[12], 10);
484 if (result != ISC_R_SUCCESS || digestbits > 384)
485 fatal("digest-bits out of range [0..384]");
486 digestbits = (digestbits +7) & ~0x7U;
487 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
488 *hmac = DNS_TSIG_HMACSHA512_NAME;
489 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
490 *hmac = DNS_TSIG_HMACSHA512_NAME;
491 result = isc_parse_uint16(&digestbits, &buf[12], 10);
492 if (result != ISC_R_SUCCESS || digestbits > 512)
493 fatal("digest-bits out of range [0..512]");
494 digestbits = (digestbits +7) & ~0x7U;
496 fatal("unknown key type '%s'", buf);
501 basenamelen(const char *file) {
502 int len = strlen(file);
504 if (len > 1 && file[len - 1] == '.')
506 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
508 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
515 unsigned char *secret = NULL;
517 isc_buffer_t secretbuf;
519 isc_buffer_t keynamesrc;
522 dns_fixedname_t fkeyname;
525 dns_name_t *hmacname = NULL;
526 isc_uint16_t digestbits = 0;
528 dns_fixedname_init(&fkeyname);
529 keyname = dns_fixedname_name(&fkeyname);
531 debug("Creating key...");
533 s = strchr(keystr, ':');
534 if (s == NULL || s == keystr || s[1] == 0)
535 fatal("key option must specify [hmac:]keyname:secret");
537 n = strchr(secretstr, ':');
539 if (n == secretstr || n[1] == 0)
540 fatal("key option must specify [hmac:]keyname:secret");
543 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
545 hmacname = DNS_TSIG_HMACMD5_NAME;
550 isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
551 isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
553 debug("namefromtext");
554 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL);
555 check_result(result, "dns_name_fromtext");
557 secretlen = strlen(secretstr) * 3 / 4;
558 secret = isc_mem_allocate(mctx, secretlen);
560 fatal("out of memory");
562 isc_buffer_init(&secretbuf, secret, secretlen);
563 result = isc_base64_decodestring(secretstr, &secretbuf);
564 if (result != ISC_R_SUCCESS) {
565 fprintf(stderr, "could not create key from %s: %s\n",
566 keystr, isc_result_totext(result));
570 secretlen = isc_buffer_usedlength(&secretbuf);
573 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
574 ISC_FALSE, NULL, 0, 0, mctx, NULL,
576 if (result != ISC_R_SUCCESS)
577 fprintf(stderr, "could not create key from %s: %s\n",
578 keystr, dns_result_totext(result));
580 dst_key_setbits(tsigkey->key, digestbits);
583 isc_mem_free(mctx, secret);
587 * Get a key from a named.conf format keyfile
590 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
591 cfg_parser_t *pctx = NULL;
592 cfg_obj_t *sessionkey = NULL;
593 const cfg_obj_t *key = NULL;
594 const cfg_obj_t *secretobj = NULL;
595 const cfg_obj_t *algorithmobj = NULL;
597 const char *secretstr;
598 const char *algorithm;
602 if (! isc_file_exists(keyfile))
603 return (ISC_R_FILENOTFOUND);
605 result = cfg_parser_create(mctx, lctx, &pctx);
606 if (result != ISC_R_SUCCESS)
609 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
611 if (result != ISC_R_SUCCESS)
614 result = cfg_map_get(sessionkey, "key", &key);
615 if (result != ISC_R_SUCCESS)
618 (void) cfg_map_get(key, "secret", &secretobj);
619 (void) cfg_map_get(key, "algorithm", &algorithmobj);
620 if (secretobj == NULL || algorithmobj == NULL)
621 fatal("key must have algorithm and secret");
623 keyname = cfg_obj_asstring(cfg_map_getname(key));
624 secretstr = cfg_obj_asstring(secretobj);
625 algorithm = cfg_obj_asstring(algorithmobj);
627 len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3;
628 keystr = isc_mem_allocate(mctx, len);
629 snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr);
634 if (sessionkey != NULL)
635 cfg_obj_destroy(pctx, &sessionkey);
636 cfg_parser_destroy(&pctx);
640 isc_mem_free(mctx, keystr);
646 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
647 dst_key_t *dstkey = NULL;
649 dns_name_t *hmacname = NULL;
651 debug("Creating key...");
654 dst_key_free(&sig0key);
656 /* Try reading the key from a K* pair */
657 result = dst_key_fromnamedfile(keyfile, NULL,
658 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
661 /* If that didn't work, try reading it as a session.key keyfile */
662 if (result != ISC_R_SUCCESS) {
663 result = read_sessionkey(mctx, lctx);
664 if (result == ISC_R_SUCCESS)
668 if (result != ISC_R_SUCCESS) {
669 fprintf(stderr, "could not read key from %.*s.{private,key}: "
670 "%s\n", basenamelen(keyfile), keyfile,
671 isc_result_totext(result));
675 switch (dst_key_alg(dstkey)) {
676 case DST_ALG_HMACMD5:
677 hmacname = DNS_TSIG_HMACMD5_NAME;
679 case DST_ALG_HMACSHA1:
680 hmacname = DNS_TSIG_HMACSHA1_NAME;
682 case DST_ALG_HMACSHA224:
683 hmacname = DNS_TSIG_HMACSHA224_NAME;
685 case DST_ALG_HMACSHA256:
686 hmacname = DNS_TSIG_HMACSHA256_NAME;
688 case DST_ALG_HMACSHA384:
689 hmacname = DNS_TSIG_HMACSHA384_NAME;
691 case DST_ALG_HMACSHA512:
692 hmacname = DNS_TSIG_HMACSHA512_NAME;
695 if (hmacname != NULL) {
696 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
697 hmacname, dstkey, ISC_FALSE,
698 NULL, 0, 0, mctx, NULL,
700 dst_key_free(&dstkey);
701 if (result != ISC_R_SUCCESS) {
702 fprintf(stderr, "could not create key from %s: %s\n",
703 keyfile, isc_result_totext(result));
707 dst_key_attach(dstkey, &sig0key);
708 dst_key_free(&dstkey);
714 isc_task_detach(&global_task);
716 if (userserver != NULL)
717 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
719 if (localaddr != NULL)
720 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
722 if (tsigkey != NULL) {
723 ddebug("Freeing TSIG key");
724 dns_tsigkey_detach(&tsigkey);
727 if (sig0key != NULL) {
728 ddebug("Freeing SIG(0) key");
729 dst_key_free(&sig0key);
732 if (updatemsg != NULL)
733 dns_message_destroy(&updatemsg);
736 ddebug("Destroy DST lib");
738 is_dst_up = ISC_FALSE;
741 cleanup_entropy(&entropy);
743 lwres_conf_clear(lwctx);
744 lwres_context_destroy(&lwctx);
746 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
748 ddebug("Destroying request manager");
749 dns_requestmgr_detach(&requestmgr);
751 ddebug("Freeing the dispatchers");
753 dns_dispatch_detach(&dispatchv4);
755 dns_dispatch_detach(&dispatchv6);
757 ddebug("Shutting down dispatch manager");
758 dns_dispatchmgr_destroy(&dispatchmgr);
763 maybeshutdown(void) {
764 ddebug("Shutting down request manager");
765 dns_requestmgr_shutdown(requestmgr);
774 shutdown_program(isc_task_t *task, isc_event_t *event) {
775 REQUIRE(task == global_task);
778 ddebug("shutdown_program()");
779 isc_event_free(&event);
781 shuttingdown = ISC_TRUE;
788 isc_sockaddr_t bind_any, bind_any6;
789 lwres_result_t lwresult;
790 unsigned int attrs, attrmask;
792 isc_logconfig_t *logconfig = NULL;
794 ddebug("setup_system()");
796 dns_result_register();
798 result = isc_net_probeipv4();
799 if (result == ISC_R_SUCCESS)
800 have_ipv4 = ISC_TRUE;
802 result = isc_net_probeipv6();
803 if (result == ISC_R_SUCCESS)
804 have_ipv6 = ISC_TRUE;
806 if (!have_ipv4 && !have_ipv6)
807 fatal("could not find either IPv4 or IPv6");
809 result = isc_log_create(mctx, &lctx, &logconfig);
810 check_result(result, "isc_log_create");
812 isc_log_setcontext(lctx);
814 dns_log_setcontext(lctx);
816 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
817 check_result(result, "isc_log_usechannel");
819 isc_log_setdebuglevel(lctx, logdebuglevel);
821 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
822 if (lwresult != LWRES_R_SUCCESS)
823 fatal("lwres_context_create failed");
825 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
826 lwconf = lwres_conf_get(lwctx);
828 ns_total = lwconf->nsnext;
830 /* No name servers in resolv.conf; default to loopback. */
831 struct in_addr localhost;
833 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
835 fatal("out of memory");
836 localhost.s_addr = htonl(INADDR_LOOPBACK);
837 isc_sockaddr_fromin(&servers[0], &localhost, dnsport);
839 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
841 fatal("out of memory");
842 for (i = 0; i < ns_total; i++) {
843 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4)
847 lwconf->nameservers[i].address, 4);
848 isc_sockaddr_fromin(&servers[i], &in4, dnsport);
852 lwconf->nameservers[i].address, 16);
853 isc_sockaddr_fromin6(&servers[i], &in6,
859 setup_entropy(mctx, NULL, &entropy);
861 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
862 check_result(result, "isc_hash_create");
865 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
866 check_result(result, "dns_dispatchmgr_create");
868 result = isc_socketmgr_create(mctx, &socketmgr);
869 check_result(result, "dns_socketmgr_create");
871 result = isc_timermgr_create(mctx, &timermgr);
872 check_result(result, "dns_timermgr_create");
874 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
875 check_result(result, "isc_taskmgr_create");
877 result = isc_task_create(taskmgr, 0, &global_task);
878 check_result(result, "isc_task_create");
880 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
881 check_result(result, "isc_task_onshutdown");
883 result = dst_lib_init(mctx, entropy, 0);
884 check_result(result, "dst_lib_init");
885 is_dst_up = ISC_TRUE;
887 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
888 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
891 attrs = DNS_DISPATCHATTR_UDP;
892 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
893 attrs |= DNS_DISPATCHATTR_IPV6;
894 isc_sockaddr_any6(&bind_any6);
895 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
896 &bind_any6, PACKETSIZE,
898 attrs, attrmask, &dispatchv6);
899 check_result(result, "dns_dispatch_getudp (v6)");
903 attrs = DNS_DISPATCHATTR_UDP;
904 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
905 attrs |= DNS_DISPATCHATTR_IPV4;
906 isc_sockaddr_any(&bind_any);
907 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
908 &bind_any, PACKETSIZE,
910 attrs, attrmask, &dispatchv4);
911 check_result(result, "dns_dispatch_getudp (v4)");
914 result = dns_requestmgr_create(mctx, timermgr,
915 socketmgr, taskmgr, dispatchmgr,
916 dispatchv4, dispatchv6, &requestmgr);
917 check_result(result, "dns_requestmgr_create");
921 else if (local_only) {
922 result = read_sessionkey(mctx, lctx);
923 if (result != ISC_R_SUCCESS)
924 fatal("can't read key from %s: %s\n",
925 keyfile, isc_result_totext(result));
926 } else if (keyfile != NULL)
927 setup_keyfile(mctx, lctx);
931 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
936 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
938 if (result != ISC_R_SUCCESS)
939 fatal("couldn't get address for '%s': %s",
940 host, isc_result_totext(result));
944 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:r:R::t:u:"
947 pre_parse_args(int argc, char **argv) {
950 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
952 case 'M': /* was -dm */
953 debugging = ISC_TRUE;
954 ddebugging = ISC_TRUE;
955 memdebugging = ISC_TRUE;
956 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
962 if (isc_commandline_option != '?')
963 fprintf(stderr, "%s: invalid argument -%c\n",
964 argv[0], isc_commandline_option);
965 fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
966 "[-g | -o | -y keyname:secret | -k keyfile] "
967 "[-v] [filename]\n");
974 isc_commandline_reset = ISC_TRUE;
975 isc_commandline_index = 1;
979 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
985 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
988 debugging = ISC_TRUE;
990 case 'D': /* was -dd */
991 debugging = ISC_TRUE;
992 ddebugging = ISC_TRUE;
997 local_only = ISC_TRUE;
1000 result = isc_parse_uint32(&i, isc_commandline_argument,
1002 if (result != ISC_R_SUCCESS) {
1003 fprintf(stderr, "bad library debug value "
1004 "'%s'\n", isc_commandline_argument);
1010 keystr = isc_commandline_argument;
1016 keyfile = isc_commandline_argument;
1019 usegsstsig = ISC_TRUE;
1020 use_win2k_gsstsig = ISC_FALSE;
1023 usegsstsig = ISC_TRUE;
1024 use_win2k_gsstsig = ISC_TRUE;
1027 result = isc_parse_uint16(&dnsport,
1028 isc_commandline_argument, 10);
1029 if (result != ISC_R_SUCCESS) {
1030 fprintf(stderr, "bad port number "
1031 "'%s'\n", isc_commandline_argument);
1036 result = isc_parse_uint32(&timeout,
1037 isc_commandline_argument, 10);
1038 if (result != ISC_R_SUCCESS) {
1039 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
1046 result = isc_parse_uint32(&udp_timeout,
1047 isc_commandline_argument, 10);
1048 if (result != ISC_R_SUCCESS) {
1049 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
1052 if (udp_timeout == 0)
1053 udp_timeout = UINT_MAX;
1056 result = isc_parse_uint32(&udp_retries,
1057 isc_commandline_argument, 10);
1058 if (result != ISC_R_SUCCESS) {
1059 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
1065 setup_entropy(mctx, isc_commandline_argument, ectx);
1069 fprintf(stderr, "%s: unhandled option: %c\n",
1070 argv[0], isc_commandline_option);
1074 if (keyfile != NULL && keystr != NULL) {
1075 fprintf(stderr, "%s: cannot specify both -k and -y\n",
1081 struct in_addr localhost;
1083 if (keyfile == NULL)
1084 keyfile = SESSION_KEYFILE;
1086 if (userserver == NULL) {
1087 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1088 if (userserver == NULL)
1089 fatal("out of memory");
1092 localhost.s_addr = htonl(INADDR_LOOPBACK);
1093 isc_sockaddr_fromin(userserver, &localhost, dnsport);
1097 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1098 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1104 fprintf(stderr, "%s: cannot specify -g or -o, " \
1105 "program not linked with GSS API Library\n",
1111 if (argv[isc_commandline_index] != NULL) {
1112 if (strcmp(argv[isc_commandline_index], "-") == 0) {
1115 result = isc_stdio_open(argv[isc_commandline_index],
1117 if (result != ISC_R_SUCCESS) {
1118 fprintf(stderr, "could not open '%s': %s\n",
1119 argv[isc_commandline_index],
1120 isc_result_totext(result));
1124 interactive = ISC_FALSE;
1129 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1130 isc_result_t result;
1132 isc_buffer_t *namebuf = NULL;
1133 isc_buffer_t source;
1135 word = nsu_strsep(cmdlinep, " \t\r\n");
1136 if (word == NULL || *word == 0) {
1137 fprintf(stderr, "could not read owner name\n");
1138 return (STATUS_SYNTAX);
1141 result = dns_message_gettempname(msg, namep);
1142 check_result(result, "dns_message_gettempname");
1143 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
1144 check_result(result, "isc_buffer_allocate");
1145 dns_name_init(*namep, NULL);
1146 dns_name_setbuffer(*namep, namebuf);
1147 dns_message_takebuffer(msg, &namebuf);
1148 isc_buffer_init(&source, word, strlen(word));
1149 isc_buffer_add(&source, strlen(word));
1150 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
1151 check_result(result, "dns_name_fromtext");
1152 isc_buffer_invalidate(&source);
1153 return (STATUS_MORE);
1157 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1158 dns_rdatatype_t rdatatype, dns_message_t *msg,
1161 char *cmdline = *cmdlinep;
1162 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1164 isc_lex_t *lex = NULL;
1165 dns_rdatacallbacks_t callbacks;
1166 isc_result_t result;
1168 if (cmdline == NULL) {
1169 rdata->flags = DNS_RDATA_UPDATE;
1170 return (STATUS_MORE);
1173 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1176 if (*cmdline != 0) {
1177 dns_rdatacallbacks_init(&callbacks);
1178 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1179 check_result(result, "isc_lex_create");
1180 isc_buffer_init(&source, cmdline, strlen(cmdline));
1181 isc_buffer_add(&source, strlen(cmdline));
1182 result = isc_lex_openbuffer(lex, &source);
1183 check_result(result, "isc_lex_openbuffer");
1184 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1185 check_result(result, "isc_buffer_allocate");
1186 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1187 dns_rootname, 0, mctx, buf,
1189 isc_lex_destroy(&lex);
1190 if (result == ISC_R_SUCCESS) {
1191 isc_buffer_usedregion(buf, &r);
1192 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1193 check_result(result, "isc_buffer_allocate");
1194 isc_buffer_putmem(newbuf, r.base, r.length);
1195 isc_buffer_usedregion(newbuf, &r);
1196 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1197 isc_buffer_free(&buf);
1198 dns_message_takebuffer(msg, &newbuf);
1200 fprintf(stderr, "invalid rdata format: %s\n",
1201 isc_result_totext(result));
1202 isc_buffer_free(&buf);
1203 return (STATUS_SYNTAX);
1206 rdata->flags = DNS_RDATA_UPDATE;
1208 *cmdlinep = cmdline;
1209 return (STATUS_MORE);
1213 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1214 isc_result_t result;
1216 dns_name_t *name = NULL;
1217 isc_textregion_t region;
1218 dns_rdataset_t *rdataset = NULL;
1219 dns_rdatalist_t *rdatalist = NULL;
1220 dns_rdataclass_t rdataclass;
1221 dns_rdatatype_t rdatatype;
1222 dns_rdata_t *rdata = NULL;
1223 isc_uint16_t retval;
1225 ddebug("make_prereq()");
1228 * Read the owner name
1230 retval = parse_name(&cmdline, updatemsg, &name);
1231 if (retval != STATUS_MORE)
1235 * If this is an rrset prereq, read the class or type.
1238 word = nsu_strsep(&cmdline, " \t\r\n");
1239 if (word == NULL || *word == 0) {
1240 fprintf(stderr, "could not read class or type\n");
1244 region.length = strlen(word);
1245 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1246 if (result == ISC_R_SUCCESS) {
1247 if (!setzoneclass(rdataclass)) {
1248 fprintf(stderr, "class mismatch: %s\n", word);
1252 * Now read the type.
1254 word = nsu_strsep(&cmdline, " \t\r\n");
1255 if (word == NULL || *word == 0) {
1256 fprintf(stderr, "could not read type\n");
1260 region.length = strlen(word);
1261 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1262 if (result != ISC_R_SUCCESS) {
1263 fprintf(stderr, "invalid type: %s\n", word);
1267 rdataclass = getzoneclass();
1268 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1269 if (result != ISC_R_SUCCESS) {
1270 fprintf(stderr, "invalid type: %s\n", word);
1275 rdatatype = dns_rdatatype_any;
1277 result = dns_message_gettemprdata(updatemsg, &rdata);
1278 check_result(result, "dns_message_gettemprdata");
1280 dns_rdata_init(rdata);
1282 if (isrrset && ispositive) {
1283 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1285 if (retval != STATUS_MORE)
1288 rdata->flags = DNS_RDATA_UPDATE;
1290 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1291 check_result(result, "dns_message_gettemprdatalist");
1292 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1293 check_result(result, "dns_message_gettemprdataset");
1294 dns_rdatalist_init(rdatalist);
1295 rdatalist->type = rdatatype;
1297 if (isrrset && rdata->data != NULL)
1298 rdatalist->rdclass = rdataclass;
1300 rdatalist->rdclass = dns_rdataclass_any;
1302 rdatalist->rdclass = dns_rdataclass_none;
1303 rdatalist->covers = 0;
1305 rdata->rdclass = rdatalist->rdclass;
1306 rdata->type = rdatatype;
1307 ISC_LIST_INIT(rdatalist->rdata);
1308 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1309 dns_rdataset_init(rdataset);
1310 dns_rdatalist_tordataset(rdatalist, rdataset);
1311 ISC_LIST_INIT(name->list);
1312 ISC_LIST_APPEND(name->list, rdataset, link);
1313 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1314 return (STATUS_MORE);
1318 dns_message_puttempname(updatemsg, &name);
1319 return (STATUS_SYNTAX);
1323 evaluate_prereq(char *cmdline) {
1325 isc_boolean_t ispositive, isrrset;
1327 ddebug("evaluate_prereq()");
1328 word = nsu_strsep(&cmdline, " \t\r\n");
1329 if (word == NULL || *word == 0) {
1330 fprintf(stderr, "could not read operation code\n");
1331 return (STATUS_SYNTAX);
1333 if (strcasecmp(word, "nxdomain") == 0) {
1334 ispositive = ISC_FALSE;
1335 isrrset = ISC_FALSE;
1336 } else if (strcasecmp(word, "yxdomain") == 0) {
1337 ispositive = ISC_TRUE;
1338 isrrset = ISC_FALSE;
1339 } else if (strcasecmp(word, "nxrrset") == 0) {
1340 ispositive = ISC_FALSE;
1342 } else if (strcasecmp(word, "yxrrset") == 0) {
1343 ispositive = ISC_TRUE;
1346 fprintf(stderr, "incorrect operation code: %s\n", word);
1347 return (STATUS_SYNTAX);
1349 return (make_prereq(cmdline, ispositive, isrrset));
1353 evaluate_server(char *cmdline) {
1354 char *word, *server;
1358 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1359 return (STATUS_SYNTAX);
1362 word = nsu_strsep(&cmdline, " \t\r\n");
1363 if (word == NULL || *word == 0) {
1364 fprintf(stderr, "could not read server name\n");
1365 return (STATUS_SYNTAX);
1369 word = nsu_strsep(&cmdline, " \t\r\n");
1370 if (word == NULL || *word == 0)
1374 port = strtol(word, &endp, 10);
1376 fprintf(stderr, "port '%s' is not numeric\n", word);
1377 return (STATUS_SYNTAX);
1378 } else if (port < 1 || port > 65535) {
1379 fprintf(stderr, "port '%s' is out of range "
1380 "(1 to 65535)\n", word);
1381 return (STATUS_SYNTAX);
1385 if (userserver == NULL) {
1386 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1387 if (userserver == NULL)
1388 fatal("out of memory");
1391 get_address(server, (in_port_t)port, userserver);
1393 return (STATUS_MORE);
1397 evaluate_local(char *cmdline) {
1401 struct in6_addr in6;
1403 word = nsu_strsep(&cmdline, " \t\r\n");
1404 if (word == NULL || *word == 0) {
1405 fprintf(stderr, "could not read server name\n");
1406 return (STATUS_SYNTAX);
1410 word = nsu_strsep(&cmdline, " \t\r\n");
1411 if (word == NULL || *word == 0)
1415 port = strtol(word, &endp, 10);
1417 fprintf(stderr, "port '%s' is not numeric\n", word);
1418 return (STATUS_SYNTAX);
1419 } else if (port < 1 || port > 65535) {
1420 fprintf(stderr, "port '%s' is out of range "
1421 "(1 to 65535)\n", word);
1422 return (STATUS_SYNTAX);
1426 if (localaddr == NULL) {
1427 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1428 if (localaddr == NULL)
1429 fatal("out of memory");
1432 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1433 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1434 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1435 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1437 fprintf(stderr, "invalid address %s", local);
1438 return (STATUS_SYNTAX);
1441 return (STATUS_MORE);
1445 evaluate_key(char *cmdline) {
1449 isc_result_t result;
1450 dns_fixedname_t fkeyname;
1451 dns_name_t *keyname;
1453 unsigned char *secret = NULL;
1454 isc_buffer_t secretbuf;
1455 dns_name_t *hmacname = NULL;
1456 isc_uint16_t digestbits = 0;
1459 namestr = nsu_strsep(&cmdline, " \t\r\n");
1460 if (namestr == NULL || *namestr == 0) {
1461 fprintf(stderr, "could not read key name\n");
1462 return (STATUS_SYNTAX);
1465 dns_fixedname_init(&fkeyname);
1466 keyname = dns_fixedname_name(&fkeyname);
1468 n = strchr(namestr, ':');
1470 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1473 hmacname = DNS_TSIG_HMACMD5_NAME;
1475 isc_buffer_init(&b, namestr, strlen(namestr));
1476 isc_buffer_add(&b, strlen(namestr));
1477 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
1478 if (result != ISC_R_SUCCESS) {
1479 fprintf(stderr, "could not parse key name\n");
1480 return (STATUS_SYNTAX);
1483 secretstr = nsu_strsep(&cmdline, "\r\n");
1484 if (secretstr == NULL || *secretstr == 0) {
1485 fprintf(stderr, "could not read key secret\n");
1486 return (STATUS_SYNTAX);
1488 secretlen = strlen(secretstr) * 3 / 4;
1489 secret = isc_mem_allocate(mctx, secretlen);
1491 fatal("out of memory");
1493 isc_buffer_init(&secretbuf, secret, secretlen);
1494 result = isc_base64_decodestring(secretstr, &secretbuf);
1495 if (result != ISC_R_SUCCESS) {
1496 fprintf(stderr, "could not create key from %s: %s\n",
1497 secretstr, isc_result_totext(result));
1498 isc_mem_free(mctx, secret);
1499 return (STATUS_SYNTAX);
1501 secretlen = isc_buffer_usedlength(&secretbuf);
1503 if (tsigkey != NULL)
1504 dns_tsigkey_detach(&tsigkey);
1505 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1506 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1508 isc_mem_free(mctx, secret);
1509 if (result != ISC_R_SUCCESS) {
1510 fprintf(stderr, "could not create key from %s %s: %s\n",
1511 namestr, secretstr, dns_result_totext(result));
1512 return (STATUS_SYNTAX);
1514 dst_key_setbits(tsigkey->key, digestbits);
1515 return (STATUS_MORE);
1519 evaluate_zone(char *cmdline) {
1522 isc_result_t result;
1524 word = nsu_strsep(&cmdline, " \t\r\n");
1525 if (word == NULL || *word == 0) {
1526 fprintf(stderr, "could not read zone name\n");
1527 return (STATUS_SYNTAX);
1530 dns_fixedname_init(&fuserzone);
1531 userzone = dns_fixedname_name(&fuserzone);
1532 isc_buffer_init(&b, word, strlen(word));
1533 isc_buffer_add(&b, strlen(word));
1534 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1535 if (result != ISC_R_SUCCESS) {
1536 userzone = NULL; /* Lest it point to an invalid name */
1537 fprintf(stderr, "could not parse zone name\n");
1538 return (STATUS_SYNTAX);
1541 return (STATUS_MORE);
1545 evaluate_realm(char *cmdline) {
1551 if (realm != NULL) {
1552 isc_mem_free(mctx, realm);
1556 word = nsu_strsep(&cmdline, " \t\r\n");
1557 if (word == NULL || *word == 0)
1558 return (STATUS_MORE);
1560 n = snprintf(buf, sizeof(buf), "@%s", word);
1561 if (n < 0 || (size_t)n >= sizeof(buf))
1562 fatal("realm is too long");
1563 realm = isc_mem_strdup(mctx, buf);
1565 fatal("out of memory");
1566 return (STATUS_MORE);
1569 return (STATUS_SYNTAX);
1574 evaluate_ttl(char *cmdline) {
1576 isc_result_t result;
1579 word = nsu_strsep(&cmdline, " \t\r\n");
1580 if (word == NULL || *word == 0) {
1581 fprintf(stderr, "could not ttl\n");
1582 return (STATUS_SYNTAX);
1585 if (!strcasecmp(word, "none")) {
1587 default_ttl_set = ISC_FALSE;
1588 return (STATUS_MORE);
1591 result = isc_parse_uint32(&ttl, word, 10);
1592 if (result != ISC_R_SUCCESS)
1593 return (STATUS_SYNTAX);
1595 if (ttl > TTL_MAX) {
1596 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1598 return (STATUS_SYNTAX);
1601 default_ttl_set = ISC_TRUE;
1603 return (STATUS_MORE);
1607 evaluate_class(char *cmdline) {
1610 isc_result_t result;
1611 dns_rdataclass_t rdclass;
1613 word = nsu_strsep(&cmdline, " \t\r\n");
1614 if (word == NULL || *word == 0) {
1615 fprintf(stderr, "could not read class name\n");
1616 return (STATUS_SYNTAX);
1620 r.length = strlen(word);
1621 result = dns_rdataclass_fromtext(&rdclass, &r);
1622 if (result != ISC_R_SUCCESS) {
1623 fprintf(stderr, "could not parse class name: %s\n", word);
1624 return (STATUS_SYNTAX);
1627 case dns_rdataclass_none:
1628 case dns_rdataclass_any:
1629 case dns_rdataclass_reserved0:
1630 fprintf(stderr, "bad default class: %s\n", word);
1631 return (STATUS_SYNTAX);
1633 defaultclass = rdclass;
1636 return (STATUS_MORE);
1640 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1641 isc_result_t result;
1642 dns_name_t *name = NULL;
1645 dns_rdataclass_t rdataclass;
1646 dns_rdatatype_t rdatatype;
1647 dns_rdata_t *rdata = NULL;
1648 dns_rdatalist_t *rdatalist = NULL;
1649 dns_rdataset_t *rdataset = NULL;
1650 isc_textregion_t region;
1651 isc_uint16_t retval;
1653 ddebug("update_addordelete()");
1656 * Read the owner name.
1658 retval = parse_name(&cmdline, updatemsg, &name);
1659 if (retval != STATUS_MORE)
1662 result = dns_message_gettemprdata(updatemsg, &rdata);
1663 check_result(result, "dns_message_gettemprdata");
1665 dns_rdata_init(rdata);
1668 * If this is an add, read the TTL and verify that it's in range.
1669 * If it's a delete, ignore a TTL if present (for compatibility).
1671 word = nsu_strsep(&cmdline, " \t\r\n");
1672 if (word == NULL || *word == 0) {
1674 fprintf(stderr, "could not read owner ttl\n");
1679 rdataclass = dns_rdataclass_any;
1680 rdatatype = dns_rdatatype_any;
1681 rdata->flags = DNS_RDATA_UPDATE;
1685 result = isc_parse_uint32(&ttl, word, 10);
1686 if (result != ISC_R_SUCCESS) {
1690 } else if (default_ttl_set) {
1694 fprintf(stderr, "ttl '%s': %s\n", word,
1695 isc_result_totext(result));
1702 else if (ttl > TTL_MAX) {
1703 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1709 * Read the class or type.
1711 word = nsu_strsep(&cmdline, " \t\r\n");
1713 if (word == NULL || *word == 0) {
1715 rdataclass = dns_rdataclass_any;
1716 rdatatype = dns_rdatatype_any;
1717 rdata->flags = DNS_RDATA_UPDATE;
1720 fprintf(stderr, "could not read class or type\n");
1725 region.length = strlen(word);
1726 rdataclass = dns_rdataclass_any;
1727 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1728 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1729 if (!setzoneclass(rdataclass)) {
1730 fprintf(stderr, "class mismatch: %s\n", word);
1734 * Now read the type.
1736 word = nsu_strsep(&cmdline, " \t\r\n");
1737 if (word == NULL || *word == 0) {
1739 rdataclass = dns_rdataclass_any;
1740 rdatatype = dns_rdatatype_any;
1741 rdata->flags = DNS_RDATA_UPDATE;
1744 fprintf(stderr, "could not read type\n");
1749 region.length = strlen(word);
1750 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1751 if (result != ISC_R_SUCCESS) {
1752 fprintf(stderr, "'%s' is not a valid type: %s\n",
1753 word, isc_result_totext(result));
1757 rdataclass = getzoneclass();
1758 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1759 if (result != ISC_R_SUCCESS) {
1760 fprintf(stderr, "'%s' is not a valid class or type: "
1761 "%s\n", word, isc_result_totext(result));
1766 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1768 if (retval != STATUS_MORE)
1772 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1773 rdataclass = dns_rdataclass_any;
1775 rdataclass = dns_rdataclass_none;
1777 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1778 fprintf(stderr, "could not read rdata\n");
1785 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1786 check_result(result, "dns_message_gettemprdatalist");
1787 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1788 check_result(result, "dns_message_gettemprdataset");
1789 dns_rdatalist_init(rdatalist);
1790 rdatalist->type = rdatatype;
1791 rdatalist->rdclass = rdataclass;
1792 rdatalist->covers = rdatatype;
1793 rdatalist->ttl = (dns_ttl_t)ttl;
1794 ISC_LIST_INIT(rdatalist->rdata);
1795 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1796 dns_rdataset_init(rdataset);
1797 dns_rdatalist_tordataset(rdatalist, rdataset);
1798 ISC_LIST_INIT(name->list);
1799 ISC_LIST_APPEND(name->list, rdataset, link);
1800 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1801 return (STATUS_MORE);
1805 dns_message_puttempname(updatemsg, &name);
1806 dns_message_puttemprdata(updatemsg, &rdata);
1807 return (STATUS_SYNTAX);
1811 evaluate_update(char *cmdline) {
1813 isc_boolean_t isdelete;
1815 ddebug("evaluate_update()");
1816 word = nsu_strsep(&cmdline, " \t\r\n");
1817 if (word == NULL || *word == 0) {
1818 fprintf(stderr, "could not read operation code\n");
1819 return (STATUS_SYNTAX);
1821 if (strcasecmp(word, "delete") == 0)
1822 isdelete = ISC_TRUE;
1823 else if (strcasecmp(word, "del") == 0)
1824 isdelete = ISC_TRUE;
1825 else if (strcasecmp(word, "add") == 0)
1826 isdelete = ISC_FALSE;
1828 fprintf(stderr, "incorrect operation code: %s\n", word);
1829 return (STATUS_SYNTAX);
1831 return (update_addordelete(cmdline, isdelete));
1835 setzone(dns_name_t *zonename) {
1836 isc_result_t result;
1837 dns_name_t *name = NULL;
1838 dns_rdataset_t *rdataset = NULL;
1840 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1841 if (result == ISC_R_SUCCESS) {
1842 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1843 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1844 for (rdataset = ISC_LIST_HEAD(name->list);
1846 rdataset = ISC_LIST_HEAD(name->list)) {
1847 ISC_LIST_UNLINK(name->list, rdataset, link);
1848 dns_rdataset_disassociate(rdataset);
1849 dns_message_puttemprdataset(updatemsg, &rdataset);
1851 dns_message_puttempname(updatemsg, &name);
1854 if (zonename != NULL) {
1855 result = dns_message_gettempname(updatemsg, &name);
1856 check_result(result, "dns_message_gettempname");
1857 dns_name_init(name, NULL);
1858 dns_name_clone(zonename, name);
1859 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1860 check_result(result, "dns_message_gettemprdataset");
1861 dns_rdataset_makequestion(rdataset, getzoneclass(),
1863 ISC_LIST_INIT(name->list);
1864 ISC_LIST_APPEND(name->list, rdataset, link);
1865 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1870 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1871 isc_result_t result;
1872 isc_buffer_t *buf = NULL;
1875 ddebug("show_message()");
1881 if (bufsz > MAXTEXT) {
1882 fprintf(stderr, "could not allocate large enough "
1883 "buffer to display message\n");
1887 isc_buffer_free(&buf);
1888 result = isc_buffer_allocate(mctx, &buf, bufsz);
1889 check_result(result, "isc_buffer_allocate");
1890 result = dns_message_totext(msg, style, 0, buf);
1892 } while (result == ISC_R_NOSPACE);
1893 if (result != ISC_R_SUCCESS) {
1894 fprintf(stderr, "could not convert message to text format.\n");
1895 isc_buffer_free(&buf);
1898 fprintf(stream, "%s\n%.*s", description,
1899 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1900 isc_buffer_free(&buf);
1904 do_next_command(char *cmdline) {
1907 ddebug("do_next_command()");
1908 word = nsu_strsep(&cmdline, " \t\r\n");
1910 if (word == NULL || *word == 0)
1911 return (STATUS_SEND);
1913 return (STATUS_MORE);
1914 if (strcasecmp(word, "quit") == 0)
1915 return (STATUS_QUIT);
1916 if (strcasecmp(word, "prereq") == 0)
1917 return (evaluate_prereq(cmdline));
1918 if (strcasecmp(word, "nxdomain") == 0)
1919 return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE));
1920 if (strcasecmp(word, "yxdomain") == 0)
1921 return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE));
1922 if (strcasecmp(word, "nxrrset") == 0)
1923 return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE));
1924 if (strcasecmp(word, "yxrrset") == 0)
1925 return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE));
1926 if (strcasecmp(word, "update") == 0)
1927 return (evaluate_update(cmdline));
1928 if (strcasecmp(word, "delete") == 0)
1929 return (update_addordelete(cmdline, ISC_TRUE));
1930 if (strcasecmp(word, "del") == 0)
1931 return (update_addordelete(cmdline, ISC_TRUE));
1932 if (strcasecmp(word, "add") == 0)
1933 return (update_addordelete(cmdline, ISC_FALSE));
1934 if (strcasecmp(word, "server") == 0)
1935 return (evaluate_server(cmdline));
1936 if (strcasecmp(word, "local") == 0)
1937 return (evaluate_local(cmdline));
1938 if (strcasecmp(word, "zone") == 0)
1939 return (evaluate_zone(cmdline));
1940 if (strcasecmp(word, "class") == 0)
1941 return (evaluate_class(cmdline));
1942 if (strcasecmp(word, "send") == 0)
1943 return (STATUS_SEND);
1944 if (strcasecmp(word, "debug") == 0) {
1946 ddebugging = ISC_TRUE;
1948 debugging = ISC_TRUE;
1949 return (STATUS_MORE);
1951 if (strcasecmp(word, "ttl") == 0)
1952 return (evaluate_ttl(cmdline));
1953 if (strcasecmp(word, "show") == 0) {
1954 show_message(stdout, updatemsg, "Outgoing update query:");
1955 return (STATUS_MORE);
1957 if (strcasecmp(word, "answer") == 0) {
1959 show_message(stdout, answer, "Answer:");
1960 return (STATUS_MORE);
1962 if (strcasecmp(word, "key") == 0) {
1963 usegsstsig = ISC_FALSE;
1964 return (evaluate_key(cmdline));
1966 if (strcasecmp(word, "realm") == 0)
1967 return (evaluate_realm(cmdline));
1968 if (strcasecmp(word, "gsstsig") == 0) {
1970 usegsstsig = ISC_TRUE;
1971 use_win2k_gsstsig = ISC_FALSE;
1973 fprintf(stderr, "gsstsig not supported\n");
1975 return (STATUS_MORE);
1977 if (strcasecmp(word, "oldgsstsig") == 0) {
1979 usegsstsig = ISC_TRUE;
1980 use_win2k_gsstsig = ISC_TRUE;
1982 fprintf(stderr, "gsstsig not supported\n");
1984 return (STATUS_MORE);
1986 if (strcasecmp(word, "help") == 0) {
1988 "local address [port] (set local resolver)\n"
1989 "server address [port] (set master server for zone)\n"
1990 "send (send the update request)\n"
1991 "show (show the update request)\n"
1992 "answer (show the answer to the last request)\n"
1993 "quit (quit, any pending update is not sent\n"
1994 "help (display this message_\n"
1995 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1996 "gsstsig (use GSS_TSIG to sign the request)\n"
1997 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1998 "zone name (set the zone to be updated)\n"
1999 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
2000 "[prereq] nxdomain name (does this name not exist)\n"
2001 "[prereq] yxdomain name (does this name exist)\n"
2002 "[prereq] nxrrset .... (does this RRset exist)\n"
2003 "[prereq] yxrrset .... (does this RRset not exist)\n"
2004 "[update] add .... (add the given record to the zone)\n"
2005 "[update] del[ete] .... (remove the given record(s) from the zone)\n");
2006 return (STATUS_MORE);
2008 fprintf(stderr, "incorrect section name: %s\n", word);
2009 return (STATUS_SYNTAX);
2013 get_next_command(void) {
2014 isc_uint16_t result = STATUS_QUIT;
2015 char cmdlinebuf[MAXCMD];
2020 #ifdef HAVE_READLINE
2021 cmdline = readline("> ");
2022 if (cmdline != NULL)
2023 add_history(cmdline);
2025 fprintf(stdout, "> ");
2027 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2030 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2033 if (cmdline != NULL) {
2034 char *tmp = cmdline;
2037 * Normalize input by removing any eol as readline()
2038 * removes eol but fgets doesn't.
2040 (void)nsu_strsep(&tmp, "\r\n");
2041 result = do_next_command(cmdline);
2043 #ifdef HAVE_READLINE
2050 static isc_boolean_t
2051 user_interaction(void) {
2052 isc_uint16_t result = STATUS_MORE;
2054 ddebug("user_interaction()");
2055 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
2056 result = get_next_command();
2057 if (!interactive && result == STATUS_SYNTAX)
2058 fatal("syntax error");
2060 if (result == STATUS_SEND)
2068 isc_event_t *event = global_event;
2069 ddebug("done_update()");
2070 isc_task_send(global_task, &event);
2074 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2075 isc_result_t result;
2076 dns_rdata_t rdata = DNS_RDATA_INIT;
2077 dns_rdata_any_tsig_t tsig;
2079 result = dns_rdataset_first(rdataset);
2080 check_result(result, "dns_rdataset_first");
2081 dns_rdataset_current(rdataset, &rdata);
2082 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2083 check_result(result, "dns_rdata_tostruct");
2084 if (tsig.error != 0) {
2085 if (isc_buffer_remaininglength(b) < 1)
2086 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2087 isc__buffer_putstr(b, "(" /*)*/);
2088 result = dns_tsigrcode_totext(tsig.error, b);
2089 check_result(result, "dns_tsigrcode_totext");
2090 if (isc_buffer_remaininglength(b) < 1)
2091 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2092 isc__buffer_putstr(b, /*(*/ ")");
2097 update_completed(isc_task_t *task, isc_event_t *event) {
2098 dns_requestevent_t *reqev = NULL;
2099 isc_result_t result;
2100 dns_request_t *request;
2104 ddebug("update_completed()");
2108 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2109 reqev = (dns_requestevent_t *)event;
2110 request = reqev->request;
2113 dns_request_destroy(&request);
2114 isc_event_free(&event);
2119 if (reqev->result != ISC_R_SUCCESS) {
2120 fprintf(stderr, "; Communication with server failed: %s\n",
2121 isc_result_totext(reqev->result));
2122 seenerror = ISC_TRUE;
2126 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
2127 check_result(result, "dns_message_create");
2128 result = dns_request_getresponse(request, answer,
2129 DNS_MESSAGEPARSE_PRESERVEORDER);
2132 if (answer->verify_attempted)
2133 ddebug("tsig verification successful");
2135 case DNS_R_CLOCKSKEW:
2136 case DNS_R_EXPECTEDTSIG:
2137 case DNS_R_TSIGERRORSET:
2138 case DNS_R_TSIGVERIFYFAILURE:
2139 case DNS_R_UNEXPECTEDTSIG:
2142 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2144 * For MS DNS that violates RFC 2845, section 4.2
2149 fprintf(stderr, "; TSIG error with server: %s\n",
2150 isc_result_totext(result));
2151 seenerror = ISC_TRUE;
2154 check_result(result, "dns_request_getresponse");
2157 if (answer->rcode != dns_rcode_noerror) {
2158 seenerror = ISC_TRUE;
2162 dns_rdataset_t *rds;
2164 isc_buffer_init(&b, buf, sizeof(buf) - 1);
2165 result = dns_rcode_totext(answer->rcode, &b);
2166 check_result(result, "dns_rcode_totext");
2167 rds = dns_message_gettsig(answer, NULL);
2169 check_tsig_error(rds, &b);
2170 fprintf(stderr, "update failed: %.*s\n",
2171 (int)isc_buffer_usedlength(&b), buf);
2175 show_message(stderr, answer, "\nReply from update query:");
2178 dns_request_destroy(&request);
2180 dns_name_free(&tmpzonename, mctx);
2181 dns_name_free(&restart_master, mctx);
2183 isc_event_free(&event);
2188 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2189 isc_sockaddr_t *srcaddr)
2191 isc_result_t result;
2192 dns_request_t *request = NULL;
2193 unsigned int options = DNS_REQUESTOPT_CASE;
2195 ddebug("send_update()");
2200 options |= DNS_REQUESTOPT_TCP;
2201 if (tsigkey == NULL && sig0key != NULL) {
2202 result = dns_message_setsig0key(updatemsg, sig0key);
2203 check_result(result, "dns_message_setsig0key");
2206 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2208 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2209 fprintf(stderr, "Sending update to %s\n", addrbuf);
2212 /* Windows doesn't like the tsig name to be compressed. */
2213 if (updatemsg->tsigname)
2214 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2216 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2217 master, options, tsigkey, timeout,
2218 udp_timeout, udp_retries, global_task,
2219 update_completed, NULL, &request);
2220 check_result(result, "dns_request_createvia3");
2223 show_message(stdout, updatemsg, "Outgoing update query:");
2229 recvsoa(isc_task_t *task, isc_event_t *event) {
2230 dns_requestevent_t *reqev = NULL;
2231 dns_request_t *request = NULL;
2232 isc_result_t result, eresult;
2233 dns_message_t *rcvmsg = NULL;
2234 dns_section_t section;
2235 dns_name_t *name = NULL;
2236 dns_rdataset_t *soaset = NULL;
2237 dns_rdata_soa_t soa;
2238 dns_rdata_t soarr = DNS_RDATA_INIT;
2241 nsu_requestinfo_t *reqinfo;
2242 dns_message_t *soaquery = NULL;
2243 isc_sockaddr_t *addr;
2244 isc_boolean_t seencname = ISC_FALSE;
2246 unsigned int nlabels;
2250 ddebug("recvsoa()");
2254 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2255 reqev = (dns_requestevent_t *)event;
2256 request = reqev->request;
2257 eresult = reqev->result;
2258 reqinfo = reqev->ev_arg;
2259 soaquery = reqinfo->msg;
2260 addr = reqinfo->addr;
2263 dns_request_destroy(&request);
2264 dns_message_destroy(&soaquery);
2265 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2266 isc_event_free(&event);
2271 if (eresult != ISC_R_SUCCESS) {
2272 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2274 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2275 fprintf(stderr, "; Communication with %s failed: %s\n",
2276 addrbuf, isc_result_totext(eresult));
2277 if (userserver != NULL)
2278 fatal("could not talk to specified name server");
2279 else if (++ns_inuse >= lwconf->nsnext)
2280 fatal("could not talk to any default name server");
2281 ddebug("Destroying request [%p]", request);
2282 dns_request_destroy(&request);
2283 dns_message_renderreset(soaquery);
2284 dns_message_settsigkey(soaquery, NULL);
2285 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2286 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2287 isc_event_free(&event);
2288 setzoneclass(dns_rdataclass_none);
2292 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2294 isc_event_free(&event);
2297 ddebug("About to create rcvmsg");
2298 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2299 check_result(result, "dns_message_create");
2300 result = dns_request_getresponse(request, rcvmsg,
2301 DNS_MESSAGEPARSE_PRESERVEORDER);
2302 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2303 dns_message_destroy(&rcvmsg);
2304 ddebug("Destroying request [%p]", request);
2305 dns_request_destroy(&request);
2306 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2307 if (reqinfo == NULL)
2308 fatal("out of memory");
2309 reqinfo->msg = soaquery;
2310 reqinfo->addr = addr;
2311 dns_message_renderreset(soaquery);
2312 ddebug("retrying soa request without TSIG");
2313 result = dns_request_createvia3(requestmgr, soaquery,
2314 localaddr, addr, 0, NULL,
2317 global_task, recvsoa, reqinfo,
2319 check_result(result, "dns_request_createvia");
2323 check_result(result, "dns_request_getresponse");
2324 section = DNS_SECTION_ANSWER;
2327 show_message(stderr, rcvmsg, "Reply from SOA query:");
2329 if (rcvmsg->rcode != dns_rcode_noerror &&
2330 rcvmsg->rcode != dns_rcode_nxdomain)
2331 fatal("response to SOA query was unsuccessful");
2333 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2334 char namebuf[DNS_NAME_FORMATSIZE];
2335 dns_name_format(userzone, namebuf, sizeof(namebuf));
2336 error("specified zone '%s' does not exist (NXDOMAIN)",
2338 dns_message_destroy(&rcvmsg);
2339 dns_request_destroy(&request);
2340 dns_message_destroy(&soaquery);
2341 ddebug("Out of recvsoa");
2343 seenerror = ISC_TRUE;
2349 section = DNS_SECTION_ANSWER;
2351 section = DNS_SECTION_AUTHORITY;
2355 result = dns_message_firstname(rcvmsg, section);
2356 if (result != ISC_R_SUCCESS) {
2360 while (result == ISC_R_SUCCESS) {
2362 dns_message_currentname(rcvmsg, section, &name);
2364 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2366 if (result == ISC_R_SUCCESS)
2368 if (section == DNS_SECTION_ANSWER) {
2369 dns_rdataset_t *tset = NULL;
2370 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2371 &tset) == ISC_R_SUCCESS ||
2372 dns_message_findtype(name, dns_rdatatype_dname, 0,
2373 &tset) == ISC_R_SUCCESS ) {
2374 seencname = ISC_TRUE;
2379 result = dns_message_nextname(rcvmsg, section);
2382 if (soaset == NULL && !seencname) {
2391 char namestr[DNS_NAME_FORMATSIZE];
2392 dns_name_format(name, namestr, sizeof(namestr));
2393 fprintf(stderr, "Found zone name: %s\n", namestr);
2396 result = dns_rdataset_first(soaset);
2397 check_result(result, "dns_rdataset_first");
2399 dns_rdata_init(&soarr);
2400 dns_rdataset_current(soaset, &soarr);
2401 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2402 check_result(result, "dns_rdata_tostruct");
2404 dns_name_init(&master, NULL);
2405 dns_name_clone(&soa.origin, &master);
2407 if (userzone != NULL)
2408 zonename = userzone;
2413 char namestr[DNS_NAME_FORMATSIZE];
2414 dns_name_format(&master, namestr, sizeof(namestr));
2415 fprintf(stderr, "The master is: %s\n", namestr);
2418 if (userserver != NULL)
2419 serveraddr = userserver;
2421 char serverstr[DNS_NAME_MAXTEXT+1];
2424 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2425 result = dns_name_totext(&master, ISC_TRUE, &buf);
2426 check_result(result, "dns_name_totext");
2427 serverstr[isc_buffer_usedlength(&buf)] = 0;
2428 get_address(serverstr, dnsport, &tempaddr);
2429 serveraddr = &tempaddr;
2431 dns_rdata_freestruct(&soa);
2435 dns_name_init(&tmpzonename, NULL);
2436 dns_name_dup(zonename, mctx, &tmpzonename);
2437 dns_name_init(&restart_master, NULL);
2438 dns_name_dup(&master, mctx, &restart_master);
2439 start_gssrequest(&master);
2441 send_update(zonename, serveraddr, localaddr);
2442 setzoneclass(dns_rdataclass_none);
2445 send_update(zonename, serveraddr, localaddr);
2446 setzoneclass(dns_rdataclass_none);
2449 dns_message_destroy(&soaquery);
2450 dns_request_destroy(&request);
2453 dns_message_destroy(&rcvmsg);
2454 ddebug("Out of recvsoa");
2458 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2459 INSIST(result == ISC_R_SUCCESS);
2461 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2462 nlabels = dns_name_countlabels(name);
2464 fatal("could not find enclosing zone");
2465 dns_name_init(&tname, NULL);
2466 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2467 dns_name_clone(&tname, name);
2468 dns_request_destroy(&request);
2469 dns_message_renderreset(soaquery);
2470 dns_message_settsigkey(soaquery, NULL);
2471 if (userserver != NULL)
2472 sendrequest(localaddr, userserver, soaquery, &request);
2474 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2479 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2480 dns_message_t *msg, dns_request_t **request)
2482 isc_result_t result;
2483 nsu_requestinfo_t *reqinfo;
2485 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2486 if (reqinfo == NULL)
2487 fatal("out of memory");
2489 reqinfo->addr = destaddr;
2490 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2491 (userserver != NULL) ? tsigkey : NULL,
2492 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2493 global_task, recvsoa, reqinfo, request);
2494 check_result(result, "dns_request_createvia");
2501 * Get the realm from the users kerberos ticket if possible
2504 get_ticket_realm(isc_mem_t *mctx)
2509 krb5_principal princ;
2510 char *name, *ticket_realm;
2512 rc = krb5_init_context(&ctx);
2516 rc = krb5_cc_default(ctx, &ccache);
2518 krb5_free_context(ctx);
2522 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2524 krb5_cc_close(ctx, ccache);
2525 krb5_free_context(ctx);
2529 rc = krb5_unparse_name(ctx, princ, &name);
2531 krb5_free_principal(ctx, princ);
2532 krb5_cc_close(ctx, ccache);
2533 krb5_free_context(ctx);
2537 ticket_realm = strrchr(name, '@');
2538 if (ticket_realm != NULL) {
2539 realm = isc_mem_strdup(mctx, ticket_realm);
2543 krb5_free_principal(ctx, princ);
2544 krb5_cc_close(ctx, ccache);
2545 krb5_free_context(ctx);
2546 if (realm != NULL && debugging)
2547 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
2552 start_gssrequest(dns_name_t *master) {
2553 gss_ctx_id_t context;
2555 isc_result_t result;
2556 isc_uint32_t val = 0;
2557 dns_message_t *rmsg;
2558 dns_request_t *request = NULL;
2559 dns_name_t *servname;
2560 dns_fixedname_t fname;
2561 char namestr[DNS_NAME_FORMATSIZE];
2562 char keystr[DNS_NAME_FORMATSIZE];
2563 char *err_message = NULL;
2565 debug("start_gssrequest");
2568 if (gssring != NULL)
2569 dns_tsigkeyring_detach(&gssring);
2571 result = dns_tsigkeyring_create(mctx, &gssring);
2573 if (result != ISC_R_SUCCESS)
2574 fatal("dns_tsigkeyring_create failed: %s",
2575 isc_result_totext(result));
2577 dns_name_format(master, namestr, sizeof(namestr));
2578 if (kserver == NULL) {
2579 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2580 if (kserver == NULL)
2581 fatal("out of memory");
2583 if (userserver == NULL)
2584 get_address(namestr, dnsport, kserver);
2586 (void)memmove(kserver, userserver, sizeof(isc_sockaddr_t));
2588 dns_fixedname_init(&fname);
2589 servname = dns_fixedname_name(&fname);
2592 get_ticket_realm(mctx);
2594 result = isc_string_printf(servicename, sizeof(servicename),
2595 "DNS/%s%s", namestr, realm ? realm : "");
2596 if (result != ISC_R_SUCCESS)
2597 fatal("isc_string_printf(servicename) failed: %s",
2598 isc_result_totext(result));
2599 isc_buffer_init(&buf, servicename, strlen(servicename));
2600 isc_buffer_add(&buf, strlen(servicename));
2601 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2602 if (result != ISC_R_SUCCESS)
2603 fatal("dns_name_fromtext(servname) failed: %s",
2604 isc_result_totext(result));
2606 dns_fixedname_init(&fkname);
2607 keyname = dns_fixedname_name(&fkname);
2609 isc_random_get(&val);
2610 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2612 if (result != ISC_R_SUCCESS)
2613 fatal("isc_string_printf(keystr) failed: %s",
2614 isc_result_totext(result));
2615 isc_buffer_init(&buf, keystr, strlen(keystr));
2616 isc_buffer_add(&buf, strlen(keystr));
2618 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
2619 if (result != ISC_R_SUCCESS)
2620 fatal("dns_name_fromtext(keyname) failed: %s",
2621 isc_result_totext(result));
2623 /* Windows doesn't recognize name compression in the key name. */
2624 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2627 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2628 if (result != ISC_R_SUCCESS)
2629 fatal("dns_message_create failed: %s",
2630 isc_result_totext(result));
2632 /* Build first request. */
2633 context = GSS_C_NO_CONTEXT;
2634 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2635 &context, use_win2k_gsstsig,
2636 mctx, &err_message);
2637 if (result == ISC_R_FAILURE)
2638 fatal("tkey query failed: %s",
2639 err_message != NULL ? err_message : "unknown error");
2640 if (result != ISC_R_SUCCESS)
2641 fatal("dns_tkey_buildgssquery failed: %s",
2642 isc_result_totext(result));
2644 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2648 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2649 dns_message_t *msg, dns_request_t **request,
2650 gss_ctx_id_t context)
2652 isc_result_t result;
2653 nsu_gssinfo_t *reqinfo;
2654 unsigned int options = 0;
2656 debug("send_gssrequest");
2657 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2658 if (reqinfo == NULL)
2659 fatal("out of memory");
2661 reqinfo->addr = destaddr;
2662 reqinfo->context = context;
2664 options |= DNS_REQUESTOPT_TCP;
2665 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2666 options, tsigkey, FIND_TIMEOUT * 20,
2667 FIND_TIMEOUT, 3, global_task, recvgss,
2669 check_result(result, "dns_request_createvia3");
2671 show_message(stdout, msg, "Outgoing update query:");
2676 recvgss(isc_task_t *task, isc_event_t *event) {
2677 dns_requestevent_t *reqev = NULL;
2678 dns_request_t *request = NULL;
2679 isc_result_t result, eresult;
2680 dns_message_t *rcvmsg = NULL;
2681 nsu_gssinfo_t *reqinfo;
2682 dns_message_t *tsigquery = NULL;
2683 isc_sockaddr_t *addr;
2684 gss_ctx_id_t context;
2686 dns_name_t *servname;
2687 dns_fixedname_t fname;
2688 char *err_message = NULL;
2692 ddebug("recvgss()");
2696 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2697 reqev = (dns_requestevent_t *)event;
2698 request = reqev->request;
2699 eresult = reqev->result;
2700 reqinfo = reqev->ev_arg;
2701 tsigquery = reqinfo->msg;
2702 context = reqinfo->context;
2703 addr = reqinfo->addr;
2706 dns_request_destroy(&request);
2707 dns_message_destroy(&tsigquery);
2708 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2709 isc_event_free(&event);
2714 if (eresult != ISC_R_SUCCESS) {
2715 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2717 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2718 fprintf(stderr, "; Communication with %s failed: %s\n",
2719 addrbuf, isc_result_totext(eresult));
2720 if (userserver != NULL)
2721 fatal("could not talk to specified name server");
2722 else if (++ns_inuse >= lwconf->nsnext)
2723 fatal("could not talk to any default name server");
2724 ddebug("Destroying request [%p]", request);
2725 dns_request_destroy(&request);
2726 dns_message_renderreset(tsigquery);
2727 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2729 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2730 isc_event_free(&event);
2733 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2735 isc_event_free(&event);
2738 ddebug("recvgss creating rcvmsg");
2739 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2740 check_result(result, "dns_message_create");
2742 result = dns_request_getresponse(request, rcvmsg,
2743 DNS_MESSAGEPARSE_PRESERVEORDER);
2744 check_result(result, "dns_request_getresponse");
2747 show_message(stderr, rcvmsg,
2748 "recvmsg reply from GSS-TSIG query");
2750 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2751 ddebug("recvgss trying %s GSS-TSIG",
2752 use_win2k_gsstsig ? "Standard" : "Win2k");
2753 if (use_win2k_gsstsig)
2754 use_win2k_gsstsig = ISC_FALSE;
2756 use_win2k_gsstsig = ISC_TRUE;
2757 tried_other_gsstsig = ISC_TRUE;
2758 start_gssrequest(&restart_master);
2762 if (rcvmsg->rcode != dns_rcode_noerror &&
2763 rcvmsg->rcode != dns_rcode_nxdomain)
2764 fatal("response to GSS-TSIG query was unsuccessful");
2767 dns_fixedname_init(&fname);
2768 servname = dns_fixedname_name(&fname);
2769 isc_buffer_init(&buf, servicename, strlen(servicename));
2770 isc_buffer_add(&buf, strlen(servicename));
2771 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2772 check_result(result, "dns_name_fromtext");
2775 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2776 &context, &tsigkey, gssring,
2781 case DNS_R_CONTINUE:
2782 send_gssrequest(localaddr, kserver, tsigquery, &request,
2788 * XXXSRA Waaay too much fun here. There's no good
2789 * reason why we need a TSIG here (the people who put
2790 * it into the spec admitted at the time that it was
2791 * not a security issue), and Windows clients don't
2792 * seem to work if named complies with the spec and
2793 * includes the gratuitous TSIG. So we're in the
2794 * bizarre situation of having to choose between
2795 * complying with a useless requirement in the spec
2796 * and interoperating. This is nuts. If we can
2797 * confirm this behavior, we should ask the WG to
2798 * consider removing the requirement for the
2799 * gratuitous TSIG here. For the moment, we ignore
2800 * the TSIG -- this too is a spec violation, but it's
2801 * the least insane thing to do.
2805 * Verify the signature.
2807 rcvmsg->state = DNS_SECTION_ANY;
2808 dns_message_setquerytsig(rcvmsg, NULL);
2809 result = dns_message_settsigkey(rcvmsg, tsigkey);
2810 check_result(result, "dns_message_settsigkey");
2811 result = dns_message_checksig(rcvmsg, NULL);
2812 ddebug("tsig verification: %s", dns_result_totext(result));
2813 check_result(result, "dns_message_checksig");
2816 send_update(&tmpzonename, serveraddr, localaddr);
2817 setzoneclass(dns_rdataclass_none);
2821 fatal("dns_tkey_negotiategss: %s %s",
2822 isc_result_totext(result),
2823 err_message != NULL ? err_message : "");
2827 dns_request_destroy(&request);
2828 dns_message_destroy(&tsigquery);
2830 dns_message_destroy(&rcvmsg);
2831 ddebug("Out of recvgss");
2836 start_update(void) {
2837 isc_result_t result;
2838 dns_rdataset_t *rdataset = NULL;
2839 dns_name_t *name = NULL;
2840 dns_request_t *request = NULL;
2841 dns_message_t *soaquery = NULL;
2842 dns_name_t *firstname;
2843 dns_section_t section = DNS_SECTION_UPDATE;
2845 ddebug("start_update()");
2848 dns_message_destroy(&answer);
2850 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2851 send_update(userzone, userserver, localaddr);
2852 setzoneclass(dns_rdataclass_none);
2856 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2858 check_result(result, "dns_message_create");
2860 if (userserver == NULL)
2861 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2863 result = dns_message_gettempname(soaquery, &name);
2864 check_result(result, "dns_message_gettempname");
2866 result = dns_message_gettemprdataset(soaquery, &rdataset);
2867 check_result(result, "dns_message_gettemprdataset");
2869 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2871 if (userzone != NULL) {
2872 dns_name_init(name, NULL);
2873 dns_name_clone(userzone, name);
2875 dns_rdataset_t *tmprdataset;
2876 result = dns_message_firstname(updatemsg, section);
2877 if (result == ISC_R_NOMORE) {
2878 section = DNS_SECTION_PREREQUISITE;
2879 result = dns_message_firstname(updatemsg, section);
2881 if (result != ISC_R_SUCCESS) {
2882 dns_message_puttempname(soaquery, &name);
2883 dns_rdataset_disassociate(rdataset);
2884 dns_message_puttemprdataset(soaquery, &rdataset);
2885 dns_message_destroy(&soaquery);
2890 dns_message_currentname(updatemsg, section, &firstname);
2891 dns_name_init(name, NULL);
2892 dns_name_clone(firstname, name);
2894 * Looks to see if the first name references a DS record
2895 * and if that name is not the root remove a label as DS
2896 * records live in the parent zone so we need to start our
2897 * search one label up.
2899 tmprdataset = ISC_LIST_HEAD(firstname->list);
2900 if (section == DNS_SECTION_UPDATE &&
2901 !dns_name_equal(firstname, dns_rootname) &&
2902 tmprdataset->type == dns_rdatatype_ds) {
2903 unsigned int labels = dns_name_countlabels(name);
2904 dns_name_getlabelsequence(name, 1, labels - 1, name);
2908 ISC_LIST_INIT(name->list);
2909 ISC_LIST_APPEND(name->list, rdataset, link);
2910 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2912 if (userserver != NULL)
2913 sendrequest(localaddr, userserver, soaquery, &request);
2916 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2922 ddebug("cleanup()");
2925 dns_message_destroy(&answer);
2928 if (tsigkey != NULL) {
2929 ddebug("detach tsigkey x%p", tsigkey);
2930 dns_tsigkey_detach(&tsigkey);
2932 if (gssring != NULL) {
2933 ddebug("Detaching GSS-TSIG keyring");
2934 dns_tsigkeyring_detach(&gssring);
2936 if (kserver != NULL) {
2937 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2940 if (realm != NULL) {
2941 isc_mem_free(mctx, realm);
2946 if (sig0key != NULL)
2947 dst_key_free(&sig0key);
2949 ddebug("Shutting down task manager");
2950 isc_taskmgr_destroy(&taskmgr);
2952 ddebug("Destroying event");
2953 isc_event_free(&global_event);
2955 ddebug("Shutting down socket manager");
2956 isc_socketmgr_destroy(&socketmgr);
2958 ddebug("Shutting down timer manager");
2959 isc_timermgr_destroy(&timermgr);
2961 ddebug("Destroying hash context");
2964 ddebug("Destroying name state");
2967 ddebug("Removing log context");
2968 isc_log_destroy(&lctx);
2970 ddebug("Destroying memory context");
2972 isc_mem_stats(mctx, stderr);
2973 isc_mem_destroy(&mctx);
2977 getinput(isc_task_t *task, isc_event_t *event) {
2987 if (global_event == NULL)
2988 global_event = event;
2991 more = user_interaction();
3001 main(int argc, char **argv) {
3002 isc_result_t result;
3003 style = &dns_master_style_debug;
3007 interactive = ISC_TF(isatty(0));
3011 pre_parse_args(argc, argv);
3013 result = isc_mem_create(0, 0, &mctx);
3014 check_result(result, "isc_mem_create");
3016 parse_args(argc, argv, mctx, &entropy);
3020 result = isc_app_onrun(mctx, global_task, getinput, NULL);
3021 check_result(result, "isc_app_onrun");
3023 (void)isc_app_run();