2 * Copyright (C) 2004-2009 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.3 2009/04/30 07:12:49 marka 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/random.h>
42 #include <isc/region.h>
43 #include <isc/sockaddr.h>
44 #include <isc/socket.h>
45 #include <isc/stdio.h>
46 #include <isc/string.h>
48 #include <isc/timer.h>
49 #include <isc/types.h>
52 #include <dns/callbacks.h>
53 #include <dns/dispatch.h>
54 #include <dns/dnssec.h>
55 #include <dns/events.h>
56 #include <dns/fixedname.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
61 #include <dns/rcode.h>
62 #include <dns/rdata.h>
63 #include <dns/rdataclass.h>
64 #include <dns/rdatalist.h>
65 #include <dns/rdataset.h>
66 #include <dns/rdatastruct.h>
67 #include <dns/rdatatype.h>
68 #include <dns/request.h>
69 #include <dns/result.h>
75 #include <lwres/lwres.h>
76 #include <lwres/net.h>
79 #include <dst/gssapi.h>
81 #include <bind9/getaddresses.h>
85 #ifdef HAVE_GETADDRINFO
86 #ifdef HAVE_GAISTRERROR
87 #define USE_GETADDRINFO
92 #ifndef USE_GETADDRINFO
93 #ifndef ISC_PLATFORM_NONSTDHERRNO
98 #define MAXCMD (4 * 1024)
99 #define MAXWIRE (64 * 1024)
100 #define PACKETSIZE ((64 * 1024) - 1)
101 #define INITTEXT (2 * 1024)
102 #define MAXTEXT (128 * 1024)
103 #define FIND_TIMEOUT 5
104 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
106 #define DNSDEFAULTPORT 53
109 #define RESOLV_CONF "/etc/resolv.conf"
112 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
113 static isc_boolean_t memdebugging = ISC_FALSE;
114 static isc_boolean_t have_ipv4 = ISC_FALSE;
115 static isc_boolean_t have_ipv6 = ISC_FALSE;
116 static isc_boolean_t is_dst_up = ISC_FALSE;
117 static isc_boolean_t usevc = ISC_FALSE;
118 static isc_boolean_t usegsstsig = ISC_FALSE;
119 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
120 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
121 static isc_taskmgr_t *taskmgr = NULL;
122 static isc_task_t *global_task = NULL;
123 static isc_event_t *global_event = NULL;
124 static isc_log_t *lctx = NULL;
125 static isc_mem_t *mctx = NULL;
126 static dns_dispatchmgr_t *dispatchmgr = NULL;
127 static dns_requestmgr_t *requestmgr = NULL;
128 static isc_socketmgr_t *socketmgr = NULL;
129 static isc_timermgr_t *timermgr = NULL;
130 static dns_dispatch_t *dispatchv4 = NULL;
131 static dns_dispatch_t *dispatchv6 = NULL;
132 static dns_message_t *updatemsg = NULL;
133 static dns_fixedname_t fuserzone;
134 static dns_name_t *userzone = NULL;
135 static dns_name_t *zonename = NULL;
136 static dns_name_t tmpzonename;
137 static dns_name_t restart_master;
138 static dns_tsig_keyring_t *gssring = NULL;
139 static dns_tsigkey_t *tsigkey = NULL;
140 static dst_key_t *sig0key;
141 static lwres_context_t *lwctx = NULL;
142 static lwres_conf_t *lwconf;
143 static isc_sockaddr_t *servers;
144 static int ns_inuse = 0;
145 static int ns_total = 0;
146 static isc_sockaddr_t *userserver = NULL;
147 static isc_sockaddr_t *localaddr = NULL;
148 static isc_sockaddr_t *serveraddr = NULL;
149 static isc_sockaddr_t tempaddr;
150 static char *keystr = NULL, *keyfile = NULL;
151 static isc_entropy_t *entropy = NULL;
152 static isc_boolean_t shuttingdown = ISC_FALSE;
154 static isc_boolean_t interactive = ISC_TRUE;
155 static isc_boolean_t seenerror = ISC_FALSE;
156 static const dns_master_style_t *style;
157 static int requests = 0;
158 static unsigned int logdebuglevel = 0;
159 static unsigned int timeout = 300;
160 static unsigned int udp_timeout = 3;
161 static unsigned int udp_retries = 3;
162 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
163 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
164 static dns_message_t *answer = NULL;
165 static isc_uint32_t default_ttl = 0;
166 static isc_boolean_t default_ttl_set = ISC_FALSE;
168 typedef struct nsu_requestinfo {
170 isc_sockaddr_t *addr;
174 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
175 dns_message_t *msg, dns_request_t **request);
177 fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
180 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
183 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
186 static dns_fixedname_t fkname;
187 static isc_sockaddr_t *kserver = NULL;
188 static char servicename[DNS_NAME_FORMATSIZE];
189 static dns_name_t *keyname;
190 typedef struct nsu_gssinfo {
192 isc_sockaddr_t *addr;
193 gss_ctx_id_t context;
197 start_gssrequest(dns_name_t *master);
199 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
200 dns_message_t *msg, dns_request_t **request,
201 gss_ctx_id_t context);
203 recvgss(isc_task_t *task, isc_event_t *event);
207 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
209 #define STATUS_MORE (isc_uint16_t)0
210 #define STATUS_SEND (isc_uint16_t)1
211 #define STATUS_QUIT (isc_uint16_t)2
212 #define STATUS_SYNTAX (isc_uint16_t)3
214 typedef struct entropysource entropysource_t;
216 struct entropysource {
217 isc_entropysource_t *source;
219 ISC_LINK(entropysource_t) link;
222 static ISC_LIST(entropysource_t) sources;
225 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
228 isc_entropysource_t *source = NULL;
229 entropysource_t *elt;
230 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
232 REQUIRE(ectx != NULL);
235 result = isc_entropy_create(mctx, ectx);
236 if (result != ISC_R_SUCCESS)
237 fatal("could not create entropy object");
238 ISC_LIST_INIT(sources);
241 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
242 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
246 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
249 if (result != ISC_R_SUCCESS)
250 fatal("could not initialize entropy source: %s",
251 isc_result_totext(result));
253 if (source != NULL) {
254 elt = isc_mem_get(mctx, sizeof(*elt));
256 fatal("out of memory");
257 elt->source = source;
259 ISC_LINK_INIT(elt, link);
260 ISC_LIST_APPEND(sources, elt, link);
265 cleanup_entropy(isc_entropy_t **ectx) {
266 entropysource_t *source;
267 while (!ISC_LIST_EMPTY(sources)) {
268 source = ISC_LIST_HEAD(sources);
269 ISC_LIST_UNLINK(sources, source, link);
270 isc_entropy_destroysource(&source->source);
271 isc_mem_put(source->mctx, source, sizeof(*source));
273 isc_entropy_detach(ectx);
277 static dns_rdataclass_t
279 if (zoneclass == dns_rdataclass_none)
280 zoneclass = defaultclass;
285 setzoneclass(dns_rdataclass_t rdclass) {
286 if (zoneclass == dns_rdataclass_none ||
287 rdclass == dns_rdataclass_none)
289 if (zoneclass != rdclass)
295 fatal(const char *format, ...) {
298 va_start(args, format);
299 vfprintf(stderr, format, args);
301 fprintf(stderr, "\n");
306 error(const char *format, ...) {
309 va_start(args, format);
310 vfprintf(stderr, format, args);
312 fprintf(stderr, "\n");
316 debug(const char *format, ...) {
320 va_start(args, format);
321 vfprintf(stderr, format, args);
323 fprintf(stderr, "\n");
328 ddebug(const char *format, ...) {
332 va_start(args, format);
333 vfprintf(stderr, format, args);
335 fprintf(stderr, "\n");
340 check_result(isc_result_t result, const char *msg) {
341 if (result != ISC_R_SUCCESS)
342 fatal("%s: %s", msg, isc_result_totext(result));
346 mem_alloc(void *arg, size_t size) {
347 return (isc_mem_get(arg, size));
351 mem_free(void *arg, void *mem, size_t size) {
352 isc_mem_put(arg, mem, size);
356 nsu_strsep(char **stringp, const char *delim) {
357 char *string = *stringp;
365 for (; *string != '\0'; string++) {
367 for (d = delim; (dc = *d) != '\0'; d++) {
375 for (s = string; *s != '\0'; s++) {
377 for (d = delim; (dc = *d) != '\0'; d++) {
393 ddebug("reset_system()");
394 /* If the update message is still around, destroy it */
395 if (updatemsg != NULL)
396 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
398 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
400 check_result(result, "dns_message_create");
402 updatemsg->opcode = dns_opcode_update;
405 dns_tsigkey_detach(&tsigkey);
407 dns_tsigkeyring_destroy(&gssring);
408 tried_other_gsstsig = ISC_FALSE;
413 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
414 isc_uint16_t digestbits = 0;
418 REQUIRE(hmac != NULL && *hmac == NULL);
419 REQUIRE(hmacstr != NULL);
421 if (len >= sizeof(buf))
422 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
424 strncpy(buf, hmacstr, len);
427 if (strcasecmp(buf, "hmac-md5") == 0) {
428 *hmac = DNS_TSIG_HMACMD5_NAME;
429 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
430 *hmac = DNS_TSIG_HMACMD5_NAME;
431 result = isc_parse_uint16(&digestbits, &buf[9], 10);
432 if (result != ISC_R_SUCCESS || digestbits > 128)
433 fatal("digest-bits out of range [0..128]");
434 digestbits = (digestbits +7) & ~0x7U;
435 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
436 *hmac = DNS_TSIG_HMACSHA1_NAME;
437 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
438 *hmac = DNS_TSIG_HMACSHA1_NAME;
439 result = isc_parse_uint16(&digestbits, &buf[10], 10);
440 if (result != ISC_R_SUCCESS || digestbits > 160)
441 fatal("digest-bits out of range [0..160]");
442 digestbits = (digestbits +7) & ~0x7U;
443 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
444 *hmac = DNS_TSIG_HMACSHA224_NAME;
445 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
446 *hmac = DNS_TSIG_HMACSHA224_NAME;
447 result = isc_parse_uint16(&digestbits, &buf[12], 10);
448 if (result != ISC_R_SUCCESS || digestbits > 224)
449 fatal("digest-bits out of range [0..224]");
450 digestbits = (digestbits +7) & ~0x7U;
451 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
452 *hmac = DNS_TSIG_HMACSHA256_NAME;
453 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
454 *hmac = DNS_TSIG_HMACSHA256_NAME;
455 result = isc_parse_uint16(&digestbits, &buf[12], 10);
456 if (result != ISC_R_SUCCESS || digestbits > 256)
457 fatal("digest-bits out of range [0..256]");
458 digestbits = (digestbits +7) & ~0x7U;
459 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
460 *hmac = DNS_TSIG_HMACSHA384_NAME;
461 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
462 *hmac = DNS_TSIG_HMACSHA384_NAME;
463 result = isc_parse_uint16(&digestbits, &buf[12], 10);
464 if (result != ISC_R_SUCCESS || digestbits > 384)
465 fatal("digest-bits out of range [0..384]");
466 digestbits = (digestbits +7) & ~0x7U;
467 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
468 *hmac = DNS_TSIG_HMACSHA512_NAME;
469 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
470 *hmac = DNS_TSIG_HMACSHA512_NAME;
471 result = isc_parse_uint16(&digestbits, &buf[12], 10);
472 if (result != ISC_R_SUCCESS || digestbits > 512)
473 fatal("digest-bits out of range [0..512]");
474 digestbits = (digestbits +7) & ~0x7U;
476 fatal("unknown key type '%s'", buf);
482 unsigned char *secret = NULL;
484 isc_buffer_t secretbuf;
486 isc_buffer_t keynamesrc;
489 dns_fixedname_t fkeyname;
492 dns_name_t *hmacname = NULL;
493 isc_uint16_t digestbits = 0;
495 dns_fixedname_init(&fkeyname);
496 keyname = dns_fixedname_name(&fkeyname);
498 debug("Creating key...");
500 s = strchr(keystr, ':');
501 if (s == NULL || s == keystr || s[1] == 0)
502 fatal("key option must specify [hmac:]keyname:secret");
504 n = strchr(secretstr, ':');
506 if (n == secretstr || n[1] == 0)
507 fatal("key option must specify [hmac:]keyname:secret");
510 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
512 hmacname = DNS_TSIG_HMACMD5_NAME;
517 isc_buffer_init(&keynamesrc, name, n - name);
518 isc_buffer_add(&keynamesrc, n - name);
520 debug("namefromtext");
521 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname,
523 check_result(result, "dns_name_fromtext");
525 secretlen = strlen(secretstr) * 3 / 4;
526 secret = isc_mem_allocate(mctx, secretlen);
528 fatal("out of memory");
530 isc_buffer_init(&secretbuf, secret, secretlen);
531 result = isc_base64_decodestring(secretstr, &secretbuf);
532 if (result != ISC_R_SUCCESS) {
533 fprintf(stderr, "could not create key from %s: %s\n",
534 keystr, isc_result_totext(result));
538 secretlen = isc_buffer_usedlength(&secretbuf);
541 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
542 ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey);
543 if (result != ISC_R_SUCCESS)
544 fprintf(stderr, "could not create key from %s: %s\n",
545 keystr, dns_result_totext(result));
547 dst_key_setbits(tsigkey->key, digestbits);
550 isc_mem_free(mctx, secret);
554 setup_keyfile(void) {
555 dst_key_t *dstkey = NULL;
557 dns_name_t *hmacname = NULL;
559 debug("Creating key...");
561 result = dst_key_fromnamedfile(keyfile,
562 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
564 if (result != ISC_R_SUCCESS) {
565 fprintf(stderr, "could not read key from %s: %s\n",
566 keyfile, isc_result_totext(result));
569 switch (dst_key_alg(dstkey)) {
570 case DST_ALG_HMACMD5:
571 hmacname = DNS_TSIG_HMACMD5_NAME;
573 case DST_ALG_HMACSHA1:
574 hmacname = DNS_TSIG_HMACSHA1_NAME;
576 case DST_ALG_HMACSHA224:
577 hmacname = DNS_TSIG_HMACSHA224_NAME;
579 case DST_ALG_HMACSHA256:
580 hmacname = DNS_TSIG_HMACSHA256_NAME;
582 case DST_ALG_HMACSHA384:
583 hmacname = DNS_TSIG_HMACSHA384_NAME;
585 case DST_ALG_HMACSHA512:
586 hmacname = DNS_TSIG_HMACSHA512_NAME;
589 if (hmacname != NULL) {
590 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
591 hmacname, dstkey, ISC_FALSE,
592 NULL, 0, 0, mctx, NULL,
594 if (result != ISC_R_SUCCESS) {
595 fprintf(stderr, "could not create key from %s: %s\n",
596 keyfile, isc_result_totext(result));
597 dst_key_free(&dstkey);
606 isc_task_detach(&global_task);
608 if (userserver != NULL)
609 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
611 if (localaddr != NULL)
612 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
614 if (tsigkey != NULL) {
615 ddebug("Freeing TSIG key");
616 dns_tsigkey_detach(&tsigkey);
619 if (sig0key != NULL) {
620 ddebug("Freeing SIG(0) key");
621 dst_key_free(&sig0key);
624 if (updatemsg != NULL)
625 dns_message_destroy(&updatemsg);
628 ddebug("Destroy DST lib");
630 is_dst_up = ISC_FALSE;
633 cleanup_entropy(&entropy);
635 lwres_conf_clear(lwctx);
636 lwres_context_destroy(&lwctx);
638 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
640 ddebug("Destroying request manager");
641 dns_requestmgr_detach(&requestmgr);
643 ddebug("Freeing the dispatchers");
645 dns_dispatch_detach(&dispatchv4);
647 dns_dispatch_detach(&dispatchv6);
649 ddebug("Shutting down dispatch manager");
650 dns_dispatchmgr_destroy(&dispatchmgr);
655 maybeshutdown(void) {
656 ddebug("Shutting down request manager");
657 dns_requestmgr_shutdown(requestmgr);
666 shutdown_program(isc_task_t *task, isc_event_t *event) {
667 REQUIRE(task == global_task);
670 ddebug("shutdown_program()");
671 isc_event_free(&event);
673 shuttingdown = ISC_TRUE;
680 isc_sockaddr_t bind_any, bind_any6;
681 lwres_result_t lwresult;
682 unsigned int attrs, attrmask;
684 isc_logconfig_t *logconfig = NULL;
686 ddebug("setup_system()");
688 dns_result_register();
690 result = isc_net_probeipv4();
691 if (result == ISC_R_SUCCESS)
692 have_ipv4 = ISC_TRUE;
694 result = isc_net_probeipv6();
695 if (result == ISC_R_SUCCESS)
696 have_ipv6 = ISC_TRUE;
698 if (!have_ipv4 && !have_ipv6)
699 fatal("could not find either IPv4 or IPv6");
701 result = isc_log_create(mctx, &lctx, &logconfig);
702 check_result(result, "isc_log_create");
704 isc_log_setcontext(lctx);
706 dns_log_setcontext(lctx);
708 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
709 check_result(result, "isc_log_usechannel");
711 isc_log_setdebuglevel(lctx, logdebuglevel);
713 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
714 if (lwresult != LWRES_R_SUCCESS)
715 fatal("lwres_context_create failed");
717 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
718 lwconf = lwres_conf_get(lwctx);
720 ns_total = lwconf->nsnext;
722 /* No name servers in resolv.conf; default to loopback. */
723 struct in_addr localhost;
725 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
727 fatal("out of memory");
728 localhost.s_addr = htonl(INADDR_LOOPBACK);
729 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
731 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
733 fatal("out of memory");
734 for (i = 0; i < ns_total; i++) {
735 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
737 memcpy(&in4, lwconf->nameservers[i].address, 4);
738 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT);
741 memcpy(&in6, lwconf->nameservers[i].address, 16);
742 isc_sockaddr_fromin6(&servers[i], &in6,
748 setup_entropy(mctx, NULL, &entropy);
750 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
751 check_result(result, "isc_hash_create");
754 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
755 check_result(result, "dns_dispatchmgr_create");
757 result = isc_socketmgr_create(mctx, &socketmgr);
758 check_result(result, "dns_socketmgr_create");
760 result = isc_timermgr_create(mctx, &timermgr);
761 check_result(result, "dns_timermgr_create");
763 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
764 check_result(result, "isc_taskmgr_create");
766 result = isc_task_create(taskmgr, 0, &global_task);
767 check_result(result, "isc_task_create");
769 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
770 check_result(result, "isc_task_onshutdown");
772 result = dst_lib_init(mctx, entropy, 0);
773 check_result(result, "dst_lib_init");
774 is_dst_up = ISC_TRUE;
776 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
777 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
780 attrs = DNS_DISPATCHATTR_UDP;
781 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
782 attrs |= DNS_DISPATCHATTR_IPV6;
783 isc_sockaddr_any6(&bind_any6);
784 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
785 &bind_any6, PACKETSIZE,
787 attrs, attrmask, &dispatchv6);
788 check_result(result, "dns_dispatch_getudp (v6)");
792 attrs = DNS_DISPATCHATTR_UDP;
793 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
794 attrs |= DNS_DISPATCHATTR_IPV4;
795 isc_sockaddr_any(&bind_any);
796 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
797 &bind_any, PACKETSIZE,
799 attrs, attrmask, &dispatchv4);
800 check_result(result, "dns_dispatch_getudp (v4)");
803 result = dns_requestmgr_create(mctx, timermgr,
804 socketmgr, taskmgr, dispatchmgr,
805 dispatchv4, dispatchv6, &requestmgr);
806 check_result(result, "dns_requestmgr_create");
810 else if (keyfile != NULL)
815 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
820 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
822 if (result != ISC_R_SUCCESS)
823 fatal("couldn't get address for '%s': %s",
824 host, isc_result_totext(result));
828 #define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
831 pre_parse_args(int argc, char **argv) {
834 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
836 case 'M': /* was -dm */
837 debugging = ISC_TRUE;
838 ddebugging = ISC_TRUE;
839 memdebugging = ISC_TRUE;
840 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
845 if (isc_commandline_option != '?')
846 fprintf(stderr, "%s: invalid argument -%c\n",
847 argv[0], isc_commandline_option);
848 fprintf(stderr, "usage: nsupdate [-d] "
849 "[-g | -o | -y keyname:secret | -k keyfile] "
850 "[-v] [filename]\n");
857 isc_commandline_reset = ISC_TRUE;
858 isc_commandline_index = 1;
862 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
868 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
871 debugging = ISC_TRUE;
873 case 'D': /* was -dd */
874 debugging = ISC_TRUE;
875 ddebugging = ISC_TRUE;
880 result = isc_parse_uint32(&i, isc_commandline_argument,
882 if (result != ISC_R_SUCCESS) {
883 fprintf(stderr, "bad library debug value "
884 "'%s'\n", isc_commandline_argument);
890 keystr = isc_commandline_argument;
896 keyfile = isc_commandline_argument;
899 usegsstsig = ISC_TRUE;
900 use_win2k_gsstsig = ISC_FALSE;
903 usegsstsig = ISC_TRUE;
904 use_win2k_gsstsig = ISC_TRUE;
907 result = isc_parse_uint32(&timeout,
908 isc_commandline_argument, 10);
909 if (result != ISC_R_SUCCESS) {
910 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
917 result = isc_parse_uint32(&udp_timeout,
918 isc_commandline_argument, 10);
919 if (result != ISC_R_SUCCESS) {
920 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
923 if (udp_timeout == 0)
924 udp_timeout = UINT_MAX;
927 result = isc_parse_uint32(&udp_retries,
928 isc_commandline_argument, 10);
929 if (result != ISC_R_SUCCESS) {
930 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
936 setup_entropy(mctx, isc_commandline_argument, ectx);
940 fprintf(stderr, "%s: unhandled option: %c\n",
941 argv[0], isc_commandline_option);
945 if (keyfile != NULL && keystr != NULL) {
946 fprintf(stderr, "%s: cannot specify both -k and -y\n",
952 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
953 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
959 fprintf(stderr, "%s: cannot specify -g or -o, " \
960 "program not linked with GSS API Library\n",
966 if (argv[isc_commandline_index] != NULL) {
967 if (strcmp(argv[isc_commandline_index], "-") == 0) {
970 result = isc_stdio_open(argv[isc_commandline_index],
972 if (result != ISC_R_SUCCESS) {
973 fprintf(stderr, "could not open '%s': %s\n",
974 argv[isc_commandline_index],
975 isc_result_totext(result));
979 interactive = ISC_FALSE;
984 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
987 isc_buffer_t *namebuf = NULL;
990 word = nsu_strsep(cmdlinep, " \t\r\n");
992 fprintf(stderr, "could not read owner name\n");
993 return (STATUS_SYNTAX);
996 result = dns_message_gettempname(msg, namep);
997 check_result(result, "dns_message_gettempname");
998 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
999 check_result(result, "isc_buffer_allocate");
1000 dns_name_init(*namep, NULL);
1001 dns_name_setbuffer(*namep, namebuf);
1002 dns_message_takebuffer(msg, &namebuf);
1003 isc_buffer_init(&source, word, strlen(word));
1004 isc_buffer_add(&source, strlen(word));
1005 result = dns_name_fromtext(*namep, &source, dns_rootname,
1007 check_result(result, "dns_name_fromtext");
1008 isc_buffer_invalidate(&source);
1009 return (STATUS_MORE);
1013 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1014 dns_rdatatype_t rdatatype, dns_message_t *msg,
1017 char *cmdline = *cmdlinep;
1018 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1020 isc_lex_t *lex = NULL;
1021 dns_rdatacallbacks_t callbacks;
1022 isc_result_t result;
1024 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1027 if (*cmdline != 0) {
1028 dns_rdatacallbacks_init(&callbacks);
1029 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1030 check_result(result, "isc_lex_create");
1031 isc_buffer_init(&source, cmdline, strlen(cmdline));
1032 isc_buffer_add(&source, strlen(cmdline));
1033 result = isc_lex_openbuffer(lex, &source);
1034 check_result(result, "isc_lex_openbuffer");
1035 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1036 check_result(result, "isc_buffer_allocate");
1037 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1038 dns_rootname, 0, mctx, buf,
1040 isc_lex_destroy(&lex);
1041 if (result == ISC_R_SUCCESS) {
1042 isc_buffer_usedregion(buf, &r);
1043 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1044 check_result(result, "isc_buffer_allocate");
1045 isc_buffer_putmem(newbuf, r.base, r.length);
1046 isc_buffer_usedregion(newbuf, &r);
1047 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1048 isc_buffer_free(&buf);
1049 dns_message_takebuffer(msg, &newbuf);
1051 fprintf(stderr, "invalid rdata format: %s\n",
1052 isc_result_totext(result));
1053 isc_buffer_free(&buf);
1054 return (STATUS_SYNTAX);
1057 rdata->flags = DNS_RDATA_UPDATE;
1059 *cmdlinep = cmdline;
1060 return (STATUS_MORE);
1064 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1065 isc_result_t result;
1067 dns_name_t *name = NULL;
1068 isc_textregion_t region;
1069 dns_rdataset_t *rdataset = NULL;
1070 dns_rdatalist_t *rdatalist = NULL;
1071 dns_rdataclass_t rdataclass;
1072 dns_rdatatype_t rdatatype;
1073 dns_rdata_t *rdata = NULL;
1074 isc_uint16_t retval;
1076 ddebug("make_prereq()");
1079 * Read the owner name
1081 retval = parse_name(&cmdline, updatemsg, &name);
1082 if (retval != STATUS_MORE)
1086 * If this is an rrset prereq, read the class or type.
1089 word = nsu_strsep(&cmdline, " \t\r\n");
1091 fprintf(stderr, "could not read class or type\n");
1095 region.length = strlen(word);
1096 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1097 if (result == ISC_R_SUCCESS) {
1098 if (!setzoneclass(rdataclass)) {
1099 fprintf(stderr, "class mismatch: %s\n", word);
1103 * Now read the type.
1105 word = nsu_strsep(&cmdline, " \t\r\n");
1107 fprintf(stderr, "could not read type\n");
1111 region.length = strlen(word);
1112 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1113 if (result != ISC_R_SUCCESS) {
1114 fprintf(stderr, "invalid type: %s\n", word);
1118 rdataclass = getzoneclass();
1119 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1120 if (result != ISC_R_SUCCESS) {
1121 fprintf(stderr, "invalid type: %s\n", word);
1126 rdatatype = dns_rdatatype_any;
1128 result = dns_message_gettemprdata(updatemsg, &rdata);
1129 check_result(result, "dns_message_gettemprdata");
1131 dns_rdata_init(rdata);
1133 if (isrrset && ispositive) {
1134 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1136 if (retval != STATUS_MORE)
1139 rdata->flags = DNS_RDATA_UPDATE;
1141 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1142 check_result(result, "dns_message_gettemprdatalist");
1143 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1144 check_result(result, "dns_message_gettemprdataset");
1145 dns_rdatalist_init(rdatalist);
1146 rdatalist->type = rdatatype;
1148 if (isrrset && rdata->data != NULL)
1149 rdatalist->rdclass = rdataclass;
1151 rdatalist->rdclass = dns_rdataclass_any;
1153 rdatalist->rdclass = dns_rdataclass_none;
1154 rdatalist->covers = 0;
1156 rdata->rdclass = rdatalist->rdclass;
1157 rdata->type = rdatatype;
1158 ISC_LIST_INIT(rdatalist->rdata);
1159 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1160 dns_rdataset_init(rdataset);
1161 dns_rdatalist_tordataset(rdatalist, rdataset);
1162 ISC_LIST_INIT(name->list);
1163 ISC_LIST_APPEND(name->list, rdataset, link);
1164 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1165 return (STATUS_MORE);
1169 dns_message_puttempname(updatemsg, &name);
1170 return (STATUS_SYNTAX);
1174 evaluate_prereq(char *cmdline) {
1176 isc_boolean_t ispositive, isrrset;
1178 ddebug("evaluate_prereq()");
1179 word = nsu_strsep(&cmdline, " \t\r\n");
1181 fprintf(stderr, "could not read operation code\n");
1182 return (STATUS_SYNTAX);
1184 if (strcasecmp(word, "nxdomain") == 0) {
1185 ispositive = ISC_FALSE;
1186 isrrset = ISC_FALSE;
1187 } else if (strcasecmp(word, "yxdomain") == 0) {
1188 ispositive = ISC_TRUE;
1189 isrrset = ISC_FALSE;
1190 } else if (strcasecmp(word, "nxrrset") == 0) {
1191 ispositive = ISC_FALSE;
1193 } else if (strcasecmp(word, "yxrrset") == 0) {
1194 ispositive = ISC_TRUE;
1197 fprintf(stderr, "incorrect operation code: %s\n", word);
1198 return (STATUS_SYNTAX);
1200 return (make_prereq(cmdline, ispositive, isrrset));
1204 evaluate_server(char *cmdline) {
1205 char *word, *server;
1208 word = nsu_strsep(&cmdline, " \t\r\n");
1210 fprintf(stderr, "could not read server name\n");
1211 return (STATUS_SYNTAX);
1215 word = nsu_strsep(&cmdline, " \t\r\n");
1217 port = DNSDEFAULTPORT;
1220 port = strtol(word, &endp, 10);
1222 fprintf(stderr, "port '%s' is not numeric\n", word);
1223 return (STATUS_SYNTAX);
1224 } else if (port < 1 || port > 65535) {
1225 fprintf(stderr, "port '%s' is out of range "
1226 "(1 to 65535)\n", word);
1227 return (STATUS_SYNTAX);
1231 if (userserver == NULL) {
1232 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1233 if (userserver == NULL)
1234 fatal("out of memory");
1237 get_address(server, (in_port_t)port, userserver);
1239 return (STATUS_MORE);
1243 evaluate_local(char *cmdline) {
1247 struct in6_addr in6;
1249 word = nsu_strsep(&cmdline, " \t\r\n");
1251 fprintf(stderr, "could not read server name\n");
1252 return (STATUS_SYNTAX);
1256 word = nsu_strsep(&cmdline, " \t\r\n");
1261 port = strtol(word, &endp, 10);
1263 fprintf(stderr, "port '%s' is not numeric\n", word);
1264 return (STATUS_SYNTAX);
1265 } else if (port < 1 || port > 65535) {
1266 fprintf(stderr, "port '%s' is out of range "
1267 "(1 to 65535)\n", word);
1268 return (STATUS_SYNTAX);
1272 if (localaddr == NULL) {
1273 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1274 if (localaddr == NULL)
1275 fatal("out of memory");
1278 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1279 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1280 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1281 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1283 fprintf(stderr, "invalid address %s", local);
1284 return (STATUS_SYNTAX);
1287 return (STATUS_MORE);
1291 evaluate_key(char *cmdline) {
1295 isc_result_t result;
1296 dns_fixedname_t fkeyname;
1297 dns_name_t *keyname;
1299 unsigned char *secret = NULL;
1300 isc_buffer_t secretbuf;
1301 dns_name_t *hmacname = NULL;
1302 isc_uint16_t digestbits = 0;
1305 namestr = nsu_strsep(&cmdline, " \t\r\n");
1306 if (*namestr == 0) {
1307 fprintf(stderr, "could not read key name\n");
1308 return (STATUS_SYNTAX);
1311 dns_fixedname_init(&fkeyname);
1312 keyname = dns_fixedname_name(&fkeyname);
1314 n = strchr(namestr, ':');
1316 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1319 hmacname = DNS_TSIG_HMACMD5_NAME;
1321 isc_buffer_init(&b, namestr, strlen(namestr));
1322 isc_buffer_add(&b, strlen(namestr));
1323 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
1324 if (result != ISC_R_SUCCESS) {
1325 fprintf(stderr, "could not parse key name\n");
1326 return (STATUS_SYNTAX);
1329 secretstr = nsu_strsep(&cmdline, "\r\n");
1330 if (*secretstr == 0) {
1331 fprintf(stderr, "could not read key secret\n");
1332 return (STATUS_SYNTAX);
1334 secretlen = strlen(secretstr) * 3 / 4;
1335 secret = isc_mem_allocate(mctx, secretlen);
1337 fatal("out of memory");
1339 isc_buffer_init(&secretbuf, secret, secretlen);
1340 result = isc_base64_decodestring(secretstr, &secretbuf);
1341 if (result != ISC_R_SUCCESS) {
1342 fprintf(stderr, "could not create key from %s: %s\n",
1343 secretstr, isc_result_totext(result));
1344 isc_mem_free(mctx, secret);
1345 return (STATUS_SYNTAX);
1347 secretlen = isc_buffer_usedlength(&secretbuf);
1349 if (tsigkey != NULL)
1350 dns_tsigkey_detach(&tsigkey);
1351 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1352 ISC_TRUE, NULL, 0, 0, mctx, NULL,
1354 isc_mem_free(mctx, secret);
1355 if (result != ISC_R_SUCCESS) {
1356 fprintf(stderr, "could not create key from %s %s: %s\n",
1357 namestr, secretstr, dns_result_totext(result));
1358 return (STATUS_SYNTAX);
1360 dst_key_setbits(tsigkey->key, digestbits);
1361 return (STATUS_MORE);
1365 evaluate_zone(char *cmdline) {
1368 isc_result_t result;
1370 word = nsu_strsep(&cmdline, " \t\r\n");
1372 fprintf(stderr, "could not read zone name\n");
1373 return (STATUS_SYNTAX);
1376 dns_fixedname_init(&fuserzone);
1377 userzone = dns_fixedname_name(&fuserzone);
1378 isc_buffer_init(&b, word, strlen(word));
1379 isc_buffer_add(&b, strlen(word));
1380 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE,
1382 if (result != ISC_R_SUCCESS) {
1383 userzone = NULL; /* Lest it point to an invalid name */
1384 fprintf(stderr, "could not parse zone name\n");
1385 return (STATUS_SYNTAX);
1388 return (STATUS_MORE);
1392 evaluate_ttl(char *cmdline) {
1394 isc_result_t result;
1397 word = nsu_strsep(&cmdline, " \t\r\n");
1399 fprintf(stderr, "could not ttl\n");
1400 return (STATUS_SYNTAX);
1403 if (!strcasecmp(word, "none")) {
1405 default_ttl_set = ISC_FALSE;
1406 return (STATUS_MORE);
1409 result = isc_parse_uint32(&ttl, word, 10);
1410 if (result != ISC_R_SUCCESS)
1411 return (STATUS_SYNTAX);
1413 if (ttl > TTL_MAX) {
1414 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1416 return (STATUS_SYNTAX);
1419 default_ttl_set = ISC_TRUE;
1421 return (STATUS_MORE);
1425 evaluate_class(char *cmdline) {
1428 isc_result_t result;
1429 dns_rdataclass_t rdclass;
1431 word = nsu_strsep(&cmdline, " \t\r\n");
1433 fprintf(stderr, "could not read class name\n");
1434 return (STATUS_SYNTAX);
1438 r.length = strlen(word);
1439 result = dns_rdataclass_fromtext(&rdclass, &r);
1440 if (result != ISC_R_SUCCESS) {
1441 fprintf(stderr, "could not parse class name: %s\n", word);
1442 return (STATUS_SYNTAX);
1445 case dns_rdataclass_none:
1446 case dns_rdataclass_any:
1447 case dns_rdataclass_reserved0:
1448 fprintf(stderr, "bad default class: %s\n", word);
1449 return (STATUS_SYNTAX);
1451 defaultclass = rdclass;
1454 return (STATUS_MORE);
1458 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1459 isc_result_t result;
1460 dns_name_t *name = NULL;
1463 dns_rdataclass_t rdataclass;
1464 dns_rdatatype_t rdatatype;
1465 dns_rdata_t *rdata = NULL;
1466 dns_rdatalist_t *rdatalist = NULL;
1467 dns_rdataset_t *rdataset = NULL;
1468 isc_textregion_t region;
1469 isc_uint16_t retval;
1471 ddebug("update_addordelete()");
1474 * Read the owner name.
1476 retval = parse_name(&cmdline, updatemsg, &name);
1477 if (retval != STATUS_MORE)
1480 result = dns_message_gettemprdata(updatemsg, &rdata);
1481 check_result(result, "dns_message_gettemprdata");
1483 dns_rdata_init(rdata);
1486 * If this is an add, read the TTL and verify that it's in range.
1487 * If it's a delete, ignore a TTL if present (for compatibility).
1489 word = nsu_strsep(&cmdline, " \t\r\n");
1492 fprintf(stderr, "could not read owner ttl\n");
1497 rdataclass = dns_rdataclass_any;
1498 rdatatype = dns_rdatatype_any;
1499 rdata->flags = DNS_RDATA_UPDATE;
1503 result = isc_parse_uint32(&ttl, word, 10);
1504 if (result != ISC_R_SUCCESS) {
1508 } else if (default_ttl_set) {
1512 fprintf(stderr, "ttl '%s': %s\n", word,
1513 isc_result_totext(result));
1520 else if (ttl > TTL_MAX) {
1521 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1527 * Read the class or type.
1529 word = nsu_strsep(&cmdline, " \t\r\n");
1533 rdataclass = dns_rdataclass_any;
1534 rdatatype = dns_rdatatype_any;
1535 rdata->flags = DNS_RDATA_UPDATE;
1538 fprintf(stderr, "could not read class or type\n");
1543 region.length = strlen(word);
1544 rdataclass = dns_rdataclass_any;
1545 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1546 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1547 if (!setzoneclass(rdataclass)) {
1548 fprintf(stderr, "class mismatch: %s\n", word);
1552 * Now read the type.
1554 word = nsu_strsep(&cmdline, " \t\r\n");
1557 rdataclass = dns_rdataclass_any;
1558 rdatatype = dns_rdatatype_any;
1559 rdata->flags = DNS_RDATA_UPDATE;
1562 fprintf(stderr, "could not read type\n");
1567 region.length = strlen(word);
1568 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1569 if (result != ISC_R_SUCCESS) {
1570 fprintf(stderr, "'%s' is not a valid type: %s\n",
1571 word, isc_result_totext(result));
1575 rdataclass = getzoneclass();
1576 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1577 if (result != ISC_R_SUCCESS) {
1578 fprintf(stderr, "'%s' is not a valid class or type: "
1579 "%s\n", word, isc_result_totext(result));
1584 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1586 if (retval != STATUS_MORE)
1590 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1591 rdataclass = dns_rdataclass_any;
1593 rdataclass = dns_rdataclass_none;
1595 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1596 fprintf(stderr, "could not read rdata\n");
1603 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1604 check_result(result, "dns_message_gettemprdatalist");
1605 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1606 check_result(result, "dns_message_gettemprdataset");
1607 dns_rdatalist_init(rdatalist);
1608 rdatalist->type = rdatatype;
1609 rdatalist->rdclass = rdataclass;
1610 rdatalist->covers = rdatatype;
1611 rdatalist->ttl = (dns_ttl_t)ttl;
1612 ISC_LIST_INIT(rdatalist->rdata);
1613 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1614 dns_rdataset_init(rdataset);
1615 dns_rdatalist_tordataset(rdatalist, rdataset);
1616 ISC_LIST_INIT(name->list);
1617 ISC_LIST_APPEND(name->list, rdataset, link);
1618 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1619 return (STATUS_MORE);
1623 dns_message_puttempname(updatemsg, &name);
1624 dns_message_puttemprdata(updatemsg, &rdata);
1625 return (STATUS_SYNTAX);
1629 evaluate_update(char *cmdline) {
1631 isc_boolean_t isdelete;
1633 ddebug("evaluate_update()");
1634 word = nsu_strsep(&cmdline, " \t\r\n");
1636 fprintf(stderr, "could not read operation code\n");
1637 return (STATUS_SYNTAX);
1639 if (strcasecmp(word, "delete") == 0)
1640 isdelete = ISC_TRUE;
1641 else if (strcasecmp(word, "add") == 0)
1642 isdelete = ISC_FALSE;
1644 fprintf(stderr, "incorrect operation code: %s\n", word);
1645 return (STATUS_SYNTAX);
1647 return (update_addordelete(cmdline, isdelete));
1651 setzone(dns_name_t *zonename) {
1652 isc_result_t result;
1653 dns_name_t *name = NULL;
1654 dns_rdataset_t *rdataset = NULL;
1656 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1657 if (result == ISC_R_SUCCESS) {
1658 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1659 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1660 for (rdataset = ISC_LIST_HEAD(name->list);
1662 rdataset = ISC_LIST_HEAD(name->list)) {
1663 ISC_LIST_UNLINK(name->list, rdataset, link);
1664 dns_rdataset_disassociate(rdataset);
1665 dns_message_puttemprdataset(updatemsg, &rdataset);
1667 dns_message_puttempname(updatemsg, &name);
1670 if (zonename != NULL) {
1671 result = dns_message_gettempname(updatemsg, &name);
1672 check_result(result, "dns_message_gettempname");
1673 dns_name_init(name, NULL);
1674 dns_name_clone(zonename, name);
1675 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1676 check_result(result, "dns_message_gettemprdataset");
1677 dns_rdataset_makequestion(rdataset, getzoneclass(),
1679 ISC_LIST_INIT(name->list);
1680 ISC_LIST_APPEND(name->list, rdataset, link);
1681 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1686 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1687 isc_result_t result;
1688 isc_buffer_t *buf = NULL;
1691 ddebug("show_message()");
1697 if (bufsz > MAXTEXT) {
1698 fprintf(stderr, "could not allocate large enough "
1699 "buffer to display message\n");
1703 isc_buffer_free(&buf);
1704 result = isc_buffer_allocate(mctx, &buf, bufsz);
1705 check_result(result, "isc_buffer_allocate");
1706 result = dns_message_totext(msg, style, 0, buf);
1708 } while (result == ISC_R_NOSPACE);
1709 if (result != ISC_R_SUCCESS) {
1710 fprintf(stderr, "could not convert message to text format.\n");
1711 isc_buffer_free(&buf);
1714 fprintf(stream, "%s\n%.*s", description,
1715 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1716 isc_buffer_free(&buf);
1721 get_next_command(void) {
1722 char cmdlinebuf[MAXCMD];
1726 ddebug("get_next_command()");
1728 fprintf(stdout, "> ");
1732 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1734 if (cmdline == NULL)
1735 return (STATUS_QUIT);
1736 word = nsu_strsep(&cmdline, " \t\r\n");
1739 return (STATUS_QUIT);
1741 return (STATUS_SEND);
1743 return (STATUS_MORE);
1744 if (strcasecmp(word, "quit") == 0)
1745 return (STATUS_QUIT);
1746 if (strcasecmp(word, "prereq") == 0)
1747 return (evaluate_prereq(cmdline));
1748 if (strcasecmp(word, "update") == 0)
1749 return (evaluate_update(cmdline));
1750 if (strcasecmp(word, "server") == 0)
1751 return (evaluate_server(cmdline));
1752 if (strcasecmp(word, "local") == 0)
1753 return (evaluate_local(cmdline));
1754 if (strcasecmp(word, "zone") == 0)
1755 return (evaluate_zone(cmdline));
1756 if (strcasecmp(word, "class") == 0)
1757 return (evaluate_class(cmdline));
1758 if (strcasecmp(word, "send") == 0)
1759 return (STATUS_SEND);
1760 if (strcasecmp(word, "debug") == 0) {
1762 ddebugging = ISC_TRUE;
1764 debugging = ISC_TRUE;
1765 return (STATUS_MORE);
1767 if (strcasecmp(word, "ttl") == 0)
1768 return (evaluate_ttl(cmdline));
1769 if (strcasecmp(word, "show") == 0) {
1770 show_message(stdout, updatemsg, "Outgoing update query:");
1771 return (STATUS_MORE);
1773 if (strcasecmp(word, "answer") == 0) {
1775 show_message(stdout, answer, "Answer:");
1776 return (STATUS_MORE);
1778 if (strcasecmp(word, "key") == 0) {
1779 usegsstsig = ISC_FALSE;
1780 return (evaluate_key(cmdline));
1782 if (strcasecmp(word, "gsstsig") == 0) {
1784 usegsstsig = ISC_TRUE;
1785 use_win2k_gsstsig = ISC_FALSE;
1787 fprintf(stderr, "gsstsig not supported\n");
1789 return (STATUS_MORE);
1791 if (strcasecmp(word, "oldgsstsig") == 0) {
1793 usegsstsig = ISC_TRUE;
1794 use_win2k_gsstsig = ISC_TRUE;
1796 fprintf(stderr, "gsstsig not supported\n");
1798 return (STATUS_MORE);
1800 if (strcasecmp(word, "help") == 0) {
1802 "local address [port] (set local resolver)\n"
1803 "server address [port] (set master server for zone)\n"
1804 "send (send the update request)\n"
1805 "show (show the update request)\n"
1806 "answer (show the answer to the last request)\n"
1807 "quit (quit, any pending update is not sent\n"
1808 "help (display this message_\n"
1809 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1810 "gsstsig (use GSS_TSIG to sign the request)\n"
1811 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1812 "zone name (set the zone to be updated)\n"
1813 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1814 "prereq nxdomain name (does this name not exist)\n"
1815 "prereq yxdomain name (does this name exist)\n"
1816 "prereq nxrrset .... (does this RRset exist)\n"
1817 "prereq yxrrset .... (does this RRset not exist)\n"
1818 "update add .... (add the given record to the zone)\n"
1819 "update delete .... (remove the given record(s) from the zone)\n");
1820 return (STATUS_MORE);
1822 fprintf(stderr, "incorrect section name: %s\n", word);
1823 return (STATUS_SYNTAX);
1826 static isc_boolean_t
1827 user_interaction(void) {
1828 isc_uint16_t result = STATUS_MORE;
1830 ddebug("user_interaction()");
1831 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
1832 result = get_next_command();
1833 if (!interactive && result == STATUS_SYNTAX)
1834 fatal("syntax error");
1836 if (result == STATUS_SEND)
1844 isc_event_t *event = global_event;
1845 ddebug("done_update()");
1846 isc_task_send(global_task, &event);
1850 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
1851 isc_result_t result;
1852 dns_rdata_t rdata = DNS_RDATA_INIT;
1853 dns_rdata_any_tsig_t tsig;
1855 result = dns_rdataset_first(rdataset);
1856 check_result(result, "dns_rdataset_first");
1857 dns_rdataset_current(rdataset, &rdata);
1858 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
1859 check_result(result, "dns_rdata_tostruct");
1860 if (tsig.error != 0) {
1861 if (isc_buffer_remaininglength(b) < 1)
1862 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1863 isc__buffer_putstr(b, "(" /*)*/);
1864 result = dns_tsigrcode_totext(tsig.error, b);
1865 check_result(result, "dns_tsigrcode_totext");
1866 if (isc_buffer_remaininglength(b) < 1)
1867 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1868 isc__buffer_putstr(b, /*(*/ ")");
1873 update_completed(isc_task_t *task, isc_event_t *event) {
1874 dns_requestevent_t *reqev = NULL;
1875 isc_result_t result;
1876 dns_request_t *request;
1880 ddebug("update_completed()");
1884 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1885 reqev = (dns_requestevent_t *)event;
1886 request = reqev->request;
1889 dns_request_destroy(&request);
1890 isc_event_free(&event);
1895 if (reqev->result != ISC_R_SUCCESS) {
1896 fprintf(stderr, "; Communication with server failed: %s\n",
1897 isc_result_totext(reqev->result));
1898 seenerror = ISC_TRUE;
1902 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
1903 check_result(result, "dns_message_create");
1904 result = dns_request_getresponse(request, answer,
1905 DNS_MESSAGEPARSE_PRESERVEORDER);
1908 if (answer->verify_attempted)
1909 ddebug("tsig verification successful");
1911 case DNS_R_CLOCKSKEW:
1912 case DNS_R_EXPECTEDTSIG:
1913 case DNS_R_TSIGERRORSET:
1914 case DNS_R_TSIGVERIFYFAILURE:
1915 case DNS_R_UNEXPECTEDTSIG:
1918 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
1920 * For MS DNS that violates RFC 2845, section 4.2
1925 fprintf(stderr, "; TSIG error with server: %s\n",
1926 isc_result_totext(result));
1927 seenerror = ISC_TRUE;
1930 check_result(result, "dns_request_getresponse");
1933 if (answer->rcode != dns_rcode_noerror) {
1934 seenerror = ISC_TRUE;
1938 dns_rdataset_t *rds;
1940 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1941 result = dns_rcode_totext(answer->rcode, &b);
1942 check_result(result, "dns_rcode_totext");
1943 rds = dns_message_gettsig(answer, NULL);
1945 check_tsig_error(rds, &b);
1946 fprintf(stderr, "update failed: %.*s\n",
1947 (int)isc_buffer_usedlength(&b), buf);
1951 show_message(stderr, answer, "\nReply from update query:");
1954 dns_request_destroy(&request);
1956 dns_name_free(&tmpzonename, mctx);
1957 dns_name_free(&restart_master, mctx);
1959 isc_event_free(&event);
1964 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
1965 isc_sockaddr_t *srcaddr)
1967 isc_result_t result;
1968 dns_request_t *request = NULL;
1969 unsigned int options = 0;
1971 ddebug("send_update()");
1976 options |= DNS_REQUESTOPT_TCP;
1977 if (tsigkey == NULL && sig0key != NULL) {
1978 result = dns_message_setsig0key(updatemsg, sig0key);
1979 check_result(result, "dns_message_setsig0key");
1982 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
1984 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
1985 fprintf(stderr, "Sending update to %s\n", addrbuf);
1988 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
1989 master, options, tsigkey, timeout,
1990 udp_timeout, udp_retries, global_task,
1991 update_completed, NULL, &request);
1992 check_result(result, "dns_request_createvia3");
1995 show_message(stdout, updatemsg, "Outgoing update query:");
2001 recvsoa(isc_task_t *task, isc_event_t *event) {
2002 dns_requestevent_t *reqev = NULL;
2003 dns_request_t *request = NULL;
2004 isc_result_t result, eresult;
2005 dns_message_t *rcvmsg = NULL;
2006 dns_section_t section;
2007 dns_name_t *name = NULL;
2008 dns_rdataset_t *soaset = NULL;
2009 dns_rdata_soa_t soa;
2010 dns_rdata_t soarr = DNS_RDATA_INIT;
2013 nsu_requestinfo_t *reqinfo;
2014 dns_message_t *soaquery = NULL;
2015 isc_sockaddr_t *addr;
2016 isc_boolean_t seencname = ISC_FALSE;
2018 unsigned int nlabels;
2022 ddebug("recvsoa()");
2026 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2027 reqev = (dns_requestevent_t *)event;
2028 request = reqev->request;
2029 eresult = reqev->result;
2030 reqinfo = reqev->ev_arg;
2031 soaquery = reqinfo->msg;
2032 addr = reqinfo->addr;
2035 dns_request_destroy(&request);
2036 dns_message_destroy(&soaquery);
2037 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2038 isc_event_free(&event);
2043 if (eresult != ISC_R_SUCCESS) {
2044 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2046 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2047 fprintf(stderr, "; Communication with %s failed: %s\n",
2048 addrbuf, isc_result_totext(eresult));
2049 if (userserver != NULL)
2050 fatal("could not talk to specified name server");
2051 else if (++ns_inuse >= lwconf->nsnext)
2052 fatal("could not talk to any default name server");
2053 ddebug("Destroying request [%p]", request);
2054 dns_request_destroy(&request);
2055 dns_message_renderreset(soaquery);
2056 dns_message_settsigkey(soaquery, NULL);
2057 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2058 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2059 isc_event_free(&event);
2060 setzoneclass(dns_rdataclass_none);
2064 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2066 isc_event_free(&event);
2069 ddebug("About to create rcvmsg");
2070 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2071 check_result(result, "dns_message_create");
2072 result = dns_request_getresponse(request, rcvmsg,
2073 DNS_MESSAGEPARSE_PRESERVEORDER);
2074 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2075 dns_message_destroy(&rcvmsg);
2076 ddebug("Destroying request [%p]", request);
2077 dns_request_destroy(&request);
2078 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2079 if (reqinfo == NULL)
2080 fatal("out of memory");
2081 reqinfo->msg = soaquery;
2082 reqinfo->addr = addr;
2083 dns_message_renderreset(soaquery);
2084 ddebug("retrying soa request without TSIG");
2085 result = dns_request_createvia3(requestmgr, soaquery,
2086 localaddr, addr, 0, NULL,
2089 global_task, recvsoa, reqinfo,
2091 check_result(result, "dns_request_createvia");
2095 check_result(result, "dns_request_getresponse");
2096 section = DNS_SECTION_ANSWER;
2098 show_message(stderr, rcvmsg, "Reply from SOA query:");
2100 if (rcvmsg->rcode != dns_rcode_noerror &&
2101 rcvmsg->rcode != dns_rcode_nxdomain)
2102 fatal("response to SOA query was unsuccessful");
2104 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2105 char namebuf[DNS_NAME_FORMATSIZE];
2106 dns_name_format(userzone, namebuf, sizeof(namebuf));
2107 error("specified zone '%s' does not exist (NXDOMAIN)",
2109 dns_message_destroy(&rcvmsg);
2110 dns_request_destroy(&request);
2111 dns_message_destroy(&soaquery);
2112 ddebug("Out of recvsoa");
2119 section = DNS_SECTION_ANSWER;
2121 section = DNS_SECTION_AUTHORITY;
2125 result = dns_message_firstname(rcvmsg, section);
2126 if (result != ISC_R_SUCCESS) {
2130 while (result == ISC_R_SUCCESS) {
2132 dns_message_currentname(rcvmsg, section, &name);
2134 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2136 if (result == ISC_R_SUCCESS)
2138 if (section == DNS_SECTION_ANSWER) {
2139 dns_rdataset_t *tset = NULL;
2140 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2141 &tset) == ISC_R_SUCCESS ||
2142 dns_message_findtype(name, dns_rdatatype_dname, 0,
2143 &tset) == ISC_R_SUCCESS ) {
2144 seencname = ISC_TRUE;
2149 result = dns_message_nextname(rcvmsg, section);
2152 if (soaset == NULL && !seencname) {
2161 char namestr[DNS_NAME_FORMATSIZE];
2162 dns_name_format(name, namestr, sizeof(namestr));
2163 fprintf(stderr, "Found zone name: %s\n", namestr);
2166 result = dns_rdataset_first(soaset);
2167 check_result(result, "dns_rdataset_first");
2169 dns_rdata_init(&soarr);
2170 dns_rdataset_current(soaset, &soarr);
2171 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2172 check_result(result, "dns_rdata_tostruct");
2174 dns_name_init(&master, NULL);
2175 dns_name_clone(&soa.origin, &master);
2177 if (userzone != NULL)
2178 zonename = userzone;
2183 char namestr[DNS_NAME_FORMATSIZE];
2184 dns_name_format(&master, namestr, sizeof(namestr));
2185 fprintf(stderr, "The master is: %s\n", namestr);
2188 if (userserver != NULL)
2189 serveraddr = userserver;
2191 char serverstr[DNS_NAME_MAXTEXT+1];
2194 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2195 result = dns_name_totext(&master, ISC_TRUE, &buf);
2196 check_result(result, "dns_name_totext");
2197 serverstr[isc_buffer_usedlength(&buf)] = 0;
2198 get_address(serverstr, DNSDEFAULTPORT, &tempaddr);
2199 serveraddr = &tempaddr;
2201 dns_rdata_freestruct(&soa);
2205 dns_name_init(&tmpzonename, NULL);
2206 dns_name_dup(zonename, mctx, &tmpzonename);
2207 dns_name_init(&restart_master, NULL);
2208 dns_name_dup(&master, mctx, &restart_master);
2209 start_gssrequest(&master);
2211 send_update(zonename, serveraddr, localaddr);
2212 setzoneclass(dns_rdataclass_none);
2215 send_update(zonename, serveraddr, localaddr);
2216 setzoneclass(dns_rdataclass_none);
2219 dns_message_destroy(&soaquery);
2220 dns_request_destroy(&request);
2223 dns_message_destroy(&rcvmsg);
2224 ddebug("Out of recvsoa");
2228 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2229 INSIST(result == ISC_R_SUCCESS);
2231 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2232 nlabels = dns_name_countlabels(name);
2234 fatal("could not find enclosing zone");
2235 dns_name_init(&tname, NULL);
2236 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2237 dns_name_clone(&tname, name);
2238 dns_request_destroy(&request);
2239 dns_message_renderreset(soaquery);
2240 dns_message_settsigkey(soaquery, NULL);
2241 if (userserver != NULL)
2242 sendrequest(localaddr, userserver, soaquery, &request);
2244 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2249 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2250 dns_message_t *msg, dns_request_t **request)
2252 isc_result_t result;
2253 nsu_requestinfo_t *reqinfo;
2255 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2256 if (reqinfo == NULL)
2257 fatal("out of memory");
2259 reqinfo->addr = destaddr;
2260 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2261 (userserver != NULL) ? tsigkey : NULL,
2262 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2263 global_task, recvsoa, reqinfo, request);
2264 check_result(result, "dns_request_createvia");
2270 start_gssrequest(dns_name_t *master)
2272 gss_ctx_id_t context;
2274 isc_result_t result;
2275 isc_uint32_t val = 0;
2276 dns_message_t *rmsg;
2277 dns_request_t *request = NULL;
2278 dns_name_t *servname;
2279 dns_fixedname_t fname;
2280 char namestr[DNS_NAME_FORMATSIZE];
2281 char keystr[DNS_NAME_FORMATSIZE];
2283 debug("start_gssrequest");
2286 if (gssring != NULL)
2287 dns_tsigkeyring_destroy(&gssring);
2289 result = dns_tsigkeyring_create(mctx, &gssring);
2291 if (result != ISC_R_SUCCESS)
2292 fatal("dns_tsigkeyring_create failed: %s",
2293 isc_result_totext(result));
2295 dns_name_format(master, namestr, sizeof(namestr));
2296 if (kserver == NULL) {
2297 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2298 if (kserver == NULL)
2299 fatal("out of memory");
2301 if (userserver == NULL)
2302 get_address(namestr, DNSDEFAULTPORT, kserver);
2304 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2306 dns_fixedname_init(&fname);
2307 servname = dns_fixedname_name(&fname);
2309 result = isc_string_printf(servicename, sizeof(servicename),
2311 if (result != ISC_R_SUCCESS)
2312 fatal("isc_string_printf(servicename) failed: %s",
2313 isc_result_totext(result));
2314 isc_buffer_init(&buf, servicename, strlen(servicename));
2315 isc_buffer_add(&buf, strlen(servicename));
2316 result = dns_name_fromtext(servname, &buf, dns_rootname,
2318 if (result != ISC_R_SUCCESS)
2319 fatal("dns_name_fromtext(servname) failed: %s",
2320 isc_result_totext(result));
2322 dns_fixedname_init(&fkname);
2323 keyname = dns_fixedname_name(&fkname);
2325 isc_random_get(&val);
2326 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2328 if (result != ISC_R_SUCCESS)
2329 fatal("isc_string_printf(keystr) failed: %s",
2330 isc_result_totext(result));
2331 isc_buffer_init(&buf, keystr, strlen(keystr));
2332 isc_buffer_add(&buf, strlen(keystr));
2334 result = dns_name_fromtext(keyname, &buf, dns_rootname,
2336 if (result != ISC_R_SUCCESS)
2337 fatal("dns_name_fromtext(keyname) failed: %s",
2338 isc_result_totext(result));
2340 /* Windows doesn't recognize name compression in the key name. */
2341 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2344 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2345 if (result != ISC_R_SUCCESS)
2346 fatal("dns_message_create failed: %s",
2347 isc_result_totext(result));
2349 /* Build first request. */
2351 context = GSS_C_NO_CONTEXT;
2352 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2353 &context, use_win2k_gsstsig);
2354 if (result == ISC_R_FAILURE)
2355 fatal("Check your Kerberos ticket, it may have expired.");
2356 if (result != ISC_R_SUCCESS)
2357 fatal("dns_tkey_buildgssquery failed: %s",
2358 isc_result_totext(result));
2360 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2364 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2365 dns_message_t *msg, dns_request_t **request,
2366 gss_ctx_id_t context)
2368 isc_result_t result;
2369 nsu_gssinfo_t *reqinfo;
2370 unsigned int options = 0;
2372 debug("send_gssrequest");
2373 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2374 if (reqinfo == NULL)
2375 fatal("out of memory");
2377 reqinfo->addr = destaddr;
2378 reqinfo->context = context;
2380 options |= DNS_REQUESTOPT_TCP;
2381 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2382 options, tsigkey, FIND_TIMEOUT * 20,
2383 FIND_TIMEOUT, 3, global_task, recvgss,
2385 check_result(result, "dns_request_createvia3");
2387 show_message(stdout, msg, "Outgoing update query:");
2392 recvgss(isc_task_t *task, isc_event_t *event) {
2393 dns_requestevent_t *reqev = NULL;
2394 dns_request_t *request = NULL;
2395 isc_result_t result, eresult;
2396 dns_message_t *rcvmsg = NULL;
2397 nsu_gssinfo_t *reqinfo;
2398 dns_message_t *tsigquery = NULL;
2399 isc_sockaddr_t *addr;
2400 gss_ctx_id_t context;
2402 dns_name_t *servname;
2403 dns_fixedname_t fname;
2407 ddebug("recvgss()");
2411 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2412 reqev = (dns_requestevent_t *)event;
2413 request = reqev->request;
2414 eresult = reqev->result;
2415 reqinfo = reqev->ev_arg;
2416 tsigquery = reqinfo->msg;
2417 context = reqinfo->context;
2418 addr = reqinfo->addr;
2421 dns_request_destroy(&request);
2422 dns_message_destroy(&tsigquery);
2423 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2424 isc_event_free(&event);
2429 if (eresult != ISC_R_SUCCESS) {
2430 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2432 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2433 fprintf(stderr, "; Communication with %s failed: %s\n",
2434 addrbuf, isc_result_totext(eresult));
2435 if (userserver != NULL)
2436 fatal("could not talk to specified name server");
2437 else if (++ns_inuse >= lwconf->nsnext)
2438 fatal("could not talk to any default name server");
2439 ddebug("Destroying request [%p]", request);
2440 dns_request_destroy(&request);
2441 dns_message_renderreset(tsigquery);
2442 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2444 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2445 isc_event_free(&event);
2448 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2450 isc_event_free(&event);
2453 ddebug("recvgss creating rcvmsg");
2454 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2455 check_result(result, "dns_message_create");
2457 result = dns_request_getresponse(request, rcvmsg,
2458 DNS_MESSAGEPARSE_PRESERVEORDER);
2459 check_result(result, "dns_request_getresponse");
2462 show_message(stderr, rcvmsg,
2463 "recvmsg reply from GSS-TSIG query");
2465 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2466 ddebug("recvgss trying %s GSS-TSIG",
2467 use_win2k_gsstsig ? "Standard" : "Win2k");
2468 if (use_win2k_gsstsig)
2469 use_win2k_gsstsig = ISC_FALSE;
2471 use_win2k_gsstsig = ISC_TRUE;
2472 tried_other_gsstsig = ISC_TRUE;
2473 start_gssrequest(&restart_master);
2477 if (rcvmsg->rcode != dns_rcode_noerror &&
2478 rcvmsg->rcode != dns_rcode_nxdomain)
2479 fatal("response to GSS-TSIG query was unsuccessful");
2482 dns_fixedname_init(&fname);
2483 servname = dns_fixedname_name(&fname);
2484 isc_buffer_init(&buf, servicename, strlen(servicename));
2485 isc_buffer_add(&buf, strlen(servicename));
2486 result = dns_name_fromtext(servname, &buf, dns_rootname,
2488 check_result(result, "dns_name_fromtext");
2491 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2492 &context, &tsigkey, gssring,
2496 case DNS_R_CONTINUE:
2497 send_gssrequest(localaddr, kserver, tsigquery, &request,
2503 * XXXSRA Waaay too much fun here. There's no good
2504 * reason why we need a TSIG here (the people who put
2505 * it into the spec admitted at the time that it was
2506 * not a security issue), and Windows clients don't
2507 * seem to work if named complies with the spec and
2508 * includes the gratuitous TSIG. So we're in the
2509 * bizarre situation of having to choose between
2510 * complying with a useless requirement in the spec
2511 * and interoperating. This is nuts. If we can
2512 * confirm this behavior, we should ask the WG to
2513 * consider removing the requirement for the
2514 * gratuitous TSIG here. For the moment, we ignore
2515 * the TSIG -- this too is a spec violation, but it's
2516 * the least insane thing to do.
2520 * Verify the signature.
2522 rcvmsg->state = DNS_SECTION_ANY;
2523 dns_message_setquerytsig(rcvmsg, NULL);
2524 result = dns_message_settsigkey(rcvmsg, tsigkey);
2525 check_result(result, "dns_message_settsigkey");
2526 result = dns_message_checksig(rcvmsg, NULL);
2527 ddebug("tsig verification: %s", dns_result_totext(result));
2528 check_result(result, "dns_message_checksig");
2531 send_update(&tmpzonename, serveraddr, localaddr);
2532 setzoneclass(dns_rdataclass_none);
2536 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
2540 dns_request_destroy(&request);
2541 dns_message_destroy(&tsigquery);
2543 dns_message_destroy(&rcvmsg);
2544 ddebug("Out of recvgss");
2549 start_update(void) {
2550 isc_result_t result;
2551 dns_rdataset_t *rdataset = NULL;
2552 dns_name_t *name = NULL;
2553 dns_request_t *request = NULL;
2554 dns_message_t *soaquery = NULL;
2555 dns_name_t *firstname;
2556 dns_section_t section = DNS_SECTION_UPDATE;
2558 ddebug("start_update()");
2561 dns_message_destroy(&answer);
2563 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2564 send_update(userzone, userserver, localaddr);
2565 setzoneclass(dns_rdataclass_none);
2569 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2571 check_result(result, "dns_message_create");
2573 if (userserver == NULL)
2574 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2576 result = dns_message_gettempname(soaquery, &name);
2577 check_result(result, "dns_message_gettempname");
2579 result = dns_message_gettemprdataset(soaquery, &rdataset);
2580 check_result(result, "dns_message_gettemprdataset");
2582 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2584 if (userzone != NULL) {
2585 dns_name_init(name, NULL);
2586 dns_name_clone(userzone, name);
2588 result = dns_message_firstname(updatemsg, section);
2589 if (result == ISC_R_NOMORE) {
2590 section = DNS_SECTION_PREREQUISITE;
2591 result = dns_message_firstname(updatemsg, section);
2593 if (result != ISC_R_SUCCESS) {
2594 dns_message_puttempname(soaquery, &name);
2595 dns_rdataset_disassociate(rdataset);
2596 dns_message_puttemprdataset(soaquery, &rdataset);
2597 dns_message_destroy(&soaquery);
2602 dns_message_currentname(updatemsg, section, &firstname);
2603 dns_name_init(name, NULL);
2604 dns_name_clone(firstname, name);
2607 ISC_LIST_INIT(name->list);
2608 ISC_LIST_APPEND(name->list, rdataset, link);
2609 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2611 if (userserver != NULL)
2612 sendrequest(localaddr, userserver, soaquery, &request);
2615 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2621 ddebug("cleanup()");
2624 dns_message_destroy(&answer);
2627 if (tsigkey != NULL) {
2628 ddebug("detach tsigkey x%p", tsigkey);
2629 dns_tsigkey_detach(&tsigkey);
2631 if (gssring != NULL) {
2632 ddebug("Destroying GSS-TSIG keyring");
2633 dns_tsigkeyring_destroy(&gssring);
2635 if (kserver != NULL) {
2636 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2641 ddebug("Shutting down task manager");
2642 isc_taskmgr_destroy(&taskmgr);
2644 ddebug("Destroying event");
2645 isc_event_free(&global_event);
2647 ddebug("Shutting down socket manager");
2648 isc_socketmgr_destroy(&socketmgr);
2650 ddebug("Shutting down timer manager");
2651 isc_timermgr_destroy(&timermgr);
2653 ddebug("Destroying hash context");
2656 ddebug("Destroying name state");
2659 ddebug("Removing log context");
2660 isc_log_destroy(&lctx);
2662 ddebug("Destroying memory context");
2664 isc_mem_stats(mctx, stderr);
2665 isc_mem_destroy(&mctx);
2669 getinput(isc_task_t *task, isc_event_t *event) {
2679 if (global_event == NULL)
2680 global_event = event;
2683 more = user_interaction();
2693 main(int argc, char **argv) {
2694 isc_result_t result;
2695 style = &dns_master_style_debug;
2699 interactive = ISC_TF(isatty(0));
2703 pre_parse_args(argc, argv);
2705 result = isc_mem_create(0, 0, &mctx);
2706 check_result(result, "isc_mem_create");
2708 parse_args(argc, argv, mctx, &entropy);
2712 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2713 check_result(result, "isc_app_onrun");
2715 (void)isc_app_run();