2 * Copyright (C) 2004-2010 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.
18 /* $Id: nsupdate.c,v 1.163.48.15 2010-12-09 04:30:57 tbox Exp $ */
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);
178 fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
181 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
184 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
187 static dns_fixedname_t fkname;
188 static isc_sockaddr_t *kserver = NULL;
189 static char *realm = NULL;
190 static char servicename[DNS_NAME_FORMATSIZE];
191 static dns_name_t *keyname;
192 typedef struct nsu_gssinfo {
194 isc_sockaddr_t *addr;
195 gss_ctx_id_t context;
199 start_gssrequest(dns_name_t *master);
201 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
202 dns_message_t *msg, dns_request_t **request,
203 gss_ctx_id_t context);
205 recvgss(isc_task_t *task, isc_event_t *event);
209 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
211 #define STATUS_MORE (isc_uint16_t)0
212 #define STATUS_SEND (isc_uint16_t)1
213 #define STATUS_QUIT (isc_uint16_t)2
214 #define STATUS_SYNTAX (isc_uint16_t)3
216 typedef struct entropysource entropysource_t;
218 struct entropysource {
219 isc_entropysource_t *source;
221 ISC_LINK(entropysource_t) link;
224 static ISC_LIST(entropysource_t) sources;
227 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
230 isc_entropysource_t *source = NULL;
231 entropysource_t *elt;
232 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
234 REQUIRE(ectx != NULL);
237 result = isc_entropy_create(mctx, ectx);
238 if (result != ISC_R_SUCCESS)
239 fatal("could not create entropy object");
240 ISC_LIST_INIT(sources);
243 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
244 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
248 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
251 if (result != ISC_R_SUCCESS)
252 fatal("could not initialize entropy source: %s",
253 isc_result_totext(result));
255 if (source != NULL) {
256 elt = isc_mem_get(mctx, sizeof(*elt));
258 fatal("out of memory");
259 elt->source = source;
261 ISC_LINK_INIT(elt, link);
262 ISC_LIST_APPEND(sources, elt, link);
267 cleanup_entropy(isc_entropy_t **ectx) {
268 entropysource_t *source;
269 while (!ISC_LIST_EMPTY(sources)) {
270 source = ISC_LIST_HEAD(sources);
271 ISC_LIST_UNLINK(sources, source, link);
272 isc_entropy_destroysource(&source->source);
273 isc_mem_put(source->mctx, source, sizeof(*source));
275 isc_entropy_detach(ectx);
279 static dns_rdataclass_t
281 if (zoneclass == dns_rdataclass_none)
282 zoneclass = defaultclass;
287 setzoneclass(dns_rdataclass_t rdclass) {
288 if (zoneclass == dns_rdataclass_none ||
289 rdclass == dns_rdataclass_none)
291 if (zoneclass != rdclass)
297 fatal(const char *format, ...) {
300 va_start(args, format);
301 vfprintf(stderr, format, args);
303 fprintf(stderr, "\n");
308 error(const char *format, ...) {
311 va_start(args, format);
312 vfprintf(stderr, format, args);
314 fprintf(stderr, "\n");
318 debug(const char *format, ...) {
322 va_start(args, format);
323 vfprintf(stderr, format, args);
325 fprintf(stderr, "\n");
330 ddebug(const char *format, ...) {
334 va_start(args, format);
335 vfprintf(stderr, format, args);
337 fprintf(stderr, "\n");
342 check_result(isc_result_t result, const char *msg) {
343 if (result != ISC_R_SUCCESS)
344 fatal("%s: %s", msg, isc_result_totext(result));
348 mem_alloc(void *arg, size_t size) {
349 return (isc_mem_get(arg, size));
353 mem_free(void *arg, void *mem, size_t size) {
354 isc_mem_put(arg, mem, size);
358 nsu_strsep(char **stringp, const char *delim) {
359 char *string = *stringp;
367 for (; *string != '\0'; string++) {
369 for (d = delim; (dc = *d) != '\0'; d++) {
377 for (s = string; *s != '\0'; s++) {
379 for (d = delim; (dc = *d) != '\0'; d++) {
395 ddebug("reset_system()");
396 /* If the update message is still around, destroy it */
397 if (updatemsg != NULL)
398 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
400 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
402 check_result(result, "dns_message_create");
404 updatemsg->opcode = dns_opcode_update;
407 dns_tsigkey_detach(&tsigkey);
409 dns_tsigkeyring_destroy(&gssring);
410 tried_other_gsstsig = ISC_FALSE;
415 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
416 isc_uint16_t digestbits = 0;
420 REQUIRE(hmac != NULL && *hmac == NULL);
421 REQUIRE(hmacstr != NULL);
423 if (len >= sizeof(buf))
424 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
426 strncpy(buf, hmacstr, len);
429 if (strcasecmp(buf, "hmac-md5") == 0) {
430 *hmac = DNS_TSIG_HMACMD5_NAME;
431 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
432 *hmac = DNS_TSIG_HMACMD5_NAME;
433 result = isc_parse_uint16(&digestbits, &buf[9], 10);
434 if (result != ISC_R_SUCCESS || digestbits > 128)
435 fatal("digest-bits out of range [0..128]");
436 digestbits = (digestbits +7) & ~0x7U;
437 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
438 *hmac = DNS_TSIG_HMACSHA1_NAME;
439 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
440 *hmac = DNS_TSIG_HMACSHA1_NAME;
441 result = isc_parse_uint16(&digestbits, &buf[10], 10);
442 if (result != ISC_R_SUCCESS || digestbits > 160)
443 fatal("digest-bits out of range [0..160]");
444 digestbits = (digestbits +7) & ~0x7U;
445 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
446 *hmac = DNS_TSIG_HMACSHA224_NAME;
447 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
448 *hmac = DNS_TSIG_HMACSHA224_NAME;
449 result = isc_parse_uint16(&digestbits, &buf[12], 10);
450 if (result != ISC_R_SUCCESS || digestbits > 224)
451 fatal("digest-bits out of range [0..224]");
452 digestbits = (digestbits +7) & ~0x7U;
453 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
454 *hmac = DNS_TSIG_HMACSHA256_NAME;
455 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
456 *hmac = DNS_TSIG_HMACSHA256_NAME;
457 result = isc_parse_uint16(&digestbits, &buf[12], 10);
458 if (result != ISC_R_SUCCESS || digestbits > 256)
459 fatal("digest-bits out of range [0..256]");
460 digestbits = (digestbits +7) & ~0x7U;
461 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
462 *hmac = DNS_TSIG_HMACSHA384_NAME;
463 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
464 *hmac = DNS_TSIG_HMACSHA384_NAME;
465 result = isc_parse_uint16(&digestbits, &buf[12], 10);
466 if (result != ISC_R_SUCCESS || digestbits > 384)
467 fatal("digest-bits out of range [0..384]");
468 digestbits = (digestbits +7) & ~0x7U;
469 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
470 *hmac = DNS_TSIG_HMACSHA512_NAME;
471 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
472 *hmac = DNS_TSIG_HMACSHA512_NAME;
473 result = isc_parse_uint16(&digestbits, &buf[12], 10);
474 if (result != ISC_R_SUCCESS || digestbits > 512)
475 fatal("digest-bits out of range [0..512]");
476 digestbits = (digestbits +7) & ~0x7U;
478 fatal("unknown key type '%s'", buf);
484 unsigned char *secret = NULL;
486 isc_buffer_t secretbuf;
488 isc_buffer_t keynamesrc;
491 dns_fixedname_t fkeyname;
494 dns_name_t *hmacname = NULL;
495 isc_uint16_t digestbits = 0;
497 dns_fixedname_init(&fkeyname);
498 keyname = dns_fixedname_name(&fkeyname);
500 debug("Creating key...");
502 s = strchr(keystr, ':');
503 if (s == NULL || s == keystr || s[1] == 0)
504 fatal("key option must specify [hmac:]keyname:secret");
506 n = strchr(secretstr, ':');
508 if (n == secretstr || n[1] == 0)
509 fatal("key option must specify [hmac:]keyname:secret");
512 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
514 hmacname = DNS_TSIG_HMACMD5_NAME;
519 isc_buffer_init(&keynamesrc, name, n - name);
520 isc_buffer_add(&keynamesrc, n - name);
522 debug("namefromtext");
523 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname,
525 check_result(result, "dns_name_fromtext");
527 secretlen = strlen(secretstr) * 3 / 4;
528 secret = isc_mem_allocate(mctx, secretlen);
530 fatal("out of memory");
532 isc_buffer_init(&secretbuf, secret, secretlen);
533 result = isc_base64_decodestring(secretstr, &secretbuf);
534 if (result != ISC_R_SUCCESS) {
535 fprintf(stderr, "could not create key from %s: %s\n",
536 keystr, isc_result_totext(result));
540 secretlen = isc_buffer_usedlength(&secretbuf);
543 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
544 ISC_FALSE, NULL, 0, 0, mctx, NULL,
546 if (result != ISC_R_SUCCESS)
547 fprintf(stderr, "could not create key from %s: %s\n",
548 keystr, dns_result_totext(result));
550 dst_key_setbits(tsigkey->key, digestbits);
553 isc_mem_free(mctx, secret);
557 basenamelen(const char *file) {
558 int len = strlen(file);
560 if (len > 1 && file[len - 1] == '.')
562 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
564 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
570 setup_keyfile(void) {
571 dst_key_t *dstkey = NULL;
573 dns_name_t *hmacname = NULL;
575 debug("Creating key...");
578 dst_key_free(&sig0key);
580 result = dst_key_fromnamedfile(keyfile,
581 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
583 if (result != ISC_R_SUCCESS) {
584 fprintf(stderr, "could not read key from %.*s.{private,key}: "
585 "%s\n", basenamelen(keyfile), keyfile,
586 isc_result_totext(result));
589 switch (dst_key_alg(dstkey)) {
590 case DST_ALG_HMACMD5:
591 hmacname = DNS_TSIG_HMACMD5_NAME;
593 case DST_ALG_HMACSHA1:
594 hmacname = DNS_TSIG_HMACSHA1_NAME;
596 case DST_ALG_HMACSHA224:
597 hmacname = DNS_TSIG_HMACSHA224_NAME;
599 case DST_ALG_HMACSHA256:
600 hmacname = DNS_TSIG_HMACSHA256_NAME;
602 case DST_ALG_HMACSHA384:
603 hmacname = DNS_TSIG_HMACSHA384_NAME;
605 case DST_ALG_HMACSHA512:
606 hmacname = DNS_TSIG_HMACSHA512_NAME;
609 if (hmacname != NULL) {
610 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
611 hmacname, dstkey, ISC_FALSE,
612 NULL, 0, 0, mctx, NULL,
614 dst_key_free(&dstkey);
615 if (result != ISC_R_SUCCESS) {
616 fprintf(stderr, "could not create key from %s: %s\n",
617 keyfile, isc_result_totext(result));
621 dst_key_attach(dstkey, &sig0key);
626 isc_task_detach(&global_task);
628 if (userserver != NULL)
629 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
631 if (localaddr != NULL)
632 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
634 if (tsigkey != NULL) {
635 ddebug("Freeing TSIG key");
636 dns_tsigkey_detach(&tsigkey);
639 if (sig0key != NULL) {
640 ddebug("Freeing SIG(0) key");
641 dst_key_free(&sig0key);
644 if (updatemsg != NULL)
645 dns_message_destroy(&updatemsg);
648 ddebug("Destroy DST lib");
650 is_dst_up = ISC_FALSE;
653 cleanup_entropy(&entropy);
655 lwres_conf_clear(lwctx);
656 lwres_context_destroy(&lwctx);
658 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
660 ddebug("Destroying request manager");
661 dns_requestmgr_detach(&requestmgr);
663 ddebug("Freeing the dispatchers");
665 dns_dispatch_detach(&dispatchv4);
667 dns_dispatch_detach(&dispatchv6);
669 ddebug("Shutting down dispatch manager");
670 dns_dispatchmgr_destroy(&dispatchmgr);
675 maybeshutdown(void) {
676 ddebug("Shutting down request manager");
677 dns_requestmgr_shutdown(requestmgr);
686 shutdown_program(isc_task_t *task, isc_event_t *event) {
687 REQUIRE(task == global_task);
690 ddebug("shutdown_program()");
691 isc_event_free(&event);
693 shuttingdown = ISC_TRUE;
700 isc_sockaddr_t bind_any, bind_any6;
701 lwres_result_t lwresult;
702 unsigned int attrs, attrmask;
704 isc_logconfig_t *logconfig = NULL;
706 ddebug("setup_system()");
708 dns_result_register();
710 result = isc_net_probeipv4();
711 if (result == ISC_R_SUCCESS)
712 have_ipv4 = ISC_TRUE;
714 result = isc_net_probeipv6();
715 if (result == ISC_R_SUCCESS)
716 have_ipv6 = ISC_TRUE;
718 if (!have_ipv4 && !have_ipv6)
719 fatal("could not find either IPv4 or IPv6");
721 result = isc_log_create(mctx, &lctx, &logconfig);
722 check_result(result, "isc_log_create");
724 isc_log_setcontext(lctx);
726 dns_log_setcontext(lctx);
728 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
729 check_result(result, "isc_log_usechannel");
731 isc_log_setdebuglevel(lctx, logdebuglevel);
733 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
734 if (lwresult != LWRES_R_SUCCESS)
735 fatal("lwres_context_create failed");
737 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
738 lwconf = lwres_conf_get(lwctx);
740 ns_total = lwconf->nsnext;
742 /* No name servers in resolv.conf; default to loopback. */
743 struct in_addr localhost;
745 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
747 fatal("out of memory");
748 localhost.s_addr = htonl(INADDR_LOOPBACK);
749 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
751 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
753 fatal("out of memory");
754 for (i = 0; i < ns_total; i++) {
755 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
757 memcpy(&in4, lwconf->nameservers[i].address, 4);
758 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT);
761 memcpy(&in6, lwconf->nameservers[i].address, 16);
762 isc_sockaddr_fromin6(&servers[i], &in6,
768 setup_entropy(mctx, NULL, &entropy);
770 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
771 check_result(result, "isc_hash_create");
774 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
775 check_result(result, "dns_dispatchmgr_create");
777 result = isc_socketmgr_create(mctx, &socketmgr);
778 check_result(result, "dns_socketmgr_create");
780 result = isc_timermgr_create(mctx, &timermgr);
781 check_result(result, "dns_timermgr_create");
783 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
784 check_result(result, "isc_taskmgr_create");
786 result = isc_task_create(taskmgr, 0, &global_task);
787 check_result(result, "isc_task_create");
789 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
790 check_result(result, "isc_task_onshutdown");
792 result = dst_lib_init(mctx, entropy, 0);
793 check_result(result, "dst_lib_init");
794 is_dst_up = ISC_TRUE;
796 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
797 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
800 attrs = DNS_DISPATCHATTR_UDP;
801 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
802 attrs |= DNS_DISPATCHATTR_IPV6;
803 isc_sockaddr_any6(&bind_any6);
804 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
805 &bind_any6, PACKETSIZE,
807 attrs, attrmask, &dispatchv6);
808 check_result(result, "dns_dispatch_getudp (v6)");
812 attrs = DNS_DISPATCHATTR_UDP;
813 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
814 attrs |= DNS_DISPATCHATTR_IPV4;
815 isc_sockaddr_any(&bind_any);
816 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
817 &bind_any, PACKETSIZE,
819 attrs, attrmask, &dispatchv4);
820 check_result(result, "dns_dispatch_getudp (v4)");
823 result = dns_requestmgr_create(mctx, timermgr,
824 socketmgr, taskmgr, dispatchmgr,
825 dispatchv4, dispatchv6, &requestmgr);
826 check_result(result, "dns_requestmgr_create");
830 else if (keyfile != NULL)
835 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
840 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
842 if (result != ISC_R_SUCCESS)
843 fatal("couldn't get address for '%s': %s",
844 host, isc_result_totext(result));
848 #define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
851 pre_parse_args(int argc, char **argv) {
854 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
856 case 'M': /* was -dm */
857 debugging = ISC_TRUE;
858 ddebugging = ISC_TRUE;
859 memdebugging = ISC_TRUE;
860 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
865 if (isc_commandline_option != '?')
866 fprintf(stderr, "%s: invalid argument -%c\n",
867 argv[0], isc_commandline_option);
868 fprintf(stderr, "usage: nsupdate [-d] "
869 "[-g | -o | -y keyname:secret | -k keyfile] "
870 "[-v] [filename]\n");
877 isc_commandline_reset = ISC_TRUE;
878 isc_commandline_index = 1;
882 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
888 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
891 debugging = ISC_TRUE;
893 case 'D': /* was -dd */
894 debugging = ISC_TRUE;
895 ddebugging = ISC_TRUE;
900 result = isc_parse_uint32(&i, isc_commandline_argument,
902 if (result != ISC_R_SUCCESS) {
903 fprintf(stderr, "bad library debug value "
904 "'%s'\n", isc_commandline_argument);
910 keystr = isc_commandline_argument;
916 keyfile = isc_commandline_argument;
919 usegsstsig = ISC_TRUE;
920 use_win2k_gsstsig = ISC_FALSE;
923 usegsstsig = ISC_TRUE;
924 use_win2k_gsstsig = ISC_TRUE;
927 result = isc_parse_uint32(&timeout,
928 isc_commandline_argument, 10);
929 if (result != ISC_R_SUCCESS) {
930 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
937 result = isc_parse_uint32(&udp_timeout,
938 isc_commandline_argument, 10);
939 if (result != ISC_R_SUCCESS) {
940 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
943 if (udp_timeout == 0)
944 udp_timeout = UINT_MAX;
947 result = isc_parse_uint32(&udp_retries,
948 isc_commandline_argument, 10);
949 if (result != ISC_R_SUCCESS) {
950 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
956 setup_entropy(mctx, isc_commandline_argument, ectx);
960 fprintf(stderr, "%s: unhandled option: %c\n",
961 argv[0], isc_commandline_option);
965 if (keyfile != NULL && keystr != NULL) {
966 fprintf(stderr, "%s: cannot specify both -k and -y\n",
972 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
973 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
979 fprintf(stderr, "%s: cannot specify -g or -o, " \
980 "program not linked with GSS API Library\n",
986 if (argv[isc_commandline_index] != NULL) {
987 if (strcmp(argv[isc_commandline_index], "-") == 0) {
990 result = isc_stdio_open(argv[isc_commandline_index],
992 if (result != ISC_R_SUCCESS) {
993 fprintf(stderr, "could not open '%s': %s\n",
994 argv[isc_commandline_index],
995 isc_result_totext(result));
999 interactive = ISC_FALSE;
1004 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1005 isc_result_t result;
1007 isc_buffer_t *namebuf = NULL;
1008 isc_buffer_t source;
1010 word = nsu_strsep(cmdlinep, " \t\r\n");
1012 fprintf(stderr, "could not read owner name\n");
1013 return (STATUS_SYNTAX);
1016 result = dns_message_gettempname(msg, namep);
1017 check_result(result, "dns_message_gettempname");
1018 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
1019 check_result(result, "isc_buffer_allocate");
1020 dns_name_init(*namep, NULL);
1021 dns_name_setbuffer(*namep, namebuf);
1022 dns_message_takebuffer(msg, &namebuf);
1023 isc_buffer_init(&source, word, strlen(word));
1024 isc_buffer_add(&source, strlen(word));
1025 result = dns_name_fromtext(*namep, &source, dns_rootname,
1027 check_result(result, "dns_name_fromtext");
1028 isc_buffer_invalidate(&source);
1029 return (STATUS_MORE);
1033 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1034 dns_rdatatype_t rdatatype, dns_message_t *msg,
1037 char *cmdline = *cmdlinep;
1038 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1040 isc_lex_t *lex = NULL;
1041 dns_rdatacallbacks_t callbacks;
1042 isc_result_t result;
1044 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1047 if (*cmdline != 0) {
1048 dns_rdatacallbacks_init(&callbacks);
1049 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1050 check_result(result, "isc_lex_create");
1051 isc_buffer_init(&source, cmdline, strlen(cmdline));
1052 isc_buffer_add(&source, strlen(cmdline));
1053 result = isc_lex_openbuffer(lex, &source);
1054 check_result(result, "isc_lex_openbuffer");
1055 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1056 check_result(result, "isc_buffer_allocate");
1057 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1058 dns_rootname, 0, mctx, buf,
1060 isc_lex_destroy(&lex);
1061 if (result == ISC_R_SUCCESS) {
1062 isc_buffer_usedregion(buf, &r);
1063 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1064 check_result(result, "isc_buffer_allocate");
1065 isc_buffer_putmem(newbuf, r.base, r.length);
1066 isc_buffer_usedregion(newbuf, &r);
1067 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1068 isc_buffer_free(&buf);
1069 dns_message_takebuffer(msg, &newbuf);
1071 fprintf(stderr, "invalid rdata format: %s\n",
1072 isc_result_totext(result));
1073 isc_buffer_free(&buf);
1074 return (STATUS_SYNTAX);
1077 rdata->flags = DNS_RDATA_UPDATE;
1079 *cmdlinep = cmdline;
1080 return (STATUS_MORE);
1084 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1085 isc_result_t result;
1087 dns_name_t *name = NULL;
1088 isc_textregion_t region;
1089 dns_rdataset_t *rdataset = NULL;
1090 dns_rdatalist_t *rdatalist = NULL;
1091 dns_rdataclass_t rdataclass;
1092 dns_rdatatype_t rdatatype;
1093 dns_rdata_t *rdata = NULL;
1094 isc_uint16_t retval;
1096 ddebug("make_prereq()");
1099 * Read the owner name
1101 retval = parse_name(&cmdline, updatemsg, &name);
1102 if (retval != STATUS_MORE)
1106 * If this is an rrset prereq, read the class or type.
1109 word = nsu_strsep(&cmdline, " \t\r\n");
1111 fprintf(stderr, "could not read class or type\n");
1115 region.length = strlen(word);
1116 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1117 if (result == ISC_R_SUCCESS) {
1118 if (!setzoneclass(rdataclass)) {
1119 fprintf(stderr, "class mismatch: %s\n", word);
1123 * Now read the type.
1125 word = nsu_strsep(&cmdline, " \t\r\n");
1127 fprintf(stderr, "could not read type\n");
1131 region.length = strlen(word);
1132 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1133 if (result != ISC_R_SUCCESS) {
1134 fprintf(stderr, "invalid type: %s\n", word);
1138 rdataclass = getzoneclass();
1139 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1140 if (result != ISC_R_SUCCESS) {
1141 fprintf(stderr, "invalid type: %s\n", word);
1146 rdatatype = dns_rdatatype_any;
1148 result = dns_message_gettemprdata(updatemsg, &rdata);
1149 check_result(result, "dns_message_gettemprdata");
1151 dns_rdata_init(rdata);
1153 if (isrrset && ispositive) {
1154 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1156 if (retval != STATUS_MORE)
1159 rdata->flags = DNS_RDATA_UPDATE;
1161 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1162 check_result(result, "dns_message_gettemprdatalist");
1163 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1164 check_result(result, "dns_message_gettemprdataset");
1165 dns_rdatalist_init(rdatalist);
1166 rdatalist->type = rdatatype;
1168 if (isrrset && rdata->data != NULL)
1169 rdatalist->rdclass = rdataclass;
1171 rdatalist->rdclass = dns_rdataclass_any;
1173 rdatalist->rdclass = dns_rdataclass_none;
1174 rdatalist->covers = 0;
1176 rdata->rdclass = rdatalist->rdclass;
1177 rdata->type = rdatatype;
1178 ISC_LIST_INIT(rdatalist->rdata);
1179 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1180 dns_rdataset_init(rdataset);
1181 dns_rdatalist_tordataset(rdatalist, rdataset);
1182 ISC_LIST_INIT(name->list);
1183 ISC_LIST_APPEND(name->list, rdataset, link);
1184 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1185 return (STATUS_MORE);
1189 dns_message_puttempname(updatemsg, &name);
1190 return (STATUS_SYNTAX);
1194 evaluate_prereq(char *cmdline) {
1196 isc_boolean_t ispositive, isrrset;
1198 ddebug("evaluate_prereq()");
1199 word = nsu_strsep(&cmdline, " \t\r\n");
1201 fprintf(stderr, "could not read operation code\n");
1202 return (STATUS_SYNTAX);
1204 if (strcasecmp(word, "nxdomain") == 0) {
1205 ispositive = ISC_FALSE;
1206 isrrset = ISC_FALSE;
1207 } else if (strcasecmp(word, "yxdomain") == 0) {
1208 ispositive = ISC_TRUE;
1209 isrrset = ISC_FALSE;
1210 } else if (strcasecmp(word, "nxrrset") == 0) {
1211 ispositive = ISC_FALSE;
1213 } else if (strcasecmp(word, "yxrrset") == 0) {
1214 ispositive = ISC_TRUE;
1217 fprintf(stderr, "incorrect operation code: %s\n", word);
1218 return (STATUS_SYNTAX);
1220 return (make_prereq(cmdline, ispositive, isrrset));
1224 evaluate_server(char *cmdline) {
1225 char *word, *server;
1228 word = nsu_strsep(&cmdline, " \t\r\n");
1230 fprintf(stderr, "could not read server name\n");
1231 return (STATUS_SYNTAX);
1235 word = nsu_strsep(&cmdline, " \t\r\n");
1237 port = DNSDEFAULTPORT;
1240 port = strtol(word, &endp, 10);
1242 fprintf(stderr, "port '%s' is not numeric\n", word);
1243 return (STATUS_SYNTAX);
1244 } else if (port < 1 || port > 65535) {
1245 fprintf(stderr, "port '%s' is out of range "
1246 "(1 to 65535)\n", word);
1247 return (STATUS_SYNTAX);
1251 if (userserver == NULL) {
1252 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1253 if (userserver == NULL)
1254 fatal("out of memory");
1257 get_address(server, (in_port_t)port, userserver);
1259 return (STATUS_MORE);
1263 evaluate_local(char *cmdline) {
1267 struct in6_addr in6;
1269 word = nsu_strsep(&cmdline, " \t\r\n");
1271 fprintf(stderr, "could not read server name\n");
1272 return (STATUS_SYNTAX);
1276 word = nsu_strsep(&cmdline, " \t\r\n");
1281 port = strtol(word, &endp, 10);
1283 fprintf(stderr, "port '%s' is not numeric\n", word);
1284 return (STATUS_SYNTAX);
1285 } else if (port < 1 || port > 65535) {
1286 fprintf(stderr, "port '%s' is out of range "
1287 "(1 to 65535)\n", word);
1288 return (STATUS_SYNTAX);
1292 if (localaddr == NULL) {
1293 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1294 if (localaddr == NULL)
1295 fatal("out of memory");
1298 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1299 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1300 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1301 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1303 fprintf(stderr, "invalid address %s", local);
1304 return (STATUS_SYNTAX);
1307 return (STATUS_MORE);
1311 evaluate_key(char *cmdline) {
1315 isc_result_t result;
1316 dns_fixedname_t fkeyname;
1317 dns_name_t *keyname;
1319 unsigned char *secret = NULL;
1320 isc_buffer_t secretbuf;
1321 dns_name_t *hmacname = NULL;
1322 isc_uint16_t digestbits = 0;
1325 namestr = nsu_strsep(&cmdline, " \t\r\n");
1326 if (*namestr == 0) {
1327 fprintf(stderr, "could not read key name\n");
1328 return (STATUS_SYNTAX);
1331 dns_fixedname_init(&fkeyname);
1332 keyname = dns_fixedname_name(&fkeyname);
1334 n = strchr(namestr, ':');
1336 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1339 hmacname = DNS_TSIG_HMACMD5_NAME;
1341 isc_buffer_init(&b, namestr, strlen(namestr));
1342 isc_buffer_add(&b, strlen(namestr));
1343 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
1344 if (result != ISC_R_SUCCESS) {
1345 fprintf(stderr, "could not parse key name\n");
1346 return (STATUS_SYNTAX);
1349 secretstr = nsu_strsep(&cmdline, "\r\n");
1350 if (*secretstr == 0) {
1351 fprintf(stderr, "could not read key secret\n");
1352 return (STATUS_SYNTAX);
1354 secretlen = strlen(secretstr) * 3 / 4;
1355 secret = isc_mem_allocate(mctx, secretlen);
1357 fatal("out of memory");
1359 isc_buffer_init(&secretbuf, secret, secretlen);
1360 result = isc_base64_decodestring(secretstr, &secretbuf);
1361 if (result != ISC_R_SUCCESS) {
1362 fprintf(stderr, "could not create key from %s: %s\n",
1363 secretstr, isc_result_totext(result));
1364 isc_mem_free(mctx, secret);
1365 return (STATUS_SYNTAX);
1367 secretlen = isc_buffer_usedlength(&secretbuf);
1369 if (tsigkey != NULL)
1370 dns_tsigkey_detach(&tsigkey);
1371 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1372 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1374 isc_mem_free(mctx, secret);
1375 if (result != ISC_R_SUCCESS) {
1376 fprintf(stderr, "could not create key from %s %s: %s\n",
1377 namestr, secretstr, dns_result_totext(result));
1378 return (STATUS_SYNTAX);
1380 dst_key_setbits(tsigkey->key, digestbits);
1381 return (STATUS_MORE);
1385 evaluate_zone(char *cmdline) {
1388 isc_result_t result;
1390 word = nsu_strsep(&cmdline, " \t\r\n");
1392 fprintf(stderr, "could not read zone name\n");
1393 return (STATUS_SYNTAX);
1396 dns_fixedname_init(&fuserzone);
1397 userzone = dns_fixedname_name(&fuserzone);
1398 isc_buffer_init(&b, word, strlen(word));
1399 isc_buffer_add(&b, strlen(word));
1400 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE,
1402 if (result != ISC_R_SUCCESS) {
1403 userzone = NULL; /* Lest it point to an invalid name */
1404 fprintf(stderr, "could not parse zone name\n");
1405 return (STATUS_SYNTAX);
1408 return (STATUS_MORE);
1412 evaluate_realm(char *cmdline) {
1417 word = nsu_strsep(&cmdline, " \t\r\n");
1420 isc_mem_free(mctx, realm);
1422 return (STATUS_MORE);
1425 snprintf(buf, sizeof(buf), "@%s", word);
1426 realm = isc_mem_strdup(mctx, buf);
1428 fatal("out of memory");
1429 return (STATUS_MORE);
1432 return (STATUS_SYNTAX);
1437 evaluate_ttl(char *cmdline) {
1439 isc_result_t result;
1442 word = nsu_strsep(&cmdline, " \t\r\n");
1444 fprintf(stderr, "could not ttl\n");
1445 return (STATUS_SYNTAX);
1448 if (!strcasecmp(word, "none")) {
1450 default_ttl_set = ISC_FALSE;
1451 return (STATUS_MORE);
1454 result = isc_parse_uint32(&ttl, word, 10);
1455 if (result != ISC_R_SUCCESS)
1456 return (STATUS_SYNTAX);
1458 if (ttl > TTL_MAX) {
1459 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1461 return (STATUS_SYNTAX);
1464 default_ttl_set = ISC_TRUE;
1466 return (STATUS_MORE);
1470 evaluate_class(char *cmdline) {
1473 isc_result_t result;
1474 dns_rdataclass_t rdclass;
1476 word = nsu_strsep(&cmdline, " \t\r\n");
1478 fprintf(stderr, "could not read class name\n");
1479 return (STATUS_SYNTAX);
1483 r.length = strlen(word);
1484 result = dns_rdataclass_fromtext(&rdclass, &r);
1485 if (result != ISC_R_SUCCESS) {
1486 fprintf(stderr, "could not parse class name: %s\n", word);
1487 return (STATUS_SYNTAX);
1490 case dns_rdataclass_none:
1491 case dns_rdataclass_any:
1492 case dns_rdataclass_reserved0:
1493 fprintf(stderr, "bad default class: %s\n", word);
1494 return (STATUS_SYNTAX);
1496 defaultclass = rdclass;
1499 return (STATUS_MORE);
1503 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1504 isc_result_t result;
1505 dns_name_t *name = NULL;
1508 dns_rdataclass_t rdataclass;
1509 dns_rdatatype_t rdatatype;
1510 dns_rdata_t *rdata = NULL;
1511 dns_rdatalist_t *rdatalist = NULL;
1512 dns_rdataset_t *rdataset = NULL;
1513 isc_textregion_t region;
1514 isc_uint16_t retval;
1516 ddebug("update_addordelete()");
1519 * Read the owner name.
1521 retval = parse_name(&cmdline, updatemsg, &name);
1522 if (retval != STATUS_MORE)
1525 result = dns_message_gettemprdata(updatemsg, &rdata);
1526 check_result(result, "dns_message_gettemprdata");
1528 dns_rdata_init(rdata);
1531 * If this is an add, read the TTL and verify that it's in range.
1532 * If it's a delete, ignore a TTL if present (for compatibility).
1534 word = nsu_strsep(&cmdline, " \t\r\n");
1537 fprintf(stderr, "could not read owner ttl\n");
1542 rdataclass = dns_rdataclass_any;
1543 rdatatype = dns_rdatatype_any;
1544 rdata->flags = DNS_RDATA_UPDATE;
1548 result = isc_parse_uint32(&ttl, word, 10);
1549 if (result != ISC_R_SUCCESS) {
1553 } else if (default_ttl_set) {
1557 fprintf(stderr, "ttl '%s': %s\n", word,
1558 isc_result_totext(result));
1565 else if (ttl > TTL_MAX) {
1566 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1572 * Read the class or type.
1574 word = nsu_strsep(&cmdline, " \t\r\n");
1578 rdataclass = dns_rdataclass_any;
1579 rdatatype = dns_rdatatype_any;
1580 rdata->flags = DNS_RDATA_UPDATE;
1583 fprintf(stderr, "could not read class or type\n");
1588 region.length = strlen(word);
1589 rdataclass = dns_rdataclass_any;
1590 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1591 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1592 if (!setzoneclass(rdataclass)) {
1593 fprintf(stderr, "class mismatch: %s\n", word);
1597 * Now read the type.
1599 word = nsu_strsep(&cmdline, " \t\r\n");
1602 rdataclass = dns_rdataclass_any;
1603 rdatatype = dns_rdatatype_any;
1604 rdata->flags = DNS_RDATA_UPDATE;
1607 fprintf(stderr, "could not read type\n");
1612 region.length = strlen(word);
1613 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1614 if (result != ISC_R_SUCCESS) {
1615 fprintf(stderr, "'%s' is not a valid type: %s\n",
1616 word, isc_result_totext(result));
1620 rdataclass = getzoneclass();
1621 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1622 if (result != ISC_R_SUCCESS) {
1623 fprintf(stderr, "'%s' is not a valid class or type: "
1624 "%s\n", word, isc_result_totext(result));
1629 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1631 if (retval != STATUS_MORE)
1635 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1636 rdataclass = dns_rdataclass_any;
1638 rdataclass = dns_rdataclass_none;
1640 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1641 fprintf(stderr, "could not read rdata\n");
1648 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1649 check_result(result, "dns_message_gettemprdatalist");
1650 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1651 check_result(result, "dns_message_gettemprdataset");
1652 dns_rdatalist_init(rdatalist);
1653 rdatalist->type = rdatatype;
1654 rdatalist->rdclass = rdataclass;
1655 rdatalist->covers = rdatatype;
1656 rdatalist->ttl = (dns_ttl_t)ttl;
1657 ISC_LIST_INIT(rdatalist->rdata);
1658 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1659 dns_rdataset_init(rdataset);
1660 dns_rdatalist_tordataset(rdatalist, rdataset);
1661 ISC_LIST_INIT(name->list);
1662 ISC_LIST_APPEND(name->list, rdataset, link);
1663 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1664 return (STATUS_MORE);
1668 dns_message_puttempname(updatemsg, &name);
1669 dns_message_puttemprdata(updatemsg, &rdata);
1670 return (STATUS_SYNTAX);
1674 evaluate_update(char *cmdline) {
1676 isc_boolean_t isdelete;
1678 ddebug("evaluate_update()");
1679 word = nsu_strsep(&cmdline, " \t\r\n");
1681 fprintf(stderr, "could not read operation code\n");
1682 return (STATUS_SYNTAX);
1684 if (strcasecmp(word, "delete") == 0)
1685 isdelete = ISC_TRUE;
1686 else if (strcasecmp(word, "add") == 0)
1687 isdelete = ISC_FALSE;
1689 fprintf(stderr, "incorrect operation code: %s\n", word);
1690 return (STATUS_SYNTAX);
1692 return (update_addordelete(cmdline, isdelete));
1696 setzone(dns_name_t *zonename) {
1697 isc_result_t result;
1698 dns_name_t *name = NULL;
1699 dns_rdataset_t *rdataset = NULL;
1701 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1702 if (result == ISC_R_SUCCESS) {
1703 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1704 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1705 for (rdataset = ISC_LIST_HEAD(name->list);
1707 rdataset = ISC_LIST_HEAD(name->list)) {
1708 ISC_LIST_UNLINK(name->list, rdataset, link);
1709 dns_rdataset_disassociate(rdataset);
1710 dns_message_puttemprdataset(updatemsg, &rdataset);
1712 dns_message_puttempname(updatemsg, &name);
1715 if (zonename != NULL) {
1716 result = dns_message_gettempname(updatemsg, &name);
1717 check_result(result, "dns_message_gettempname");
1718 dns_name_init(name, NULL);
1719 dns_name_clone(zonename, name);
1720 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1721 check_result(result, "dns_message_gettemprdataset");
1722 dns_rdataset_makequestion(rdataset, getzoneclass(),
1724 ISC_LIST_INIT(name->list);
1725 ISC_LIST_APPEND(name->list, rdataset, link);
1726 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1731 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1732 isc_result_t result;
1733 isc_buffer_t *buf = NULL;
1736 ddebug("show_message()");
1742 if (bufsz > MAXTEXT) {
1743 fprintf(stderr, "could not allocate large enough "
1744 "buffer to display message\n");
1748 isc_buffer_free(&buf);
1749 result = isc_buffer_allocate(mctx, &buf, bufsz);
1750 check_result(result, "isc_buffer_allocate");
1751 result = dns_message_totext(msg, style, 0, buf);
1753 } while (result == ISC_R_NOSPACE);
1754 if (result != ISC_R_SUCCESS) {
1755 fprintf(stderr, "could not convert message to text format.\n");
1756 isc_buffer_free(&buf);
1759 fprintf(stream, "%s\n%.*s", description,
1760 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1761 isc_buffer_free(&buf);
1766 get_next_command(void) {
1767 char cmdlinebuf[MAXCMD];
1771 ddebug("get_next_command()");
1773 fprintf(stdout, "> ");
1777 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1779 if (cmdline == NULL)
1780 return (STATUS_QUIT);
1781 word = nsu_strsep(&cmdline, " \t\r\n");
1784 return (STATUS_QUIT);
1786 return (STATUS_SEND);
1788 return (STATUS_MORE);
1789 if (strcasecmp(word, "quit") == 0)
1790 return (STATUS_QUIT);
1791 if (strcasecmp(word, "prereq") == 0)
1792 return (evaluate_prereq(cmdline));
1793 if (strcasecmp(word, "update") == 0)
1794 return (evaluate_update(cmdline));
1795 if (strcasecmp(word, "server") == 0)
1796 return (evaluate_server(cmdline));
1797 if (strcasecmp(word, "local") == 0)
1798 return (evaluate_local(cmdline));
1799 if (strcasecmp(word, "zone") == 0)
1800 return (evaluate_zone(cmdline));
1801 if (strcasecmp(word, "class") == 0)
1802 return (evaluate_class(cmdline));
1803 if (strcasecmp(word, "send") == 0)
1804 return (STATUS_SEND);
1805 if (strcasecmp(word, "debug") == 0) {
1807 ddebugging = ISC_TRUE;
1809 debugging = ISC_TRUE;
1810 return (STATUS_MORE);
1812 if (strcasecmp(word, "ttl") == 0)
1813 return (evaluate_ttl(cmdline));
1814 if (strcasecmp(word, "show") == 0) {
1815 show_message(stdout, updatemsg, "Outgoing update query:");
1816 return (STATUS_MORE);
1818 if (strcasecmp(word, "answer") == 0) {
1820 show_message(stdout, answer, "Answer:");
1821 return (STATUS_MORE);
1823 if (strcasecmp(word, "key") == 0) {
1824 usegsstsig = ISC_FALSE;
1825 return (evaluate_key(cmdline));
1827 if (strcasecmp(word, "realm") == 0)
1828 return (evaluate_realm(cmdline));
1829 if (strcasecmp(word, "gsstsig") == 0) {
1831 usegsstsig = ISC_TRUE;
1832 use_win2k_gsstsig = ISC_FALSE;
1834 fprintf(stderr, "gsstsig not supported\n");
1836 return (STATUS_MORE);
1838 if (strcasecmp(word, "oldgsstsig") == 0) {
1840 usegsstsig = ISC_TRUE;
1841 use_win2k_gsstsig = ISC_TRUE;
1843 fprintf(stderr, "gsstsig not supported\n");
1845 return (STATUS_MORE);
1847 if (strcasecmp(word, "help") == 0) {
1849 "local address [port] (set local resolver)\n"
1850 "server address [port] (set master server for zone)\n"
1851 "send (send the update request)\n"
1852 "show (show the update request)\n"
1853 "answer (show the answer to the last request)\n"
1854 "quit (quit, any pending update is not sent\n"
1855 "help (display this message_\n"
1856 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1857 "gsstsig (use GSS_TSIG to sign the request)\n"
1858 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1859 "zone name (set the zone to be updated)\n"
1860 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1861 "prereq nxdomain name (does this name not exist)\n"
1862 "prereq yxdomain name (does this name exist)\n"
1863 "prereq nxrrset .... (does this RRset exist)\n"
1864 "prereq yxrrset .... (does this RRset not exist)\n"
1865 "update add .... (add the given record to the zone)\n"
1866 "update delete .... (remove the given record(s) from the zone)\n");
1867 return (STATUS_MORE);
1869 fprintf(stderr, "incorrect section name: %s\n", word);
1870 return (STATUS_SYNTAX);
1873 static isc_boolean_t
1874 user_interaction(void) {
1875 isc_uint16_t result = STATUS_MORE;
1877 ddebug("user_interaction()");
1878 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
1879 result = get_next_command();
1880 if (!interactive && result == STATUS_SYNTAX)
1881 fatal("syntax error");
1883 if (result == STATUS_SEND)
1891 isc_event_t *event = global_event;
1892 ddebug("done_update()");
1893 isc_task_send(global_task, &event);
1897 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
1898 isc_result_t result;
1899 dns_rdata_t rdata = DNS_RDATA_INIT;
1900 dns_rdata_any_tsig_t tsig;
1902 result = dns_rdataset_first(rdataset);
1903 check_result(result, "dns_rdataset_first");
1904 dns_rdataset_current(rdataset, &rdata);
1905 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
1906 check_result(result, "dns_rdata_tostruct");
1907 if (tsig.error != 0) {
1908 if (isc_buffer_remaininglength(b) < 1)
1909 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1910 isc__buffer_putstr(b, "(" /*)*/);
1911 result = dns_tsigrcode_totext(tsig.error, b);
1912 check_result(result, "dns_tsigrcode_totext");
1913 if (isc_buffer_remaininglength(b) < 1)
1914 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1915 isc__buffer_putstr(b, /*(*/ ")");
1920 update_completed(isc_task_t *task, isc_event_t *event) {
1921 dns_requestevent_t *reqev = NULL;
1922 isc_result_t result;
1923 dns_request_t *request;
1927 ddebug("update_completed()");
1931 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1932 reqev = (dns_requestevent_t *)event;
1933 request = reqev->request;
1936 dns_request_destroy(&request);
1937 isc_event_free(&event);
1942 if (reqev->result != ISC_R_SUCCESS) {
1943 fprintf(stderr, "; Communication with server failed: %s\n",
1944 isc_result_totext(reqev->result));
1945 seenerror = ISC_TRUE;
1949 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
1950 check_result(result, "dns_message_create");
1951 result = dns_request_getresponse(request, answer,
1952 DNS_MESSAGEPARSE_PRESERVEORDER);
1955 if (answer->verify_attempted)
1956 ddebug("tsig verification successful");
1958 case DNS_R_CLOCKSKEW:
1959 case DNS_R_EXPECTEDTSIG:
1960 case DNS_R_TSIGERRORSET:
1961 case DNS_R_TSIGVERIFYFAILURE:
1962 case DNS_R_UNEXPECTEDTSIG:
1965 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
1967 * For MS DNS that violates RFC 2845, section 4.2
1972 fprintf(stderr, "; TSIG error with server: %s\n",
1973 isc_result_totext(result));
1974 seenerror = ISC_TRUE;
1977 check_result(result, "dns_request_getresponse");
1980 if (answer->rcode != dns_rcode_noerror) {
1981 seenerror = ISC_TRUE;
1985 dns_rdataset_t *rds;
1987 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1988 result = dns_rcode_totext(answer->rcode, &b);
1989 check_result(result, "dns_rcode_totext");
1990 rds = dns_message_gettsig(answer, NULL);
1992 check_tsig_error(rds, &b);
1993 fprintf(stderr, "update failed: %.*s\n",
1994 (int)isc_buffer_usedlength(&b), buf);
1998 show_message(stderr, answer, "\nReply from update query:");
2001 dns_request_destroy(&request);
2003 dns_name_free(&tmpzonename, mctx);
2004 dns_name_free(&restart_master, mctx);
2006 isc_event_free(&event);
2011 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2012 isc_sockaddr_t *srcaddr)
2014 isc_result_t result;
2015 dns_request_t *request = NULL;
2016 unsigned int options = 0;
2018 ddebug("send_update()");
2023 options |= DNS_REQUESTOPT_TCP;
2024 if (tsigkey == NULL && sig0key != NULL) {
2025 result = dns_message_setsig0key(updatemsg, sig0key);
2026 check_result(result, "dns_message_setsig0key");
2029 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2031 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2032 fprintf(stderr, "Sending update to %s\n", addrbuf);
2035 /* Windows doesn't like the tsig name to be compressed. */
2036 if (updatemsg->tsigname)
2037 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2039 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2040 master, options, tsigkey, timeout,
2041 udp_timeout, udp_retries, global_task,
2042 update_completed, NULL, &request);
2043 check_result(result, "dns_request_createvia3");
2046 show_message(stdout, updatemsg, "Outgoing update query:");
2052 recvsoa(isc_task_t *task, isc_event_t *event) {
2053 dns_requestevent_t *reqev = NULL;
2054 dns_request_t *request = NULL;
2055 isc_result_t result, eresult;
2056 dns_message_t *rcvmsg = NULL;
2057 dns_section_t section;
2058 dns_name_t *name = NULL;
2059 dns_rdataset_t *soaset = NULL;
2060 dns_rdata_soa_t soa;
2061 dns_rdata_t soarr = DNS_RDATA_INIT;
2064 nsu_requestinfo_t *reqinfo;
2065 dns_message_t *soaquery = NULL;
2066 isc_sockaddr_t *addr;
2067 isc_boolean_t seencname = ISC_FALSE;
2069 unsigned int nlabels;
2073 ddebug("recvsoa()");
2077 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2078 reqev = (dns_requestevent_t *)event;
2079 request = reqev->request;
2080 eresult = reqev->result;
2081 reqinfo = reqev->ev_arg;
2082 soaquery = reqinfo->msg;
2083 addr = reqinfo->addr;
2086 dns_request_destroy(&request);
2087 dns_message_destroy(&soaquery);
2088 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2089 isc_event_free(&event);
2094 if (eresult != ISC_R_SUCCESS) {
2095 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2097 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2098 fprintf(stderr, "; Communication with %s failed: %s\n",
2099 addrbuf, isc_result_totext(eresult));
2100 if (userserver != NULL)
2101 fatal("could not talk to specified name server");
2102 else if (++ns_inuse >= lwconf->nsnext)
2103 fatal("could not talk to any default name server");
2104 ddebug("Destroying request [%p]", request);
2105 dns_request_destroy(&request);
2106 dns_message_renderreset(soaquery);
2107 dns_message_settsigkey(soaquery, NULL);
2108 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2109 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2110 isc_event_free(&event);
2111 setzoneclass(dns_rdataclass_none);
2115 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2117 isc_event_free(&event);
2120 ddebug("About to create rcvmsg");
2121 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2122 check_result(result, "dns_message_create");
2123 result = dns_request_getresponse(request, rcvmsg,
2124 DNS_MESSAGEPARSE_PRESERVEORDER);
2125 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2126 dns_message_destroy(&rcvmsg);
2127 ddebug("Destroying request [%p]", request);
2128 dns_request_destroy(&request);
2129 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2130 if (reqinfo == NULL)
2131 fatal("out of memory");
2132 reqinfo->msg = soaquery;
2133 reqinfo->addr = addr;
2134 dns_message_renderreset(soaquery);
2135 ddebug("retrying soa request without TSIG");
2136 result = dns_request_createvia3(requestmgr, soaquery,
2137 localaddr, addr, 0, NULL,
2140 global_task, recvsoa, reqinfo,
2142 check_result(result, "dns_request_createvia");
2146 check_result(result, "dns_request_getresponse");
2147 section = DNS_SECTION_ANSWER;
2149 show_message(stderr, rcvmsg, "Reply from SOA query:");
2151 if (rcvmsg->rcode != dns_rcode_noerror &&
2152 rcvmsg->rcode != dns_rcode_nxdomain)
2153 fatal("response to SOA query was unsuccessful");
2155 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2156 char namebuf[DNS_NAME_FORMATSIZE];
2157 dns_name_format(userzone, namebuf, sizeof(namebuf));
2158 error("specified zone '%s' does not exist (NXDOMAIN)",
2160 dns_message_destroy(&rcvmsg);
2161 dns_request_destroy(&request);
2162 dns_message_destroy(&soaquery);
2163 ddebug("Out of recvsoa");
2170 section = DNS_SECTION_ANSWER;
2172 section = DNS_SECTION_AUTHORITY;
2176 result = dns_message_firstname(rcvmsg, section);
2177 if (result != ISC_R_SUCCESS) {
2181 while (result == ISC_R_SUCCESS) {
2183 dns_message_currentname(rcvmsg, section, &name);
2185 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2187 if (result == ISC_R_SUCCESS)
2189 if (section == DNS_SECTION_ANSWER) {
2190 dns_rdataset_t *tset = NULL;
2191 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2192 &tset) == ISC_R_SUCCESS ||
2193 dns_message_findtype(name, dns_rdatatype_dname, 0,
2194 &tset) == ISC_R_SUCCESS ) {
2195 seencname = ISC_TRUE;
2200 result = dns_message_nextname(rcvmsg, section);
2203 if (soaset == NULL && !seencname) {
2212 char namestr[DNS_NAME_FORMATSIZE];
2213 dns_name_format(name, namestr, sizeof(namestr));
2214 fprintf(stderr, "Found zone name: %s\n", namestr);
2217 result = dns_rdataset_first(soaset);
2218 check_result(result, "dns_rdataset_first");
2220 dns_rdata_init(&soarr);
2221 dns_rdataset_current(soaset, &soarr);
2222 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2223 check_result(result, "dns_rdata_tostruct");
2225 dns_name_init(&master, NULL);
2226 dns_name_clone(&soa.origin, &master);
2228 if (userzone != NULL)
2229 zonename = userzone;
2234 char namestr[DNS_NAME_FORMATSIZE];
2235 dns_name_format(&master, namestr, sizeof(namestr));
2236 fprintf(stderr, "The master is: %s\n", namestr);
2239 if (userserver != NULL)
2240 serveraddr = userserver;
2242 char serverstr[DNS_NAME_MAXTEXT+1];
2245 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2246 result = dns_name_totext(&master, ISC_TRUE, &buf);
2247 check_result(result, "dns_name_totext");
2248 serverstr[isc_buffer_usedlength(&buf)] = 0;
2249 get_address(serverstr, DNSDEFAULTPORT, &tempaddr);
2250 serveraddr = &tempaddr;
2252 dns_rdata_freestruct(&soa);
2256 dns_name_init(&tmpzonename, NULL);
2257 dns_name_dup(zonename, mctx, &tmpzonename);
2258 dns_name_init(&restart_master, NULL);
2259 dns_name_dup(&master, mctx, &restart_master);
2260 start_gssrequest(&master);
2262 send_update(zonename, serveraddr, localaddr);
2263 setzoneclass(dns_rdataclass_none);
2266 send_update(zonename, serveraddr, localaddr);
2267 setzoneclass(dns_rdataclass_none);
2270 dns_message_destroy(&soaquery);
2271 dns_request_destroy(&request);
2274 dns_message_destroy(&rcvmsg);
2275 ddebug("Out of recvsoa");
2279 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2280 INSIST(result == ISC_R_SUCCESS);
2282 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2283 nlabels = dns_name_countlabels(name);
2285 fatal("could not find enclosing zone");
2286 dns_name_init(&tname, NULL);
2287 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2288 dns_name_clone(&tname, name);
2289 dns_request_destroy(&request);
2290 dns_message_renderreset(soaquery);
2291 dns_message_settsigkey(soaquery, NULL);
2292 if (userserver != NULL)
2293 sendrequest(localaddr, userserver, soaquery, &request);
2295 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2300 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2301 dns_message_t *msg, dns_request_t **request)
2303 isc_result_t result;
2304 nsu_requestinfo_t *reqinfo;
2306 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2307 if (reqinfo == NULL)
2308 fatal("out of memory");
2310 reqinfo->addr = destaddr;
2311 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2312 (userserver != NULL) ? tsigkey : NULL,
2313 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2314 global_task, recvsoa, reqinfo, request);
2315 check_result(result, "dns_request_createvia");
2321 start_gssrequest(dns_name_t *master)
2323 gss_ctx_id_t context;
2325 isc_result_t result;
2326 isc_uint32_t val = 0;
2327 dns_message_t *rmsg;
2328 dns_request_t *request = NULL;
2329 dns_name_t *servname;
2330 dns_fixedname_t fname;
2331 char namestr[DNS_NAME_FORMATSIZE];
2332 char keystr[DNS_NAME_FORMATSIZE];
2334 debug("start_gssrequest");
2337 if (gssring != NULL)
2338 dns_tsigkeyring_destroy(&gssring);
2340 result = dns_tsigkeyring_create(mctx, &gssring);
2342 if (result != ISC_R_SUCCESS)
2343 fatal("dns_tsigkeyring_create failed: %s",
2344 isc_result_totext(result));
2346 dns_name_format(master, namestr, sizeof(namestr));
2347 if (kserver == NULL) {
2348 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2349 if (kserver == NULL)
2350 fatal("out of memory");
2352 if (userserver == NULL)
2353 get_address(namestr, DNSDEFAULTPORT, kserver);
2355 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2357 dns_fixedname_init(&fname);
2358 servname = dns_fixedname_name(&fname);
2360 result = isc_string_printf(servicename, sizeof(servicename),
2361 "DNS/%s%s", namestr, realm ? realm : "");
2362 if (result != ISC_R_SUCCESS)
2363 fatal("isc_string_printf(servicename) failed: %s",
2364 isc_result_totext(result));
2365 isc_buffer_init(&buf, servicename, strlen(servicename));
2366 isc_buffer_add(&buf, strlen(servicename));
2367 result = dns_name_fromtext(servname, &buf, dns_rootname,
2369 if (result != ISC_R_SUCCESS)
2370 fatal("dns_name_fromtext(servname) failed: %s",
2371 isc_result_totext(result));
2373 dns_fixedname_init(&fkname);
2374 keyname = dns_fixedname_name(&fkname);
2376 isc_random_get(&val);
2377 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2379 if (result != ISC_R_SUCCESS)
2380 fatal("isc_string_printf(keystr) failed: %s",
2381 isc_result_totext(result));
2382 isc_buffer_init(&buf, keystr, strlen(keystr));
2383 isc_buffer_add(&buf, strlen(keystr));
2385 result = dns_name_fromtext(keyname, &buf, dns_rootname,
2387 if (result != ISC_R_SUCCESS)
2388 fatal("dns_name_fromtext(keyname) failed: %s",
2389 isc_result_totext(result));
2391 /* Windows doesn't recognize name compression in the key name. */
2392 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2395 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2396 if (result != ISC_R_SUCCESS)
2397 fatal("dns_message_create failed: %s",
2398 isc_result_totext(result));
2400 /* Build first request. */
2401 context = GSS_C_NO_CONTEXT;
2402 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2403 &context, use_win2k_gsstsig);
2404 if (result == ISC_R_FAILURE)
2405 fatal("Check your Kerberos ticket, it may have expired.");
2406 if (result != ISC_R_SUCCESS)
2407 fatal("dns_tkey_buildgssquery failed: %s",
2408 isc_result_totext(result));
2410 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2414 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2415 dns_message_t *msg, dns_request_t **request,
2416 gss_ctx_id_t context)
2418 isc_result_t result;
2419 nsu_gssinfo_t *reqinfo;
2420 unsigned int options = 0;
2422 debug("send_gssrequest");
2423 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2424 if (reqinfo == NULL)
2425 fatal("out of memory");
2427 reqinfo->addr = destaddr;
2428 reqinfo->context = context;
2430 options |= DNS_REQUESTOPT_TCP;
2431 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2432 options, tsigkey, FIND_TIMEOUT * 20,
2433 FIND_TIMEOUT, 3, global_task, recvgss,
2435 check_result(result, "dns_request_createvia3");
2437 show_message(stdout, msg, "Outgoing update query:");
2442 recvgss(isc_task_t *task, isc_event_t *event) {
2443 dns_requestevent_t *reqev = NULL;
2444 dns_request_t *request = NULL;
2445 isc_result_t result, eresult;
2446 dns_message_t *rcvmsg = NULL;
2447 nsu_gssinfo_t *reqinfo;
2448 dns_message_t *tsigquery = NULL;
2449 isc_sockaddr_t *addr;
2450 gss_ctx_id_t context;
2452 dns_name_t *servname;
2453 dns_fixedname_t fname;
2457 ddebug("recvgss()");
2461 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2462 reqev = (dns_requestevent_t *)event;
2463 request = reqev->request;
2464 eresult = reqev->result;
2465 reqinfo = reqev->ev_arg;
2466 tsigquery = reqinfo->msg;
2467 context = reqinfo->context;
2468 addr = reqinfo->addr;
2471 dns_request_destroy(&request);
2472 dns_message_destroy(&tsigquery);
2473 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2474 isc_event_free(&event);
2479 if (eresult != ISC_R_SUCCESS) {
2480 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2482 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2483 fprintf(stderr, "; Communication with %s failed: %s\n",
2484 addrbuf, isc_result_totext(eresult));
2485 if (userserver != NULL)
2486 fatal("could not talk to specified name server");
2487 else if (++ns_inuse >= lwconf->nsnext)
2488 fatal("could not talk to any default name server");
2489 ddebug("Destroying request [%p]", request);
2490 dns_request_destroy(&request);
2491 dns_message_renderreset(tsigquery);
2492 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2494 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2495 isc_event_free(&event);
2498 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2500 isc_event_free(&event);
2503 ddebug("recvgss creating rcvmsg");
2504 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2505 check_result(result, "dns_message_create");
2507 result = dns_request_getresponse(request, rcvmsg,
2508 DNS_MESSAGEPARSE_PRESERVEORDER);
2509 check_result(result, "dns_request_getresponse");
2512 show_message(stderr, rcvmsg,
2513 "recvmsg reply from GSS-TSIG query");
2515 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2516 ddebug("recvgss trying %s GSS-TSIG",
2517 use_win2k_gsstsig ? "Standard" : "Win2k");
2518 if (use_win2k_gsstsig)
2519 use_win2k_gsstsig = ISC_FALSE;
2521 use_win2k_gsstsig = ISC_TRUE;
2522 tried_other_gsstsig = ISC_TRUE;
2523 start_gssrequest(&restart_master);
2527 if (rcvmsg->rcode != dns_rcode_noerror &&
2528 rcvmsg->rcode != dns_rcode_nxdomain)
2529 fatal("response to GSS-TSIG query was unsuccessful");
2532 dns_fixedname_init(&fname);
2533 servname = dns_fixedname_name(&fname);
2534 isc_buffer_init(&buf, servicename, strlen(servicename));
2535 isc_buffer_add(&buf, strlen(servicename));
2536 result = dns_name_fromtext(servname, &buf, dns_rootname,
2538 check_result(result, "dns_name_fromtext");
2541 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2542 &context, &tsigkey, gssring,
2546 case DNS_R_CONTINUE:
2547 send_gssrequest(localaddr, kserver, tsigquery, &request,
2553 * XXXSRA Waaay too much fun here. There's no good
2554 * reason why we need a TSIG here (the people who put
2555 * it into the spec admitted at the time that it was
2556 * not a security issue), and Windows clients don't
2557 * seem to work if named complies with the spec and
2558 * includes the gratuitous TSIG. So we're in the
2559 * bizarre situation of having to choose between
2560 * complying with a useless requirement in the spec
2561 * and interoperating. This is nuts. If we can
2562 * confirm this behavior, we should ask the WG to
2563 * consider removing the requirement for the
2564 * gratuitous TSIG here. For the moment, we ignore
2565 * the TSIG -- this too is a spec violation, but it's
2566 * the least insane thing to do.
2570 * Verify the signature.
2572 rcvmsg->state = DNS_SECTION_ANY;
2573 dns_message_setquerytsig(rcvmsg, NULL);
2574 result = dns_message_settsigkey(rcvmsg, tsigkey);
2575 check_result(result, "dns_message_settsigkey");
2576 result = dns_message_checksig(rcvmsg, NULL);
2577 ddebug("tsig verification: %s", dns_result_totext(result));
2578 check_result(result, "dns_message_checksig");
2581 send_update(&tmpzonename, serveraddr, localaddr);
2582 setzoneclass(dns_rdataclass_none);
2586 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
2590 dns_request_destroy(&request);
2591 dns_message_destroy(&tsigquery);
2593 dns_message_destroy(&rcvmsg);
2594 ddebug("Out of recvgss");
2599 start_update(void) {
2600 isc_result_t result;
2601 dns_rdataset_t *rdataset = NULL;
2602 dns_name_t *name = NULL;
2603 dns_request_t *request = NULL;
2604 dns_message_t *soaquery = NULL;
2605 dns_name_t *firstname;
2606 dns_section_t section = DNS_SECTION_UPDATE;
2608 ddebug("start_update()");
2611 dns_message_destroy(&answer);
2613 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2614 send_update(userzone, userserver, localaddr);
2615 setzoneclass(dns_rdataclass_none);
2619 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2621 check_result(result, "dns_message_create");
2623 if (userserver == NULL)
2624 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2626 result = dns_message_gettempname(soaquery, &name);
2627 check_result(result, "dns_message_gettempname");
2629 result = dns_message_gettemprdataset(soaquery, &rdataset);
2630 check_result(result, "dns_message_gettemprdataset");
2632 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2634 if (userzone != NULL) {
2635 dns_name_init(name, NULL);
2636 dns_name_clone(userzone, name);
2638 dns_rdataset_t *tmprdataset;
2639 result = dns_message_firstname(updatemsg, section);
2640 if (result == ISC_R_NOMORE) {
2641 section = DNS_SECTION_PREREQUISITE;
2642 result = dns_message_firstname(updatemsg, section);
2644 if (result != ISC_R_SUCCESS) {
2645 dns_message_puttempname(soaquery, &name);
2646 dns_rdataset_disassociate(rdataset);
2647 dns_message_puttemprdataset(soaquery, &rdataset);
2648 dns_message_destroy(&soaquery);
2653 dns_message_currentname(updatemsg, section, &firstname);
2654 dns_name_init(name, NULL);
2655 dns_name_clone(firstname, name);
2657 * Looks to see if the first name references a DS record
2658 * and if that name is not the root remove a label as DS
2659 * records live in the parent zone so we need to start our
2660 * search one label up.
2662 tmprdataset = ISC_LIST_HEAD(firstname->list);
2663 if (section == DNS_SECTION_UPDATE &&
2664 !dns_name_equal(firstname, dns_rootname) &&
2665 tmprdataset->type == dns_rdatatype_ds) {
2666 unsigned int labels = dns_name_countlabels(name);
2667 dns_name_getlabelsequence(name, 1, labels - 1, name);
2671 ISC_LIST_INIT(name->list);
2672 ISC_LIST_APPEND(name->list, rdataset, link);
2673 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2675 if (userserver != NULL)
2676 sendrequest(localaddr, userserver, soaquery, &request);
2679 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2685 ddebug("cleanup()");
2688 dns_message_destroy(&answer);
2691 if (tsigkey != NULL) {
2692 ddebug("detach tsigkey x%p", tsigkey);
2693 dns_tsigkey_detach(&tsigkey);
2695 if (gssring != NULL) {
2696 ddebug("Destroying GSS-TSIG keyring");
2697 dns_tsigkeyring_destroy(&gssring);
2699 if (kserver != NULL) {
2700 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2703 if (realm != NULL) {
2704 isc_mem_free(mctx, realm);
2709 ddebug("Shutting down task manager");
2710 isc_taskmgr_destroy(&taskmgr);
2712 ddebug("Destroying event");
2713 isc_event_free(&global_event);
2715 ddebug("Shutting down socket manager");
2716 isc_socketmgr_destroy(&socketmgr);
2718 ddebug("Shutting down timer manager");
2719 isc_timermgr_destroy(&timermgr);
2721 ddebug("Destroying hash context");
2724 ddebug("Destroying name state");
2727 ddebug("Removing log context");
2728 isc_log_destroy(&lctx);
2730 ddebug("Destroying memory context");
2732 isc_mem_stats(mctx, stderr);
2733 isc_mem_destroy(&mctx);
2737 getinput(isc_task_t *task, isc_event_t *event) {
2747 if (global_event == NULL)
2748 global_event = event;
2751 more = user_interaction();
2761 main(int argc, char **argv) {
2762 isc_result_t result;
2763 style = &dns_master_style_debug;
2767 interactive = ISC_TF(isatty(0));
2771 pre_parse_args(argc, argv);
2773 result = isc_mem_create(0, 0, &mctx);
2774 check_result(result, "isc_mem_create");
2776 parse_args(argc, argv, mctx, &entropy);
2780 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2781 check_result(result, "isc_app_onrun");
2783 (void)isc_app_run();