2 * Copyright (C) 2004-2012 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>
40 #include <isc/parseint.h>
41 #include <isc/print.h>
42 #include <isc/random.h>
43 #include <isc/region.h>
44 #include <isc/sockaddr.h>
45 #include <isc/socket.h>
46 #include <isc/stdio.h>
47 #include <isc/string.h>
49 #include <isc/timer.h>
50 #include <isc/types.h>
53 #include <dns/callbacks.h>
54 #include <dns/dispatch.h>
55 #include <dns/dnssec.h>
56 #include <dns/events.h>
57 #include <dns/fixedname.h>
59 #include <dns/masterdump.h>
60 #include <dns/message.h>
62 #include <dns/rcode.h>
63 #include <dns/rdata.h>
64 #include <dns/rdataclass.h>
65 #include <dns/rdatalist.h>
66 #include <dns/rdataset.h>
67 #include <dns/rdatastruct.h>
68 #include <dns/rdatatype.h>
69 #include <dns/request.h>
70 #include <dns/result.h>
76 #include <lwres/lwres.h>
77 #include <lwres/net.h>
80 #include <dst/gssapi.h>
82 #include <bind9/getaddresses.h>
86 #ifdef HAVE_GETADDRINFO
87 #ifdef HAVE_GAISTRERROR
88 #define USE_GETADDRINFO
93 #ifndef USE_GETADDRINFO
94 #ifndef ISC_PLATFORM_NONSTDHERRNO
99 #define MAXCMD (4 * 1024)
100 #define MAXWIRE (64 * 1024)
101 #define PACKETSIZE ((64 * 1024) - 1)
102 #define INITTEXT (2 * 1024)
103 #define MAXTEXT (128 * 1024)
104 #define FIND_TIMEOUT 5
105 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
107 #define DNSDEFAULTPORT 53
110 #define RESOLV_CONF "/etc/resolv.conf"
113 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
114 static isc_boolean_t memdebugging = ISC_FALSE;
115 static isc_boolean_t have_ipv4 = ISC_FALSE;
116 static isc_boolean_t have_ipv6 = ISC_FALSE;
117 static isc_boolean_t is_dst_up = ISC_FALSE;
118 static isc_boolean_t usevc = ISC_FALSE;
119 static isc_boolean_t usegsstsig = ISC_FALSE;
120 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
121 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
122 static isc_taskmgr_t *taskmgr = NULL;
123 static isc_task_t *global_task = NULL;
124 static isc_event_t *global_event = NULL;
125 static isc_log_t *lctx = NULL;
126 static isc_mem_t *mctx = NULL;
127 static dns_dispatchmgr_t *dispatchmgr = NULL;
128 static dns_requestmgr_t *requestmgr = NULL;
129 static isc_socketmgr_t *socketmgr = NULL;
130 static isc_timermgr_t *timermgr = NULL;
131 static dns_dispatch_t *dispatchv4 = NULL;
132 static dns_dispatch_t *dispatchv6 = NULL;
133 static dns_message_t *updatemsg = NULL;
134 static dns_fixedname_t fuserzone;
135 static dns_name_t *userzone = NULL;
136 static dns_name_t *zonename = NULL;
137 static dns_name_t tmpzonename;
138 static dns_name_t restart_master;
139 static dns_tsig_keyring_t *gssring = NULL;
140 static dns_tsigkey_t *tsigkey = NULL;
141 static dst_key_t *sig0key;
142 static lwres_context_t *lwctx = NULL;
143 static lwres_conf_t *lwconf;
144 static isc_sockaddr_t *servers;
145 static int ns_inuse = 0;
146 static int ns_total = 0;
147 static isc_sockaddr_t *userserver = NULL;
148 static isc_sockaddr_t *localaddr = NULL;
149 static isc_sockaddr_t *serveraddr = NULL;
150 static isc_sockaddr_t tempaddr;
151 static char *keystr = NULL, *keyfile = NULL;
152 static isc_entropy_t *entropy = NULL;
153 static isc_boolean_t shuttingdown = ISC_FALSE;
155 static isc_boolean_t interactive = ISC_TRUE;
156 static isc_boolean_t seenerror = ISC_FALSE;
157 static const dns_master_style_t *style;
158 static int requests = 0;
159 static unsigned int logdebuglevel = 0;
160 static unsigned int timeout = 300;
161 static unsigned int udp_timeout = 3;
162 static unsigned int udp_retries = 3;
163 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
164 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
165 static dns_message_t *answer = NULL;
166 static isc_uint32_t default_ttl = 0;
167 static isc_boolean_t default_ttl_set = ISC_FALSE;
169 typedef struct nsu_requestinfo {
171 isc_sockaddr_t *addr;
175 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
176 dns_message_t *msg, dns_request_t **request);
177 ISC_PLATFORM_NORETURN_PRE static void
178 fatal(const char *format, ...)
179 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
182 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
185 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
188 static dns_fixedname_t fkname;
189 static isc_sockaddr_t *kserver = NULL;
190 static char *realm = NULL;
191 static char servicename[DNS_NAME_FORMATSIZE];
192 static dns_name_t *keyname;
193 typedef struct nsu_gssinfo {
195 isc_sockaddr_t *addr;
196 gss_ctx_id_t context;
200 start_gssrequest(dns_name_t *master);
202 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
203 dns_message_t *msg, dns_request_t **request,
204 gss_ctx_id_t context);
206 recvgss(isc_task_t *task, isc_event_t *event);
210 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
212 #define STATUS_MORE (isc_uint16_t)0
213 #define STATUS_SEND (isc_uint16_t)1
214 #define STATUS_QUIT (isc_uint16_t)2
215 #define STATUS_SYNTAX (isc_uint16_t)3
217 typedef struct entropysource entropysource_t;
219 struct entropysource {
220 isc_entropysource_t *source;
222 ISC_LINK(entropysource_t) link;
225 static ISC_LIST(entropysource_t) sources;
228 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
231 isc_entropysource_t *source = NULL;
232 entropysource_t *elt;
233 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
235 REQUIRE(ectx != NULL);
238 result = isc_entropy_create(mctx, ectx);
239 if (result != ISC_R_SUCCESS)
240 fatal("could not create entropy object");
241 ISC_LIST_INIT(sources);
244 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
245 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
249 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
252 if (result != ISC_R_SUCCESS)
253 fatal("could not initialize entropy source: %s",
254 isc_result_totext(result));
256 if (source != NULL) {
257 elt = isc_mem_get(mctx, sizeof(*elt));
259 fatal("out of memory");
260 elt->source = source;
262 ISC_LINK_INIT(elt, link);
263 ISC_LIST_APPEND(sources, elt, link);
268 cleanup_entropy(isc_entropy_t **ectx) {
269 entropysource_t *source;
270 while (!ISC_LIST_EMPTY(sources)) {
271 source = ISC_LIST_HEAD(sources);
272 ISC_LIST_UNLINK(sources, source, link);
273 isc_entropy_destroysource(&source->source);
274 isc_mem_put(source->mctx, source, sizeof(*source));
276 isc_entropy_detach(ectx);
280 static dns_rdataclass_t
282 if (zoneclass == dns_rdataclass_none)
283 zoneclass = defaultclass;
288 setzoneclass(dns_rdataclass_t rdclass) {
289 if (zoneclass == dns_rdataclass_none ||
290 rdclass == dns_rdataclass_none)
292 if (zoneclass != rdclass)
298 fatal(const char *format, ...) {
301 va_start(args, format);
302 vfprintf(stderr, format, args);
304 fprintf(stderr, "\n");
309 error(const char *format, ...) {
312 va_start(args, format);
313 vfprintf(stderr, format, args);
315 fprintf(stderr, "\n");
319 debug(const char *format, ...) {
323 va_start(args, format);
324 vfprintf(stderr, format, args);
326 fprintf(stderr, "\n");
331 ddebug(const char *format, ...) {
335 va_start(args, format);
336 vfprintf(stderr, format, args);
338 fprintf(stderr, "\n");
343 check_result(isc_result_t result, const char *msg) {
344 if (result != ISC_R_SUCCESS)
345 fatal("%s: %s", msg, isc_result_totext(result));
349 mem_alloc(void *arg, size_t size) {
350 return (isc_mem_get(arg, size));
354 mem_free(void *arg, void *mem, size_t size) {
355 isc_mem_put(arg, mem, size);
359 nsu_strsep(char **stringp, const char *delim) {
360 char *string = *stringp;
368 for (; *string != '\0'; string++) {
370 for (d = delim; (dc = *d) != '\0'; d++) {
378 for (s = string; *s != '\0'; s++) {
380 for (d = delim; (dc = *d) != '\0'; d++) {
396 ddebug("reset_system()");
397 /* If the update message is still around, destroy it */
398 if (updatemsg != NULL)
399 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
401 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
403 check_result(result, "dns_message_create");
405 updatemsg->opcode = dns_opcode_update;
408 dns_tsigkey_detach(&tsigkey);
410 dns_tsigkeyring_destroy(&gssring);
411 tried_other_gsstsig = ISC_FALSE;
416 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
417 isc_uint16_t digestbits = 0;
421 REQUIRE(hmac != NULL && *hmac == NULL);
422 REQUIRE(hmacstr != NULL);
424 if (len >= sizeof(buf))
425 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
427 strncpy(buf, hmacstr, len);
430 if (strcasecmp(buf, "hmac-md5") == 0) {
431 *hmac = DNS_TSIG_HMACMD5_NAME;
432 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
433 *hmac = DNS_TSIG_HMACMD5_NAME;
434 result = isc_parse_uint16(&digestbits, &buf[9], 10);
435 if (result != ISC_R_SUCCESS || digestbits > 128)
436 fatal("digest-bits out of range [0..128]");
437 digestbits = (digestbits +7) & ~0x7U;
438 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
439 *hmac = DNS_TSIG_HMACSHA1_NAME;
440 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
441 *hmac = DNS_TSIG_HMACSHA1_NAME;
442 result = isc_parse_uint16(&digestbits, &buf[10], 10);
443 if (result != ISC_R_SUCCESS || digestbits > 160)
444 fatal("digest-bits out of range [0..160]");
445 digestbits = (digestbits +7) & ~0x7U;
446 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
447 *hmac = DNS_TSIG_HMACSHA224_NAME;
448 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
449 *hmac = DNS_TSIG_HMACSHA224_NAME;
450 result = isc_parse_uint16(&digestbits, &buf[12], 10);
451 if (result != ISC_R_SUCCESS || digestbits > 224)
452 fatal("digest-bits out of range [0..224]");
453 digestbits = (digestbits +7) & ~0x7U;
454 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
455 *hmac = DNS_TSIG_HMACSHA256_NAME;
456 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
457 *hmac = DNS_TSIG_HMACSHA256_NAME;
458 result = isc_parse_uint16(&digestbits, &buf[12], 10);
459 if (result != ISC_R_SUCCESS || digestbits > 256)
460 fatal("digest-bits out of range [0..256]");
461 digestbits = (digestbits +7) & ~0x7U;
462 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
463 *hmac = DNS_TSIG_HMACSHA384_NAME;
464 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
465 *hmac = DNS_TSIG_HMACSHA384_NAME;
466 result = isc_parse_uint16(&digestbits, &buf[12], 10);
467 if (result != ISC_R_SUCCESS || digestbits > 384)
468 fatal("digest-bits out of range [0..384]");
469 digestbits = (digestbits +7) & ~0x7U;
470 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
471 *hmac = DNS_TSIG_HMACSHA512_NAME;
472 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
473 *hmac = DNS_TSIG_HMACSHA512_NAME;
474 result = isc_parse_uint16(&digestbits, &buf[12], 10);
475 if (result != ISC_R_SUCCESS || digestbits > 512)
476 fatal("digest-bits out of range [0..512]");
477 digestbits = (digestbits +7) & ~0x7U;
479 fatal("unknown key type '%s'", buf);
485 unsigned char *secret = NULL;
487 isc_buffer_t secretbuf;
489 isc_buffer_t keynamesrc;
492 dns_fixedname_t fkeyname;
495 dns_name_t *hmacname = NULL;
496 isc_uint16_t digestbits = 0;
498 dns_fixedname_init(&fkeyname);
499 keyname = dns_fixedname_name(&fkeyname);
501 debug("Creating key...");
503 s = strchr(keystr, ':');
504 if (s == NULL || s == keystr || s[1] == 0)
505 fatal("key option must specify [hmac:]keyname:secret");
507 n = strchr(secretstr, ':');
509 if (n == secretstr || n[1] == 0)
510 fatal("key option must specify [hmac:]keyname:secret");
513 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
515 hmacname = DNS_TSIG_HMACMD5_NAME;
520 isc_buffer_init(&keynamesrc, name, n - name);
521 isc_buffer_add(&keynamesrc, n - name);
523 debug("namefromtext");
524 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname,
526 check_result(result, "dns_name_fromtext");
528 secretlen = strlen(secretstr) * 3 / 4;
529 secret = isc_mem_allocate(mctx, secretlen);
531 fatal("out of memory");
533 isc_buffer_init(&secretbuf, secret, secretlen);
534 result = isc_base64_decodestring(secretstr, &secretbuf);
535 if (result != ISC_R_SUCCESS) {
536 fprintf(stderr, "could not create key from %s: %s\n",
537 keystr, isc_result_totext(result));
541 secretlen = isc_buffer_usedlength(&secretbuf);
544 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
545 ISC_FALSE, NULL, 0, 0, mctx, NULL,
547 if (result != ISC_R_SUCCESS)
548 fprintf(stderr, "could not create key from %s: %s\n",
549 keystr, dns_result_totext(result));
551 dst_key_setbits(tsigkey->key, digestbits);
554 isc_mem_free(mctx, secret);
558 basenamelen(const char *file) {
559 int len = strlen(file);
561 if (len > 1 && file[len - 1] == '.')
563 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
565 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
571 setup_keyfile(void) {
572 dst_key_t *dstkey = NULL;
574 dns_name_t *hmacname = NULL;
576 debug("Creating key...");
579 dst_key_free(&sig0key);
581 result = dst_key_fromnamedfile(keyfile,
582 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
584 if (result != ISC_R_SUCCESS) {
585 fprintf(stderr, "could not read key from %.*s.{private,key}: "
586 "%s\n", basenamelen(keyfile), keyfile,
587 isc_result_totext(result));
590 switch (dst_key_alg(dstkey)) {
591 case DST_ALG_HMACMD5:
592 hmacname = DNS_TSIG_HMACMD5_NAME;
594 case DST_ALG_HMACSHA1:
595 hmacname = DNS_TSIG_HMACSHA1_NAME;
597 case DST_ALG_HMACSHA224:
598 hmacname = DNS_TSIG_HMACSHA224_NAME;
600 case DST_ALG_HMACSHA256:
601 hmacname = DNS_TSIG_HMACSHA256_NAME;
603 case DST_ALG_HMACSHA384:
604 hmacname = DNS_TSIG_HMACSHA384_NAME;
606 case DST_ALG_HMACSHA512:
607 hmacname = DNS_TSIG_HMACSHA512_NAME;
610 if (hmacname != NULL) {
611 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
612 hmacname, dstkey, ISC_FALSE,
613 NULL, 0, 0, mctx, NULL,
615 dst_key_free(&dstkey);
616 if (result != ISC_R_SUCCESS) {
617 fprintf(stderr, "could not create key from %s: %s\n",
618 keyfile, isc_result_totext(result));
622 dst_key_attach(dstkey, &sig0key);
623 dst_key_free(&dstkey);
629 isc_task_detach(&global_task);
631 if (userserver != NULL)
632 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
634 if (localaddr != NULL)
635 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
637 if (tsigkey != NULL) {
638 ddebug("Freeing TSIG key");
639 dns_tsigkey_detach(&tsigkey);
642 if (sig0key != NULL) {
643 ddebug("Freeing SIG(0) key");
644 dst_key_free(&sig0key);
647 if (updatemsg != NULL)
648 dns_message_destroy(&updatemsg);
651 ddebug("Destroy DST lib");
653 is_dst_up = ISC_FALSE;
656 cleanup_entropy(&entropy);
658 lwres_conf_clear(lwctx);
659 lwres_context_destroy(&lwctx);
661 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
663 ddebug("Destroying request manager");
664 dns_requestmgr_detach(&requestmgr);
666 ddebug("Freeing the dispatchers");
668 dns_dispatch_detach(&dispatchv4);
670 dns_dispatch_detach(&dispatchv6);
672 ddebug("Shutting down dispatch manager");
673 dns_dispatchmgr_destroy(&dispatchmgr);
678 maybeshutdown(void) {
679 ddebug("Shutting down request manager");
680 dns_requestmgr_shutdown(requestmgr);
689 shutdown_program(isc_task_t *task, isc_event_t *event) {
690 REQUIRE(task == global_task);
693 ddebug("shutdown_program()");
694 isc_event_free(&event);
696 shuttingdown = ISC_TRUE;
703 isc_sockaddr_t bind_any, bind_any6;
704 lwres_result_t lwresult;
705 unsigned int attrs, attrmask;
707 isc_logconfig_t *logconfig = NULL;
709 ddebug("setup_system()");
711 dns_result_register();
713 result = isc_net_probeipv4();
714 if (result == ISC_R_SUCCESS)
715 have_ipv4 = ISC_TRUE;
717 result = isc_net_probeipv6();
718 if (result == ISC_R_SUCCESS)
719 have_ipv6 = ISC_TRUE;
721 if (!have_ipv4 && !have_ipv6)
722 fatal("could not find either IPv4 or IPv6");
724 result = isc_log_create(mctx, &lctx, &logconfig);
725 check_result(result, "isc_log_create");
727 isc_log_setcontext(lctx);
729 dns_log_setcontext(lctx);
731 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
732 check_result(result, "isc_log_usechannel");
734 isc_log_setdebuglevel(lctx, logdebuglevel);
736 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
737 if (lwresult != LWRES_R_SUCCESS)
738 fatal("lwres_context_create failed");
740 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
741 lwconf = lwres_conf_get(lwctx);
743 ns_total = lwconf->nsnext;
745 /* No name servers in resolv.conf; default to loopback. */
746 struct in_addr localhost;
748 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
750 fatal("out of memory");
751 localhost.s_addr = htonl(INADDR_LOOPBACK);
752 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
754 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
756 fatal("out of memory");
757 for (i = 0; i < ns_total; i++) {
758 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
760 memcpy(&in4, lwconf->nameservers[i].address, 4);
761 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT);
764 memcpy(&in6, lwconf->nameservers[i].address, 16);
765 isc_sockaddr_fromin6(&servers[i], &in6,
771 setup_entropy(mctx, NULL, &entropy);
773 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
774 check_result(result, "isc_hash_create");
777 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
778 check_result(result, "dns_dispatchmgr_create");
780 result = isc_socketmgr_create(mctx, &socketmgr);
781 check_result(result, "dns_socketmgr_create");
783 result = isc_timermgr_create(mctx, &timermgr);
784 check_result(result, "dns_timermgr_create");
786 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
787 check_result(result, "isc_taskmgr_create");
789 result = isc_task_create(taskmgr, 0, &global_task);
790 check_result(result, "isc_task_create");
792 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
793 check_result(result, "isc_task_onshutdown");
795 result = dst_lib_init(mctx, entropy, 0);
796 check_result(result, "dst_lib_init");
797 is_dst_up = ISC_TRUE;
799 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
800 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
803 attrs = DNS_DISPATCHATTR_UDP;
804 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
805 attrs |= DNS_DISPATCHATTR_IPV6;
806 isc_sockaddr_any6(&bind_any6);
807 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
808 &bind_any6, PACKETSIZE,
810 attrs, attrmask, &dispatchv6);
811 check_result(result, "dns_dispatch_getudp (v6)");
815 attrs = DNS_DISPATCHATTR_UDP;
816 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
817 attrs |= DNS_DISPATCHATTR_IPV4;
818 isc_sockaddr_any(&bind_any);
819 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
820 &bind_any, PACKETSIZE,
822 attrs, attrmask, &dispatchv4);
823 check_result(result, "dns_dispatch_getudp (v4)");
826 result = dns_requestmgr_create(mctx, timermgr,
827 socketmgr, taskmgr, dispatchmgr,
828 dispatchv4, dispatchv6, &requestmgr);
829 check_result(result, "dns_requestmgr_create");
833 else if (keyfile != NULL)
838 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
843 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
845 if (result != ISC_R_SUCCESS)
846 fatal("couldn't get address for '%s': %s",
847 host, isc_result_totext(result));
851 #define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
854 pre_parse_args(int argc, char **argv) {
857 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
859 case 'M': /* was -dm */
860 debugging = ISC_TRUE;
861 ddebugging = ISC_TRUE;
862 memdebugging = ISC_TRUE;
863 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
868 if (isc_commandline_option != '?')
869 fprintf(stderr, "%s: invalid argument -%c\n",
870 argv[0], isc_commandline_option);
871 fprintf(stderr, "usage: nsupdate [-d] "
872 "[-g | -o | -y keyname:secret | -k keyfile] "
873 "[-v] [filename]\n");
880 isc_commandline_reset = ISC_TRUE;
881 isc_commandline_index = 1;
885 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
891 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
894 debugging = ISC_TRUE;
896 case 'D': /* was -dd */
897 debugging = ISC_TRUE;
898 ddebugging = ISC_TRUE;
903 result = isc_parse_uint32(&i, isc_commandline_argument,
905 if (result != ISC_R_SUCCESS) {
906 fprintf(stderr, "bad library debug value "
907 "'%s'\n", isc_commandline_argument);
913 keystr = isc_commandline_argument;
919 keyfile = isc_commandline_argument;
922 usegsstsig = ISC_TRUE;
923 use_win2k_gsstsig = ISC_FALSE;
926 usegsstsig = ISC_TRUE;
927 use_win2k_gsstsig = ISC_TRUE;
930 result = isc_parse_uint32(&timeout,
931 isc_commandline_argument, 10);
932 if (result != ISC_R_SUCCESS) {
933 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
940 result = isc_parse_uint32(&udp_timeout,
941 isc_commandline_argument, 10);
942 if (result != ISC_R_SUCCESS) {
943 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
946 if (udp_timeout == 0)
947 udp_timeout = UINT_MAX;
950 result = isc_parse_uint32(&udp_retries,
951 isc_commandline_argument, 10);
952 if (result != ISC_R_SUCCESS) {
953 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
959 setup_entropy(mctx, isc_commandline_argument, ectx);
963 fprintf(stderr, "%s: unhandled option: %c\n",
964 argv[0], isc_commandline_option);
968 if (keyfile != NULL && keystr != NULL) {
969 fprintf(stderr, "%s: cannot specify both -k and -y\n",
975 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
976 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
982 fprintf(stderr, "%s: cannot specify -g or -o, " \
983 "program not linked with GSS API Library\n",
989 if (argv[isc_commandline_index] != NULL) {
990 if (strcmp(argv[isc_commandline_index], "-") == 0) {
993 result = isc_stdio_open(argv[isc_commandline_index],
995 if (result != ISC_R_SUCCESS) {
996 fprintf(stderr, "could not open '%s': %s\n",
997 argv[isc_commandline_index],
998 isc_result_totext(result));
1002 interactive = ISC_FALSE;
1007 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1008 isc_result_t result;
1010 isc_buffer_t *namebuf = NULL;
1011 isc_buffer_t source;
1013 word = nsu_strsep(cmdlinep, " \t\r\n");
1015 fprintf(stderr, "could not read owner name\n");
1016 return (STATUS_SYNTAX);
1019 result = dns_message_gettempname(msg, namep);
1020 check_result(result, "dns_message_gettempname");
1021 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
1022 check_result(result, "isc_buffer_allocate");
1023 dns_name_init(*namep, NULL);
1024 dns_name_setbuffer(*namep, namebuf);
1025 dns_message_takebuffer(msg, &namebuf);
1026 isc_buffer_init(&source, word, strlen(word));
1027 isc_buffer_add(&source, strlen(word));
1028 result = dns_name_fromtext(*namep, &source, dns_rootname,
1030 check_result(result, "dns_name_fromtext");
1031 isc_buffer_invalidate(&source);
1032 return (STATUS_MORE);
1036 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1037 dns_rdatatype_t rdatatype, dns_message_t *msg,
1040 char *cmdline = *cmdlinep;
1041 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1043 isc_lex_t *lex = NULL;
1044 dns_rdatacallbacks_t callbacks;
1045 isc_result_t result;
1047 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1050 if (*cmdline != 0) {
1051 dns_rdatacallbacks_init(&callbacks);
1052 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1053 check_result(result, "isc_lex_create");
1054 isc_buffer_init(&source, cmdline, strlen(cmdline));
1055 isc_buffer_add(&source, strlen(cmdline));
1056 result = isc_lex_openbuffer(lex, &source);
1057 check_result(result, "isc_lex_openbuffer");
1058 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1059 check_result(result, "isc_buffer_allocate");
1060 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1061 dns_rootname, 0, mctx, buf,
1063 isc_lex_destroy(&lex);
1064 if (result == ISC_R_SUCCESS) {
1065 isc_buffer_usedregion(buf, &r);
1066 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1067 check_result(result, "isc_buffer_allocate");
1068 isc_buffer_putmem(newbuf, r.base, r.length);
1069 isc_buffer_usedregion(newbuf, &r);
1070 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1071 isc_buffer_free(&buf);
1072 dns_message_takebuffer(msg, &newbuf);
1074 fprintf(stderr, "invalid rdata format: %s\n",
1075 isc_result_totext(result));
1076 isc_buffer_free(&buf);
1077 return (STATUS_SYNTAX);
1080 rdata->flags = DNS_RDATA_UPDATE;
1082 *cmdlinep = cmdline;
1083 return (STATUS_MORE);
1087 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1088 isc_result_t result;
1090 dns_name_t *name = NULL;
1091 isc_textregion_t region;
1092 dns_rdataset_t *rdataset = NULL;
1093 dns_rdatalist_t *rdatalist = NULL;
1094 dns_rdataclass_t rdataclass;
1095 dns_rdatatype_t rdatatype;
1096 dns_rdata_t *rdata = NULL;
1097 isc_uint16_t retval;
1099 ddebug("make_prereq()");
1102 * Read the owner name
1104 retval = parse_name(&cmdline, updatemsg, &name);
1105 if (retval != STATUS_MORE)
1109 * If this is an rrset prereq, read the class or type.
1112 word = nsu_strsep(&cmdline, " \t\r\n");
1114 fprintf(stderr, "could not read class or type\n");
1118 region.length = strlen(word);
1119 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1120 if (result == ISC_R_SUCCESS) {
1121 if (!setzoneclass(rdataclass)) {
1122 fprintf(stderr, "class mismatch: %s\n", word);
1126 * Now read the type.
1128 word = nsu_strsep(&cmdline, " \t\r\n");
1130 fprintf(stderr, "could not read type\n");
1134 region.length = strlen(word);
1135 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1136 if (result != ISC_R_SUCCESS) {
1137 fprintf(stderr, "invalid type: %s\n", word);
1141 rdataclass = getzoneclass();
1142 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1143 if (result != ISC_R_SUCCESS) {
1144 fprintf(stderr, "invalid type: %s\n", word);
1149 rdatatype = dns_rdatatype_any;
1151 result = dns_message_gettemprdata(updatemsg, &rdata);
1152 check_result(result, "dns_message_gettemprdata");
1154 dns_rdata_init(rdata);
1156 if (isrrset && ispositive) {
1157 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1159 if (retval != STATUS_MORE)
1162 rdata->flags = DNS_RDATA_UPDATE;
1164 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1165 check_result(result, "dns_message_gettemprdatalist");
1166 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1167 check_result(result, "dns_message_gettemprdataset");
1168 dns_rdatalist_init(rdatalist);
1169 rdatalist->type = rdatatype;
1171 if (isrrset && rdata->data != NULL)
1172 rdatalist->rdclass = rdataclass;
1174 rdatalist->rdclass = dns_rdataclass_any;
1176 rdatalist->rdclass = dns_rdataclass_none;
1177 rdatalist->covers = 0;
1179 rdata->rdclass = rdatalist->rdclass;
1180 rdata->type = rdatatype;
1181 ISC_LIST_INIT(rdatalist->rdata);
1182 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1183 dns_rdataset_init(rdataset);
1184 dns_rdatalist_tordataset(rdatalist, rdataset);
1185 ISC_LIST_INIT(name->list);
1186 ISC_LIST_APPEND(name->list, rdataset, link);
1187 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1188 return (STATUS_MORE);
1192 dns_message_puttempname(updatemsg, &name);
1193 return (STATUS_SYNTAX);
1197 evaluate_prereq(char *cmdline) {
1199 isc_boolean_t ispositive, isrrset;
1201 ddebug("evaluate_prereq()");
1202 word = nsu_strsep(&cmdline, " \t\r\n");
1204 fprintf(stderr, "could not read operation code\n");
1205 return (STATUS_SYNTAX);
1207 if (strcasecmp(word, "nxdomain") == 0) {
1208 ispositive = ISC_FALSE;
1209 isrrset = ISC_FALSE;
1210 } else if (strcasecmp(word, "yxdomain") == 0) {
1211 ispositive = ISC_TRUE;
1212 isrrset = ISC_FALSE;
1213 } else if (strcasecmp(word, "nxrrset") == 0) {
1214 ispositive = ISC_FALSE;
1216 } else if (strcasecmp(word, "yxrrset") == 0) {
1217 ispositive = ISC_TRUE;
1220 fprintf(stderr, "incorrect operation code: %s\n", word);
1221 return (STATUS_SYNTAX);
1223 return (make_prereq(cmdline, ispositive, isrrset));
1227 evaluate_server(char *cmdline) {
1228 char *word, *server;
1231 word = nsu_strsep(&cmdline, " \t\r\n");
1233 fprintf(stderr, "could not read server name\n");
1234 return (STATUS_SYNTAX);
1238 word = nsu_strsep(&cmdline, " \t\r\n");
1240 port = DNSDEFAULTPORT;
1243 port = strtol(word, &endp, 10);
1245 fprintf(stderr, "port '%s' is not numeric\n", word);
1246 return (STATUS_SYNTAX);
1247 } else if (port < 1 || port > 65535) {
1248 fprintf(stderr, "port '%s' is out of range "
1249 "(1 to 65535)\n", word);
1250 return (STATUS_SYNTAX);
1254 if (userserver == NULL) {
1255 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1256 if (userserver == NULL)
1257 fatal("out of memory");
1260 get_address(server, (in_port_t)port, userserver);
1262 return (STATUS_MORE);
1266 evaluate_local(char *cmdline) {
1270 struct in6_addr in6;
1272 word = nsu_strsep(&cmdline, " \t\r\n");
1274 fprintf(stderr, "could not read server name\n");
1275 return (STATUS_SYNTAX);
1279 word = nsu_strsep(&cmdline, " \t\r\n");
1284 port = strtol(word, &endp, 10);
1286 fprintf(stderr, "port '%s' is not numeric\n", word);
1287 return (STATUS_SYNTAX);
1288 } else if (port < 1 || port > 65535) {
1289 fprintf(stderr, "port '%s' is out of range "
1290 "(1 to 65535)\n", word);
1291 return (STATUS_SYNTAX);
1295 if (localaddr == NULL) {
1296 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1297 if (localaddr == NULL)
1298 fatal("out of memory");
1301 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1302 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1303 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1304 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1306 fprintf(stderr, "invalid address %s", local);
1307 return (STATUS_SYNTAX);
1310 return (STATUS_MORE);
1314 evaluate_key(char *cmdline) {
1318 isc_result_t result;
1319 dns_fixedname_t fkeyname;
1320 dns_name_t *keyname;
1322 unsigned char *secret = NULL;
1323 isc_buffer_t secretbuf;
1324 dns_name_t *hmacname = NULL;
1325 isc_uint16_t digestbits = 0;
1328 namestr = nsu_strsep(&cmdline, " \t\r\n");
1329 if (*namestr == 0) {
1330 fprintf(stderr, "could not read key name\n");
1331 return (STATUS_SYNTAX);
1334 dns_fixedname_init(&fkeyname);
1335 keyname = dns_fixedname_name(&fkeyname);
1337 n = strchr(namestr, ':');
1339 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1342 hmacname = DNS_TSIG_HMACMD5_NAME;
1344 isc_buffer_init(&b, namestr, strlen(namestr));
1345 isc_buffer_add(&b, strlen(namestr));
1346 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
1347 if (result != ISC_R_SUCCESS) {
1348 fprintf(stderr, "could not parse key name\n");
1349 return (STATUS_SYNTAX);
1352 secretstr = nsu_strsep(&cmdline, "\r\n");
1353 if (*secretstr == 0) {
1354 fprintf(stderr, "could not read key secret\n");
1355 return (STATUS_SYNTAX);
1357 secretlen = strlen(secretstr) * 3 / 4;
1358 secret = isc_mem_allocate(mctx, secretlen);
1360 fatal("out of memory");
1362 isc_buffer_init(&secretbuf, secret, secretlen);
1363 result = isc_base64_decodestring(secretstr, &secretbuf);
1364 if (result != ISC_R_SUCCESS) {
1365 fprintf(stderr, "could not create key from %s: %s\n",
1366 secretstr, isc_result_totext(result));
1367 isc_mem_free(mctx, secret);
1368 return (STATUS_SYNTAX);
1370 secretlen = isc_buffer_usedlength(&secretbuf);
1372 if (tsigkey != NULL)
1373 dns_tsigkey_detach(&tsigkey);
1374 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1375 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1377 isc_mem_free(mctx, secret);
1378 if (result != ISC_R_SUCCESS) {
1379 fprintf(stderr, "could not create key from %s %s: %s\n",
1380 namestr, secretstr, dns_result_totext(result));
1381 return (STATUS_SYNTAX);
1383 dst_key_setbits(tsigkey->key, digestbits);
1384 return (STATUS_MORE);
1388 evaluate_zone(char *cmdline) {
1391 isc_result_t result;
1393 word = nsu_strsep(&cmdline, " \t\r\n");
1395 fprintf(stderr, "could not read zone name\n");
1396 return (STATUS_SYNTAX);
1399 dns_fixedname_init(&fuserzone);
1400 userzone = dns_fixedname_name(&fuserzone);
1401 isc_buffer_init(&b, word, strlen(word));
1402 isc_buffer_add(&b, strlen(word));
1403 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE,
1405 if (result != ISC_R_SUCCESS) {
1406 userzone = NULL; /* Lest it point to an invalid name */
1407 fprintf(stderr, "could not parse zone name\n");
1408 return (STATUS_SYNTAX);
1411 return (STATUS_MORE);
1415 evaluate_realm(char *cmdline) {
1420 word = nsu_strsep(&cmdline, " \t\r\n");
1423 isc_mem_free(mctx, realm);
1425 return (STATUS_MORE);
1428 snprintf(buf, sizeof(buf), "@%s", word);
1429 realm = isc_mem_strdup(mctx, buf);
1431 fatal("out of memory");
1432 return (STATUS_MORE);
1435 return (STATUS_SYNTAX);
1440 evaluate_ttl(char *cmdline) {
1442 isc_result_t result;
1445 word = nsu_strsep(&cmdline, " \t\r\n");
1447 fprintf(stderr, "could not ttl\n");
1448 return (STATUS_SYNTAX);
1451 if (!strcasecmp(word, "none")) {
1453 default_ttl_set = ISC_FALSE;
1454 return (STATUS_MORE);
1457 result = isc_parse_uint32(&ttl, word, 10);
1458 if (result != ISC_R_SUCCESS)
1459 return (STATUS_SYNTAX);
1461 if (ttl > TTL_MAX) {
1462 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1464 return (STATUS_SYNTAX);
1467 default_ttl_set = ISC_TRUE;
1469 return (STATUS_MORE);
1473 evaluate_class(char *cmdline) {
1476 isc_result_t result;
1477 dns_rdataclass_t rdclass;
1479 word = nsu_strsep(&cmdline, " \t\r\n");
1481 fprintf(stderr, "could not read class name\n");
1482 return (STATUS_SYNTAX);
1486 r.length = strlen(word);
1487 result = dns_rdataclass_fromtext(&rdclass, &r);
1488 if (result != ISC_R_SUCCESS) {
1489 fprintf(stderr, "could not parse class name: %s\n", word);
1490 return (STATUS_SYNTAX);
1493 case dns_rdataclass_none:
1494 case dns_rdataclass_any:
1495 case dns_rdataclass_reserved0:
1496 fprintf(stderr, "bad default class: %s\n", word);
1497 return (STATUS_SYNTAX);
1499 defaultclass = rdclass;
1502 return (STATUS_MORE);
1506 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1507 isc_result_t result;
1508 dns_name_t *name = NULL;
1511 dns_rdataclass_t rdataclass;
1512 dns_rdatatype_t rdatatype;
1513 dns_rdata_t *rdata = NULL;
1514 dns_rdatalist_t *rdatalist = NULL;
1515 dns_rdataset_t *rdataset = NULL;
1516 isc_textregion_t region;
1517 isc_uint16_t retval;
1519 ddebug("update_addordelete()");
1522 * Read the owner name.
1524 retval = parse_name(&cmdline, updatemsg, &name);
1525 if (retval != STATUS_MORE)
1528 result = dns_message_gettemprdata(updatemsg, &rdata);
1529 check_result(result, "dns_message_gettemprdata");
1531 dns_rdata_init(rdata);
1534 * If this is an add, read the TTL and verify that it's in range.
1535 * If it's a delete, ignore a TTL if present (for compatibility).
1537 word = nsu_strsep(&cmdline, " \t\r\n");
1540 fprintf(stderr, "could not read owner ttl\n");
1545 rdataclass = dns_rdataclass_any;
1546 rdatatype = dns_rdatatype_any;
1547 rdata->flags = DNS_RDATA_UPDATE;
1551 result = isc_parse_uint32(&ttl, word, 10);
1552 if (result != ISC_R_SUCCESS) {
1556 } else if (default_ttl_set) {
1560 fprintf(stderr, "ttl '%s': %s\n", word,
1561 isc_result_totext(result));
1568 else if (ttl > TTL_MAX) {
1569 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1575 * Read the class or type.
1577 word = nsu_strsep(&cmdline, " \t\r\n");
1581 rdataclass = dns_rdataclass_any;
1582 rdatatype = dns_rdatatype_any;
1583 rdata->flags = DNS_RDATA_UPDATE;
1586 fprintf(stderr, "could not read class or type\n");
1591 region.length = strlen(word);
1592 rdataclass = dns_rdataclass_any;
1593 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1594 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1595 if (!setzoneclass(rdataclass)) {
1596 fprintf(stderr, "class mismatch: %s\n", word);
1600 * Now read the type.
1602 word = nsu_strsep(&cmdline, " \t\r\n");
1605 rdataclass = dns_rdataclass_any;
1606 rdatatype = dns_rdatatype_any;
1607 rdata->flags = DNS_RDATA_UPDATE;
1610 fprintf(stderr, "could not read type\n");
1615 region.length = strlen(word);
1616 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1617 if (result != ISC_R_SUCCESS) {
1618 fprintf(stderr, "'%s' is not a valid type: %s\n",
1619 word, isc_result_totext(result));
1623 rdataclass = getzoneclass();
1624 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1625 if (result != ISC_R_SUCCESS) {
1626 fprintf(stderr, "'%s' is not a valid class or type: "
1627 "%s\n", word, isc_result_totext(result));
1632 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1634 if (retval != STATUS_MORE)
1638 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1639 rdataclass = dns_rdataclass_any;
1641 rdataclass = dns_rdataclass_none;
1643 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1644 fprintf(stderr, "could not read rdata\n");
1651 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1652 check_result(result, "dns_message_gettemprdatalist");
1653 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1654 check_result(result, "dns_message_gettemprdataset");
1655 dns_rdatalist_init(rdatalist);
1656 rdatalist->type = rdatatype;
1657 rdatalist->rdclass = rdataclass;
1658 rdatalist->covers = rdatatype;
1659 rdatalist->ttl = (dns_ttl_t)ttl;
1660 ISC_LIST_INIT(rdatalist->rdata);
1661 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1662 dns_rdataset_init(rdataset);
1663 dns_rdatalist_tordataset(rdatalist, rdataset);
1664 ISC_LIST_INIT(name->list);
1665 ISC_LIST_APPEND(name->list, rdataset, link);
1666 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1667 return (STATUS_MORE);
1671 dns_message_puttempname(updatemsg, &name);
1672 dns_message_puttemprdata(updatemsg, &rdata);
1673 return (STATUS_SYNTAX);
1677 evaluate_update(char *cmdline) {
1679 isc_boolean_t isdelete;
1681 ddebug("evaluate_update()");
1682 word = nsu_strsep(&cmdline, " \t\r\n");
1684 fprintf(stderr, "could not read operation code\n");
1685 return (STATUS_SYNTAX);
1687 if (strcasecmp(word, "delete") == 0)
1688 isdelete = ISC_TRUE;
1689 else if (strcasecmp(word, "add") == 0)
1690 isdelete = ISC_FALSE;
1692 fprintf(stderr, "incorrect operation code: %s\n", word);
1693 return (STATUS_SYNTAX);
1695 return (update_addordelete(cmdline, isdelete));
1699 setzone(dns_name_t *zonename) {
1700 isc_result_t result;
1701 dns_name_t *name = NULL;
1702 dns_rdataset_t *rdataset = NULL;
1704 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1705 if (result == ISC_R_SUCCESS) {
1706 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1707 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1708 for (rdataset = ISC_LIST_HEAD(name->list);
1710 rdataset = ISC_LIST_HEAD(name->list)) {
1711 ISC_LIST_UNLINK(name->list, rdataset, link);
1712 dns_rdataset_disassociate(rdataset);
1713 dns_message_puttemprdataset(updatemsg, &rdataset);
1715 dns_message_puttempname(updatemsg, &name);
1718 if (zonename != NULL) {
1719 result = dns_message_gettempname(updatemsg, &name);
1720 check_result(result, "dns_message_gettempname");
1721 dns_name_init(name, NULL);
1722 dns_name_clone(zonename, name);
1723 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1724 check_result(result, "dns_message_gettemprdataset");
1725 dns_rdataset_makequestion(rdataset, getzoneclass(),
1727 ISC_LIST_INIT(name->list);
1728 ISC_LIST_APPEND(name->list, rdataset, link);
1729 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1734 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1735 isc_result_t result;
1736 isc_buffer_t *buf = NULL;
1739 ddebug("show_message()");
1745 if (bufsz > MAXTEXT) {
1746 fprintf(stderr, "could not allocate large enough "
1747 "buffer to display message\n");
1751 isc_buffer_free(&buf);
1752 result = isc_buffer_allocate(mctx, &buf, bufsz);
1753 check_result(result, "isc_buffer_allocate");
1754 result = dns_message_totext(msg, style, 0, buf);
1756 } while (result == ISC_R_NOSPACE);
1757 if (result != ISC_R_SUCCESS) {
1758 fprintf(stderr, "could not convert message to text format.\n");
1759 isc_buffer_free(&buf);
1762 fprintf(stream, "%s\n%.*s", description,
1763 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1764 isc_buffer_free(&buf);
1769 get_next_command(void) {
1770 char cmdlinebuf[MAXCMD];
1774 ddebug("get_next_command()");
1776 fprintf(stdout, "> ");
1780 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1782 if (cmdline == NULL)
1783 return (STATUS_QUIT);
1784 word = nsu_strsep(&cmdline, " \t\r\n");
1787 return (STATUS_QUIT);
1789 return (STATUS_SEND);
1791 return (STATUS_MORE);
1792 if (strcasecmp(word, "quit") == 0)
1793 return (STATUS_QUIT);
1794 if (strcasecmp(word, "prereq") == 0)
1795 return (evaluate_prereq(cmdline));
1796 if (strcasecmp(word, "update") == 0)
1797 return (evaluate_update(cmdline));
1798 if (strcasecmp(word, "server") == 0)
1799 return (evaluate_server(cmdline));
1800 if (strcasecmp(word, "local") == 0)
1801 return (evaluate_local(cmdline));
1802 if (strcasecmp(word, "zone") == 0)
1803 return (evaluate_zone(cmdline));
1804 if (strcasecmp(word, "class") == 0)
1805 return (evaluate_class(cmdline));
1806 if (strcasecmp(word, "send") == 0)
1807 return (STATUS_SEND);
1808 if (strcasecmp(word, "debug") == 0) {
1810 ddebugging = ISC_TRUE;
1812 debugging = ISC_TRUE;
1813 return (STATUS_MORE);
1815 if (strcasecmp(word, "ttl") == 0)
1816 return (evaluate_ttl(cmdline));
1817 if (strcasecmp(word, "show") == 0) {
1818 show_message(stdout, updatemsg, "Outgoing update query:");
1819 return (STATUS_MORE);
1821 if (strcasecmp(word, "answer") == 0) {
1823 show_message(stdout, answer, "Answer:");
1824 return (STATUS_MORE);
1826 if (strcasecmp(word, "key") == 0) {
1827 usegsstsig = ISC_FALSE;
1828 return (evaluate_key(cmdline));
1830 if (strcasecmp(word, "realm") == 0)
1831 return (evaluate_realm(cmdline));
1832 if (strcasecmp(word, "gsstsig") == 0) {
1834 usegsstsig = ISC_TRUE;
1835 use_win2k_gsstsig = ISC_FALSE;
1837 fprintf(stderr, "gsstsig not supported\n");
1839 return (STATUS_MORE);
1841 if (strcasecmp(word, "oldgsstsig") == 0) {
1843 usegsstsig = ISC_TRUE;
1844 use_win2k_gsstsig = ISC_TRUE;
1846 fprintf(stderr, "gsstsig not supported\n");
1848 return (STATUS_MORE);
1850 if (strcasecmp(word, "help") == 0) {
1852 "local address [port] (set local resolver)\n"
1853 "server address [port] (set master server for zone)\n"
1854 "send (send the update request)\n"
1855 "show (show the update request)\n"
1856 "answer (show the answer to the last request)\n"
1857 "quit (quit, any pending update is not sent\n"
1858 "help (display this message_\n"
1859 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1860 "gsstsig (use GSS_TSIG to sign the request)\n"
1861 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1862 "zone name (set the zone to be updated)\n"
1863 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1864 "prereq nxdomain name (does this name not exist)\n"
1865 "prereq yxdomain name (does this name exist)\n"
1866 "prereq nxrrset .... (does this RRset exist)\n"
1867 "prereq yxrrset .... (does this RRset not exist)\n"
1868 "update add .... (add the given record to the zone)\n"
1869 "update delete .... (remove the given record(s) from the zone)\n");
1870 return (STATUS_MORE);
1872 fprintf(stderr, "incorrect section name: %s\n", word);
1873 return (STATUS_SYNTAX);
1876 static isc_boolean_t
1877 user_interaction(void) {
1878 isc_uint16_t result = STATUS_MORE;
1880 ddebug("user_interaction()");
1881 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
1882 result = get_next_command();
1883 if (!interactive && result == STATUS_SYNTAX)
1884 fatal("syntax error");
1886 if (result == STATUS_SEND)
1894 isc_event_t *event = global_event;
1895 ddebug("done_update()");
1896 isc_task_send(global_task, &event);
1900 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
1901 isc_result_t result;
1902 dns_rdata_t rdata = DNS_RDATA_INIT;
1903 dns_rdata_any_tsig_t tsig;
1905 result = dns_rdataset_first(rdataset);
1906 check_result(result, "dns_rdataset_first");
1907 dns_rdataset_current(rdataset, &rdata);
1908 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
1909 check_result(result, "dns_rdata_tostruct");
1910 if (tsig.error != 0) {
1911 if (isc_buffer_remaininglength(b) < 1)
1912 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1913 isc__buffer_putstr(b, "(" /*)*/);
1914 result = dns_tsigrcode_totext(tsig.error, b);
1915 check_result(result, "dns_tsigrcode_totext");
1916 if (isc_buffer_remaininglength(b) < 1)
1917 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1918 isc__buffer_putstr(b, /*(*/ ")");
1923 update_completed(isc_task_t *task, isc_event_t *event) {
1924 dns_requestevent_t *reqev = NULL;
1925 isc_result_t result;
1926 dns_request_t *request;
1930 ddebug("update_completed()");
1934 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1935 reqev = (dns_requestevent_t *)event;
1936 request = reqev->request;
1939 dns_request_destroy(&request);
1940 isc_event_free(&event);
1945 if (reqev->result != ISC_R_SUCCESS) {
1946 fprintf(stderr, "; Communication with server failed: %s\n",
1947 isc_result_totext(reqev->result));
1948 seenerror = ISC_TRUE;
1952 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
1953 check_result(result, "dns_message_create");
1954 result = dns_request_getresponse(request, answer,
1955 DNS_MESSAGEPARSE_PRESERVEORDER);
1958 if (answer->verify_attempted)
1959 ddebug("tsig verification successful");
1961 case DNS_R_CLOCKSKEW:
1962 case DNS_R_EXPECTEDTSIG:
1963 case DNS_R_TSIGERRORSET:
1964 case DNS_R_TSIGVERIFYFAILURE:
1965 case DNS_R_UNEXPECTEDTSIG:
1968 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
1970 * For MS DNS that violates RFC 2845, section 4.2
1975 fprintf(stderr, "; TSIG error with server: %s\n",
1976 isc_result_totext(result));
1977 seenerror = ISC_TRUE;
1980 check_result(result, "dns_request_getresponse");
1983 if (answer->rcode != dns_rcode_noerror) {
1984 seenerror = ISC_TRUE;
1988 dns_rdataset_t *rds;
1990 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1991 result = dns_rcode_totext(answer->rcode, &b);
1992 check_result(result, "dns_rcode_totext");
1993 rds = dns_message_gettsig(answer, NULL);
1995 check_tsig_error(rds, &b);
1996 fprintf(stderr, "update failed: %.*s\n",
1997 (int)isc_buffer_usedlength(&b), buf);
2001 show_message(stderr, answer, "\nReply from update query:");
2004 dns_request_destroy(&request);
2006 dns_name_free(&tmpzonename, mctx);
2007 dns_name_free(&restart_master, mctx);
2009 isc_event_free(&event);
2014 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2015 isc_sockaddr_t *srcaddr)
2017 isc_result_t result;
2018 dns_request_t *request = NULL;
2019 unsigned int options = 0;
2021 ddebug("send_update()");
2026 options |= DNS_REQUESTOPT_TCP;
2027 if (tsigkey == NULL && sig0key != NULL) {
2028 result = dns_message_setsig0key(updatemsg, sig0key);
2029 check_result(result, "dns_message_setsig0key");
2032 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2034 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2035 fprintf(stderr, "Sending update to %s\n", addrbuf);
2038 /* Windows doesn't like the tsig name to be compressed. */
2039 if (updatemsg->tsigname)
2040 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2042 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2043 master, options, tsigkey, timeout,
2044 udp_timeout, udp_retries, global_task,
2045 update_completed, NULL, &request);
2046 check_result(result, "dns_request_createvia3");
2049 show_message(stdout, updatemsg, "Outgoing update query:");
2055 recvsoa(isc_task_t *task, isc_event_t *event) {
2056 dns_requestevent_t *reqev = NULL;
2057 dns_request_t *request = NULL;
2058 isc_result_t result, eresult;
2059 dns_message_t *rcvmsg = NULL;
2060 dns_section_t section;
2061 dns_name_t *name = NULL;
2062 dns_rdataset_t *soaset = NULL;
2063 dns_rdata_soa_t soa;
2064 dns_rdata_t soarr = DNS_RDATA_INIT;
2067 nsu_requestinfo_t *reqinfo;
2068 dns_message_t *soaquery = NULL;
2069 isc_sockaddr_t *addr;
2070 isc_boolean_t seencname = ISC_FALSE;
2072 unsigned int nlabels;
2076 ddebug("recvsoa()");
2080 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2081 reqev = (dns_requestevent_t *)event;
2082 request = reqev->request;
2083 eresult = reqev->result;
2084 reqinfo = reqev->ev_arg;
2085 soaquery = reqinfo->msg;
2086 addr = reqinfo->addr;
2089 dns_request_destroy(&request);
2090 dns_message_destroy(&soaquery);
2091 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2092 isc_event_free(&event);
2097 if (eresult != ISC_R_SUCCESS) {
2098 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2100 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2101 fprintf(stderr, "; Communication with %s failed: %s\n",
2102 addrbuf, isc_result_totext(eresult));
2103 if (userserver != NULL)
2104 fatal("could not talk to specified name server");
2105 else if (++ns_inuse >= lwconf->nsnext)
2106 fatal("could not talk to any default name server");
2107 ddebug("Destroying request [%p]", request);
2108 dns_request_destroy(&request);
2109 dns_message_renderreset(soaquery);
2110 dns_message_settsigkey(soaquery, NULL);
2111 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2112 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2113 isc_event_free(&event);
2114 setzoneclass(dns_rdataclass_none);
2118 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2120 isc_event_free(&event);
2123 ddebug("About to create rcvmsg");
2124 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2125 check_result(result, "dns_message_create");
2126 result = dns_request_getresponse(request, rcvmsg,
2127 DNS_MESSAGEPARSE_PRESERVEORDER);
2128 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2129 dns_message_destroy(&rcvmsg);
2130 ddebug("Destroying request [%p]", request);
2131 dns_request_destroy(&request);
2132 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2133 if (reqinfo == NULL)
2134 fatal("out of memory");
2135 reqinfo->msg = soaquery;
2136 reqinfo->addr = addr;
2137 dns_message_renderreset(soaquery);
2138 ddebug("retrying soa request without TSIG");
2139 result = dns_request_createvia3(requestmgr, soaquery,
2140 localaddr, addr, 0, NULL,
2143 global_task, recvsoa, reqinfo,
2145 check_result(result, "dns_request_createvia");
2149 check_result(result, "dns_request_getresponse");
2150 section = DNS_SECTION_ANSWER;
2153 show_message(stderr, rcvmsg, "Reply from SOA query:");
2155 if (rcvmsg->rcode != dns_rcode_noerror &&
2156 rcvmsg->rcode != dns_rcode_nxdomain)
2157 fatal("response to SOA query was unsuccessful");
2159 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2160 char namebuf[DNS_NAME_FORMATSIZE];
2161 dns_name_format(userzone, namebuf, sizeof(namebuf));
2162 error("specified zone '%s' does not exist (NXDOMAIN)",
2164 dns_message_destroy(&rcvmsg);
2165 dns_request_destroy(&request);
2166 dns_message_destroy(&soaquery);
2167 ddebug("Out of recvsoa");
2169 seenerror = ISC_TRUE;
2175 section = DNS_SECTION_ANSWER;
2177 section = DNS_SECTION_AUTHORITY;
2181 result = dns_message_firstname(rcvmsg, section);
2182 if (result != ISC_R_SUCCESS) {
2186 while (result == ISC_R_SUCCESS) {
2188 dns_message_currentname(rcvmsg, section, &name);
2190 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2192 if (result == ISC_R_SUCCESS)
2194 if (section == DNS_SECTION_ANSWER) {
2195 dns_rdataset_t *tset = NULL;
2196 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2197 &tset) == ISC_R_SUCCESS ||
2198 dns_message_findtype(name, dns_rdatatype_dname, 0,
2199 &tset) == ISC_R_SUCCESS ) {
2200 seencname = ISC_TRUE;
2205 result = dns_message_nextname(rcvmsg, section);
2208 if (soaset == NULL && !seencname) {
2217 char namestr[DNS_NAME_FORMATSIZE];
2218 dns_name_format(name, namestr, sizeof(namestr));
2219 fprintf(stderr, "Found zone name: %s\n", namestr);
2222 result = dns_rdataset_first(soaset);
2223 check_result(result, "dns_rdataset_first");
2225 dns_rdata_init(&soarr);
2226 dns_rdataset_current(soaset, &soarr);
2227 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2228 check_result(result, "dns_rdata_tostruct");
2230 dns_name_init(&master, NULL);
2231 dns_name_clone(&soa.origin, &master);
2233 if (userzone != NULL)
2234 zonename = userzone;
2239 char namestr[DNS_NAME_FORMATSIZE];
2240 dns_name_format(&master, namestr, sizeof(namestr));
2241 fprintf(stderr, "The master is: %s\n", namestr);
2244 if (userserver != NULL)
2245 serveraddr = userserver;
2247 char serverstr[DNS_NAME_MAXTEXT+1];
2250 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2251 result = dns_name_totext(&master, ISC_TRUE, &buf);
2252 check_result(result, "dns_name_totext");
2253 serverstr[isc_buffer_usedlength(&buf)] = 0;
2254 get_address(serverstr, DNSDEFAULTPORT, &tempaddr);
2255 serveraddr = &tempaddr;
2257 dns_rdata_freestruct(&soa);
2261 dns_name_init(&tmpzonename, NULL);
2262 dns_name_dup(zonename, mctx, &tmpzonename);
2263 dns_name_init(&restart_master, NULL);
2264 dns_name_dup(&master, mctx, &restart_master);
2265 start_gssrequest(&master);
2267 send_update(zonename, serveraddr, localaddr);
2268 setzoneclass(dns_rdataclass_none);
2271 send_update(zonename, serveraddr, localaddr);
2272 setzoneclass(dns_rdataclass_none);
2275 dns_message_destroy(&soaquery);
2276 dns_request_destroy(&request);
2279 dns_message_destroy(&rcvmsg);
2280 ddebug("Out of recvsoa");
2284 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2285 INSIST(result == ISC_R_SUCCESS);
2287 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2288 nlabels = dns_name_countlabels(name);
2290 fatal("could not find enclosing zone");
2291 dns_name_init(&tname, NULL);
2292 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2293 dns_name_clone(&tname, name);
2294 dns_request_destroy(&request);
2295 dns_message_renderreset(soaquery);
2296 dns_message_settsigkey(soaquery, NULL);
2297 if (userserver != NULL)
2298 sendrequest(localaddr, userserver, soaquery, &request);
2300 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2305 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2306 dns_message_t *msg, dns_request_t **request)
2308 isc_result_t result;
2309 nsu_requestinfo_t *reqinfo;
2311 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2312 if (reqinfo == NULL)
2313 fatal("out of memory");
2315 reqinfo->addr = destaddr;
2316 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2317 (userserver != NULL) ? tsigkey : NULL,
2318 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2319 global_task, recvsoa, reqinfo, request);
2320 check_result(result, "dns_request_createvia");
2326 start_gssrequest(dns_name_t *master)
2328 gss_ctx_id_t context;
2330 isc_result_t result;
2331 isc_uint32_t val = 0;
2332 dns_message_t *rmsg;
2333 dns_request_t *request = NULL;
2334 dns_name_t *servname;
2335 dns_fixedname_t fname;
2336 char namestr[DNS_NAME_FORMATSIZE];
2337 char keystr[DNS_NAME_FORMATSIZE];
2339 debug("start_gssrequest");
2342 if (gssring != NULL)
2343 dns_tsigkeyring_destroy(&gssring);
2345 result = dns_tsigkeyring_create(mctx, &gssring);
2347 if (result != ISC_R_SUCCESS)
2348 fatal("dns_tsigkeyring_create failed: %s",
2349 isc_result_totext(result));
2351 dns_name_format(master, namestr, sizeof(namestr));
2352 if (kserver == NULL) {
2353 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2354 if (kserver == NULL)
2355 fatal("out of memory");
2357 if (userserver == NULL)
2358 get_address(namestr, DNSDEFAULTPORT, kserver);
2360 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2362 dns_fixedname_init(&fname);
2363 servname = dns_fixedname_name(&fname);
2365 result = isc_string_printf(servicename, sizeof(servicename),
2366 "DNS/%s%s", namestr, realm ? realm : "");
2367 if (result != ISC_R_SUCCESS)
2368 fatal("isc_string_printf(servicename) failed: %s",
2369 isc_result_totext(result));
2370 isc_buffer_init(&buf, servicename, strlen(servicename));
2371 isc_buffer_add(&buf, strlen(servicename));
2372 result = dns_name_fromtext(servname, &buf, dns_rootname,
2374 if (result != ISC_R_SUCCESS)
2375 fatal("dns_name_fromtext(servname) failed: %s",
2376 isc_result_totext(result));
2378 dns_fixedname_init(&fkname);
2379 keyname = dns_fixedname_name(&fkname);
2381 isc_random_get(&val);
2382 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2384 if (result != ISC_R_SUCCESS)
2385 fatal("isc_string_printf(keystr) failed: %s",
2386 isc_result_totext(result));
2387 isc_buffer_init(&buf, keystr, strlen(keystr));
2388 isc_buffer_add(&buf, strlen(keystr));
2390 result = dns_name_fromtext(keyname, &buf, dns_rootname,
2392 if (result != ISC_R_SUCCESS)
2393 fatal("dns_name_fromtext(keyname) failed: %s",
2394 isc_result_totext(result));
2396 /* Windows doesn't recognize name compression in the key name. */
2397 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2400 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2401 if (result != ISC_R_SUCCESS)
2402 fatal("dns_message_create failed: %s",
2403 isc_result_totext(result));
2405 /* Build first request. */
2406 context = GSS_C_NO_CONTEXT;
2407 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2408 &context, use_win2k_gsstsig);
2409 if (result == ISC_R_FAILURE)
2410 fatal("Check your Kerberos ticket, it may have expired.");
2411 if (result != ISC_R_SUCCESS)
2412 fatal("dns_tkey_buildgssquery failed: %s",
2413 isc_result_totext(result));
2415 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2419 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2420 dns_message_t *msg, dns_request_t **request,
2421 gss_ctx_id_t context)
2423 isc_result_t result;
2424 nsu_gssinfo_t *reqinfo;
2425 unsigned int options = 0;
2427 debug("send_gssrequest");
2428 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2429 if (reqinfo == NULL)
2430 fatal("out of memory");
2432 reqinfo->addr = destaddr;
2433 reqinfo->context = context;
2435 options |= DNS_REQUESTOPT_TCP;
2436 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2437 options, tsigkey, FIND_TIMEOUT * 20,
2438 FIND_TIMEOUT, 3, global_task, recvgss,
2440 check_result(result, "dns_request_createvia3");
2442 show_message(stdout, msg, "Outgoing update query:");
2447 recvgss(isc_task_t *task, isc_event_t *event) {
2448 dns_requestevent_t *reqev = NULL;
2449 dns_request_t *request = NULL;
2450 isc_result_t result, eresult;
2451 dns_message_t *rcvmsg = NULL;
2452 nsu_gssinfo_t *reqinfo;
2453 dns_message_t *tsigquery = NULL;
2454 isc_sockaddr_t *addr;
2455 gss_ctx_id_t context;
2457 dns_name_t *servname;
2458 dns_fixedname_t fname;
2462 ddebug("recvgss()");
2466 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2467 reqev = (dns_requestevent_t *)event;
2468 request = reqev->request;
2469 eresult = reqev->result;
2470 reqinfo = reqev->ev_arg;
2471 tsigquery = reqinfo->msg;
2472 context = reqinfo->context;
2473 addr = reqinfo->addr;
2476 dns_request_destroy(&request);
2477 dns_message_destroy(&tsigquery);
2478 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2479 isc_event_free(&event);
2484 if (eresult != ISC_R_SUCCESS) {
2485 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2487 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2488 fprintf(stderr, "; Communication with %s failed: %s\n",
2489 addrbuf, isc_result_totext(eresult));
2490 if (userserver != NULL)
2491 fatal("could not talk to specified name server");
2492 else if (++ns_inuse >= lwconf->nsnext)
2493 fatal("could not talk to any default name server");
2494 ddebug("Destroying request [%p]", request);
2495 dns_request_destroy(&request);
2496 dns_message_renderreset(tsigquery);
2497 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2499 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2500 isc_event_free(&event);
2503 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2505 isc_event_free(&event);
2508 ddebug("recvgss creating rcvmsg");
2509 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2510 check_result(result, "dns_message_create");
2512 result = dns_request_getresponse(request, rcvmsg,
2513 DNS_MESSAGEPARSE_PRESERVEORDER);
2514 check_result(result, "dns_request_getresponse");
2517 show_message(stderr, rcvmsg,
2518 "recvmsg reply from GSS-TSIG query");
2520 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2521 ddebug("recvgss trying %s GSS-TSIG",
2522 use_win2k_gsstsig ? "Standard" : "Win2k");
2523 if (use_win2k_gsstsig)
2524 use_win2k_gsstsig = ISC_FALSE;
2526 use_win2k_gsstsig = ISC_TRUE;
2527 tried_other_gsstsig = ISC_TRUE;
2528 start_gssrequest(&restart_master);
2532 if (rcvmsg->rcode != dns_rcode_noerror &&
2533 rcvmsg->rcode != dns_rcode_nxdomain)
2534 fatal("response to GSS-TSIG query was unsuccessful");
2537 dns_fixedname_init(&fname);
2538 servname = dns_fixedname_name(&fname);
2539 isc_buffer_init(&buf, servicename, strlen(servicename));
2540 isc_buffer_add(&buf, strlen(servicename));
2541 result = dns_name_fromtext(servname, &buf, dns_rootname,
2543 check_result(result, "dns_name_fromtext");
2546 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2547 &context, &tsigkey, gssring,
2551 case DNS_R_CONTINUE:
2552 send_gssrequest(localaddr, kserver, tsigquery, &request,
2558 * XXXSRA Waaay too much fun here. There's no good
2559 * reason why we need a TSIG here (the people who put
2560 * it into the spec admitted at the time that it was
2561 * not a security issue), and Windows clients don't
2562 * seem to work if named complies with the spec and
2563 * includes the gratuitous TSIG. So we're in the
2564 * bizarre situation of having to choose between
2565 * complying with a useless requirement in the spec
2566 * and interoperating. This is nuts. If we can
2567 * confirm this behavior, we should ask the WG to
2568 * consider removing the requirement for the
2569 * gratuitous TSIG here. For the moment, we ignore
2570 * the TSIG -- this too is a spec violation, but it's
2571 * the least insane thing to do.
2575 * Verify the signature.
2577 rcvmsg->state = DNS_SECTION_ANY;
2578 dns_message_setquerytsig(rcvmsg, NULL);
2579 result = dns_message_settsigkey(rcvmsg, tsigkey);
2580 check_result(result, "dns_message_settsigkey");
2581 result = dns_message_checksig(rcvmsg, NULL);
2582 ddebug("tsig verification: %s", dns_result_totext(result));
2583 check_result(result, "dns_message_checksig");
2586 send_update(&tmpzonename, serveraddr, localaddr);
2587 setzoneclass(dns_rdataclass_none);
2591 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
2595 dns_request_destroy(&request);
2596 dns_message_destroy(&tsigquery);
2598 dns_message_destroy(&rcvmsg);
2599 ddebug("Out of recvgss");
2604 start_update(void) {
2605 isc_result_t result;
2606 dns_rdataset_t *rdataset = NULL;
2607 dns_name_t *name = NULL;
2608 dns_request_t *request = NULL;
2609 dns_message_t *soaquery = NULL;
2610 dns_name_t *firstname;
2611 dns_section_t section = DNS_SECTION_UPDATE;
2613 ddebug("start_update()");
2616 dns_message_destroy(&answer);
2618 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2619 send_update(userzone, userserver, localaddr);
2620 setzoneclass(dns_rdataclass_none);
2624 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2626 check_result(result, "dns_message_create");
2628 if (userserver == NULL)
2629 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2631 result = dns_message_gettempname(soaquery, &name);
2632 check_result(result, "dns_message_gettempname");
2634 result = dns_message_gettemprdataset(soaquery, &rdataset);
2635 check_result(result, "dns_message_gettemprdataset");
2637 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2639 if (userzone != NULL) {
2640 dns_name_init(name, NULL);
2641 dns_name_clone(userzone, name);
2643 dns_rdataset_t *tmprdataset;
2644 result = dns_message_firstname(updatemsg, section);
2645 if (result == ISC_R_NOMORE) {
2646 section = DNS_SECTION_PREREQUISITE;
2647 result = dns_message_firstname(updatemsg, section);
2649 if (result != ISC_R_SUCCESS) {
2650 dns_message_puttempname(soaquery, &name);
2651 dns_rdataset_disassociate(rdataset);
2652 dns_message_puttemprdataset(soaquery, &rdataset);
2653 dns_message_destroy(&soaquery);
2658 dns_message_currentname(updatemsg, section, &firstname);
2659 dns_name_init(name, NULL);
2660 dns_name_clone(firstname, name);
2662 * Looks to see if the first name references a DS record
2663 * and if that name is not the root remove a label as DS
2664 * records live in the parent zone so we need to start our
2665 * search one label up.
2667 tmprdataset = ISC_LIST_HEAD(firstname->list);
2668 if (section == DNS_SECTION_UPDATE &&
2669 !dns_name_equal(firstname, dns_rootname) &&
2670 tmprdataset->type == dns_rdatatype_ds) {
2671 unsigned int labels = dns_name_countlabels(name);
2672 dns_name_getlabelsequence(name, 1, labels - 1, name);
2676 ISC_LIST_INIT(name->list);
2677 ISC_LIST_APPEND(name->list, rdataset, link);
2678 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2680 if (userserver != NULL)
2681 sendrequest(localaddr, userserver, soaquery, &request);
2684 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2690 ddebug("cleanup()");
2693 dns_message_destroy(&answer);
2696 if (tsigkey != NULL) {
2697 ddebug("detach tsigkey x%p", tsigkey);
2698 dns_tsigkey_detach(&tsigkey);
2700 if (gssring != NULL) {
2701 ddebug("Destroying GSS-TSIG keyring");
2702 dns_tsigkeyring_destroy(&gssring);
2704 if (kserver != NULL) {
2705 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2708 if (realm != NULL) {
2709 isc_mem_free(mctx, realm);
2714 if (sig0key != NULL)
2715 dst_key_free(&sig0key);
2717 ddebug("Shutting down task manager");
2718 isc_taskmgr_destroy(&taskmgr);
2720 ddebug("Destroying event");
2721 isc_event_free(&global_event);
2723 ddebug("Shutting down socket manager");
2724 isc_socketmgr_destroy(&socketmgr);
2726 ddebug("Shutting down timer manager");
2727 isc_timermgr_destroy(&timermgr);
2729 ddebug("Destroying hash context");
2732 ddebug("Destroying name state");
2735 ddebug("Removing log context");
2736 isc_log_destroy(&lctx);
2738 ddebug("Destroying memory context");
2740 isc_mem_stats(mctx, stderr);
2741 isc_mem_destroy(&mctx);
2745 getinput(isc_task_t *task, isc_event_t *event) {
2755 if (global_event == NULL)
2756 global_event = event;
2759 more = user_interaction();
2769 main(int argc, char **argv) {
2770 isc_result_t result;
2771 style = &dns_master_style_debug;
2775 interactive = ISC_TF(isatty(0));
2779 pre_parse_args(argc, argv);
2781 result = isc_mem_create(0, 0, &mctx);
2782 check_result(result, "isc_mem_create");
2784 parse_args(argc, argv, mctx, &entropy);
2788 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2789 check_result(result, "isc_app_onrun");
2791 (void)isc_app_run();