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);
622 dst_key_free(&dstkey);
628 isc_task_detach(&global_task);
630 if (userserver != NULL)
631 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
633 if (localaddr != NULL)
634 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
636 if (tsigkey != NULL) {
637 ddebug("Freeing TSIG key");
638 dns_tsigkey_detach(&tsigkey);
641 if (sig0key != NULL) {
642 ddebug("Freeing SIG(0) key");
643 dst_key_free(&sig0key);
646 if (updatemsg != NULL)
647 dns_message_destroy(&updatemsg);
650 ddebug("Destroy DST lib");
652 is_dst_up = ISC_FALSE;
655 cleanup_entropy(&entropy);
657 lwres_conf_clear(lwctx);
658 lwres_context_destroy(&lwctx);
660 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
662 ddebug("Destroying request manager");
663 dns_requestmgr_detach(&requestmgr);
665 ddebug("Freeing the dispatchers");
667 dns_dispatch_detach(&dispatchv4);
669 dns_dispatch_detach(&dispatchv6);
671 ddebug("Shutting down dispatch manager");
672 dns_dispatchmgr_destroy(&dispatchmgr);
677 maybeshutdown(void) {
678 ddebug("Shutting down request manager");
679 dns_requestmgr_shutdown(requestmgr);
688 shutdown_program(isc_task_t *task, isc_event_t *event) {
689 REQUIRE(task == global_task);
692 ddebug("shutdown_program()");
693 isc_event_free(&event);
695 shuttingdown = ISC_TRUE;
702 isc_sockaddr_t bind_any, bind_any6;
703 lwres_result_t lwresult;
704 unsigned int attrs, attrmask;
706 isc_logconfig_t *logconfig = NULL;
708 ddebug("setup_system()");
710 dns_result_register();
712 result = isc_net_probeipv4();
713 if (result == ISC_R_SUCCESS)
714 have_ipv4 = ISC_TRUE;
716 result = isc_net_probeipv6();
717 if (result == ISC_R_SUCCESS)
718 have_ipv6 = ISC_TRUE;
720 if (!have_ipv4 && !have_ipv6)
721 fatal("could not find either IPv4 or IPv6");
723 result = isc_log_create(mctx, &lctx, &logconfig);
724 check_result(result, "isc_log_create");
726 isc_log_setcontext(lctx);
728 dns_log_setcontext(lctx);
730 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
731 check_result(result, "isc_log_usechannel");
733 isc_log_setdebuglevel(lctx, logdebuglevel);
735 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
736 if (lwresult != LWRES_R_SUCCESS)
737 fatal("lwres_context_create failed");
739 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
740 lwconf = lwres_conf_get(lwctx);
742 ns_total = lwconf->nsnext;
744 /* No name servers in resolv.conf; default to loopback. */
745 struct in_addr localhost;
747 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
749 fatal("out of memory");
750 localhost.s_addr = htonl(INADDR_LOOPBACK);
751 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
753 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
755 fatal("out of memory");
756 for (i = 0; i < ns_total; i++) {
757 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
759 memcpy(&in4, lwconf->nameservers[i].address, 4);
760 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT);
763 memcpy(&in6, lwconf->nameservers[i].address, 16);
764 isc_sockaddr_fromin6(&servers[i], &in6,
770 setup_entropy(mctx, NULL, &entropy);
772 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
773 check_result(result, "isc_hash_create");
776 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
777 check_result(result, "dns_dispatchmgr_create");
779 result = isc_socketmgr_create(mctx, &socketmgr);
780 check_result(result, "dns_socketmgr_create");
782 result = isc_timermgr_create(mctx, &timermgr);
783 check_result(result, "dns_timermgr_create");
785 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
786 check_result(result, "isc_taskmgr_create");
788 result = isc_task_create(taskmgr, 0, &global_task);
789 check_result(result, "isc_task_create");
791 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
792 check_result(result, "isc_task_onshutdown");
794 result = dst_lib_init(mctx, entropy, 0);
795 check_result(result, "dst_lib_init");
796 is_dst_up = ISC_TRUE;
798 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
799 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
802 attrs = DNS_DISPATCHATTR_UDP;
803 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
804 attrs |= DNS_DISPATCHATTR_IPV6;
805 isc_sockaddr_any6(&bind_any6);
806 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
807 &bind_any6, PACKETSIZE,
809 attrs, attrmask, &dispatchv6);
810 check_result(result, "dns_dispatch_getudp (v6)");
814 attrs = DNS_DISPATCHATTR_UDP;
815 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
816 attrs |= DNS_DISPATCHATTR_IPV4;
817 isc_sockaddr_any(&bind_any);
818 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
819 &bind_any, PACKETSIZE,
821 attrs, attrmask, &dispatchv4);
822 check_result(result, "dns_dispatch_getudp (v4)");
825 result = dns_requestmgr_create(mctx, timermgr,
826 socketmgr, taskmgr, dispatchmgr,
827 dispatchv4, dispatchv6, &requestmgr);
828 check_result(result, "dns_requestmgr_create");
832 else if (keyfile != NULL)
837 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
842 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
844 if (result != ISC_R_SUCCESS)
845 fatal("couldn't get address for '%s': %s",
846 host, isc_result_totext(result));
850 #define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
853 pre_parse_args(int argc, char **argv) {
856 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
858 case 'M': /* was -dm */
859 debugging = ISC_TRUE;
860 ddebugging = ISC_TRUE;
861 memdebugging = ISC_TRUE;
862 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
867 if (isc_commandline_option != '?')
868 fprintf(stderr, "%s: invalid argument -%c\n",
869 argv[0], isc_commandline_option);
870 fprintf(stderr, "usage: nsupdate [-d] "
871 "[-g | -o | -y keyname:secret | -k keyfile] "
872 "[-v] [filename]\n");
879 isc_commandline_reset = ISC_TRUE;
880 isc_commandline_index = 1;
884 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
890 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
893 debugging = ISC_TRUE;
895 case 'D': /* was -dd */
896 debugging = ISC_TRUE;
897 ddebugging = ISC_TRUE;
902 result = isc_parse_uint32(&i, isc_commandline_argument,
904 if (result != ISC_R_SUCCESS) {
905 fprintf(stderr, "bad library debug value "
906 "'%s'\n", isc_commandline_argument);
912 keystr = isc_commandline_argument;
918 keyfile = isc_commandline_argument;
921 usegsstsig = ISC_TRUE;
922 use_win2k_gsstsig = ISC_FALSE;
925 usegsstsig = ISC_TRUE;
926 use_win2k_gsstsig = ISC_TRUE;
929 result = isc_parse_uint32(&timeout,
930 isc_commandline_argument, 10);
931 if (result != ISC_R_SUCCESS) {
932 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
939 result = isc_parse_uint32(&udp_timeout,
940 isc_commandline_argument, 10);
941 if (result != ISC_R_SUCCESS) {
942 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
945 if (udp_timeout == 0)
946 udp_timeout = UINT_MAX;
949 result = isc_parse_uint32(&udp_retries,
950 isc_commandline_argument, 10);
951 if (result != ISC_R_SUCCESS) {
952 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
958 setup_entropy(mctx, isc_commandline_argument, ectx);
962 fprintf(stderr, "%s: unhandled option: %c\n",
963 argv[0], isc_commandline_option);
967 if (keyfile != NULL && keystr != NULL) {
968 fprintf(stderr, "%s: cannot specify both -k and -y\n",
974 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
975 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
981 fprintf(stderr, "%s: cannot specify -g or -o, " \
982 "program not linked with GSS API Library\n",
988 if (argv[isc_commandline_index] != NULL) {
989 if (strcmp(argv[isc_commandline_index], "-") == 0) {
992 result = isc_stdio_open(argv[isc_commandline_index],
994 if (result != ISC_R_SUCCESS) {
995 fprintf(stderr, "could not open '%s': %s\n",
996 argv[isc_commandline_index],
997 isc_result_totext(result));
1001 interactive = ISC_FALSE;
1006 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1007 isc_result_t result;
1009 isc_buffer_t *namebuf = NULL;
1010 isc_buffer_t source;
1012 word = nsu_strsep(cmdlinep, " \t\r\n");
1014 fprintf(stderr, "could not read owner name\n");
1015 return (STATUS_SYNTAX);
1018 result = dns_message_gettempname(msg, namep);
1019 check_result(result, "dns_message_gettempname");
1020 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
1021 check_result(result, "isc_buffer_allocate");
1022 dns_name_init(*namep, NULL);
1023 dns_name_setbuffer(*namep, namebuf);
1024 dns_message_takebuffer(msg, &namebuf);
1025 isc_buffer_init(&source, word, strlen(word));
1026 isc_buffer_add(&source, strlen(word));
1027 result = dns_name_fromtext(*namep, &source, dns_rootname,
1029 check_result(result, "dns_name_fromtext");
1030 isc_buffer_invalidate(&source);
1031 return (STATUS_MORE);
1035 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1036 dns_rdatatype_t rdatatype, dns_message_t *msg,
1039 char *cmdline = *cmdlinep;
1040 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1042 isc_lex_t *lex = NULL;
1043 dns_rdatacallbacks_t callbacks;
1044 isc_result_t result;
1046 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1049 if (*cmdline != 0) {
1050 dns_rdatacallbacks_init(&callbacks);
1051 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1052 check_result(result, "isc_lex_create");
1053 isc_buffer_init(&source, cmdline, strlen(cmdline));
1054 isc_buffer_add(&source, strlen(cmdline));
1055 result = isc_lex_openbuffer(lex, &source);
1056 check_result(result, "isc_lex_openbuffer");
1057 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1058 check_result(result, "isc_buffer_allocate");
1059 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1060 dns_rootname, 0, mctx, buf,
1062 isc_lex_destroy(&lex);
1063 if (result == ISC_R_SUCCESS) {
1064 isc_buffer_usedregion(buf, &r);
1065 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1066 check_result(result, "isc_buffer_allocate");
1067 isc_buffer_putmem(newbuf, r.base, r.length);
1068 isc_buffer_usedregion(newbuf, &r);
1069 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1070 isc_buffer_free(&buf);
1071 dns_message_takebuffer(msg, &newbuf);
1073 fprintf(stderr, "invalid rdata format: %s\n",
1074 isc_result_totext(result));
1075 isc_buffer_free(&buf);
1076 return (STATUS_SYNTAX);
1079 rdata->flags = DNS_RDATA_UPDATE;
1081 *cmdlinep = cmdline;
1082 return (STATUS_MORE);
1086 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1087 isc_result_t result;
1089 dns_name_t *name = NULL;
1090 isc_textregion_t region;
1091 dns_rdataset_t *rdataset = NULL;
1092 dns_rdatalist_t *rdatalist = NULL;
1093 dns_rdataclass_t rdataclass;
1094 dns_rdatatype_t rdatatype;
1095 dns_rdata_t *rdata = NULL;
1096 isc_uint16_t retval;
1098 ddebug("make_prereq()");
1101 * Read the owner name
1103 retval = parse_name(&cmdline, updatemsg, &name);
1104 if (retval != STATUS_MORE)
1108 * If this is an rrset prereq, read the class or type.
1111 word = nsu_strsep(&cmdline, " \t\r\n");
1113 fprintf(stderr, "could not read class or type\n");
1117 region.length = strlen(word);
1118 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1119 if (result == ISC_R_SUCCESS) {
1120 if (!setzoneclass(rdataclass)) {
1121 fprintf(stderr, "class mismatch: %s\n", word);
1125 * Now read the type.
1127 word = nsu_strsep(&cmdline, " \t\r\n");
1129 fprintf(stderr, "could not read type\n");
1133 region.length = strlen(word);
1134 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1135 if (result != ISC_R_SUCCESS) {
1136 fprintf(stderr, "invalid type: %s\n", word);
1140 rdataclass = getzoneclass();
1141 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1142 if (result != ISC_R_SUCCESS) {
1143 fprintf(stderr, "invalid type: %s\n", word);
1148 rdatatype = dns_rdatatype_any;
1150 result = dns_message_gettemprdata(updatemsg, &rdata);
1151 check_result(result, "dns_message_gettemprdata");
1153 dns_rdata_init(rdata);
1155 if (isrrset && ispositive) {
1156 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1158 if (retval != STATUS_MORE)
1161 rdata->flags = DNS_RDATA_UPDATE;
1163 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1164 check_result(result, "dns_message_gettemprdatalist");
1165 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1166 check_result(result, "dns_message_gettemprdataset");
1167 dns_rdatalist_init(rdatalist);
1168 rdatalist->type = rdatatype;
1170 if (isrrset && rdata->data != NULL)
1171 rdatalist->rdclass = rdataclass;
1173 rdatalist->rdclass = dns_rdataclass_any;
1175 rdatalist->rdclass = dns_rdataclass_none;
1176 rdatalist->covers = 0;
1178 rdata->rdclass = rdatalist->rdclass;
1179 rdata->type = rdatatype;
1180 ISC_LIST_INIT(rdatalist->rdata);
1181 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1182 dns_rdataset_init(rdataset);
1183 dns_rdatalist_tordataset(rdatalist, rdataset);
1184 ISC_LIST_INIT(name->list);
1185 ISC_LIST_APPEND(name->list, rdataset, link);
1186 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1187 return (STATUS_MORE);
1191 dns_message_puttempname(updatemsg, &name);
1192 return (STATUS_SYNTAX);
1196 evaluate_prereq(char *cmdline) {
1198 isc_boolean_t ispositive, isrrset;
1200 ddebug("evaluate_prereq()");
1201 word = nsu_strsep(&cmdline, " \t\r\n");
1203 fprintf(stderr, "could not read operation code\n");
1204 return (STATUS_SYNTAX);
1206 if (strcasecmp(word, "nxdomain") == 0) {
1207 ispositive = ISC_FALSE;
1208 isrrset = ISC_FALSE;
1209 } else if (strcasecmp(word, "yxdomain") == 0) {
1210 ispositive = ISC_TRUE;
1211 isrrset = ISC_FALSE;
1212 } else if (strcasecmp(word, "nxrrset") == 0) {
1213 ispositive = ISC_FALSE;
1215 } else if (strcasecmp(word, "yxrrset") == 0) {
1216 ispositive = ISC_TRUE;
1219 fprintf(stderr, "incorrect operation code: %s\n", word);
1220 return (STATUS_SYNTAX);
1222 return (make_prereq(cmdline, ispositive, isrrset));
1226 evaluate_server(char *cmdline) {
1227 char *word, *server;
1230 word = nsu_strsep(&cmdline, " \t\r\n");
1232 fprintf(stderr, "could not read server name\n");
1233 return (STATUS_SYNTAX);
1237 word = nsu_strsep(&cmdline, " \t\r\n");
1239 port = DNSDEFAULTPORT;
1242 port = strtol(word, &endp, 10);
1244 fprintf(stderr, "port '%s' is not numeric\n", word);
1245 return (STATUS_SYNTAX);
1246 } else if (port < 1 || port > 65535) {
1247 fprintf(stderr, "port '%s' is out of range "
1248 "(1 to 65535)\n", word);
1249 return (STATUS_SYNTAX);
1253 if (userserver == NULL) {
1254 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1255 if (userserver == NULL)
1256 fatal("out of memory");
1259 get_address(server, (in_port_t)port, userserver);
1261 return (STATUS_MORE);
1265 evaluate_local(char *cmdline) {
1269 struct in6_addr in6;
1271 word = nsu_strsep(&cmdline, " \t\r\n");
1273 fprintf(stderr, "could not read server name\n");
1274 return (STATUS_SYNTAX);
1278 word = nsu_strsep(&cmdline, " \t\r\n");
1283 port = strtol(word, &endp, 10);
1285 fprintf(stderr, "port '%s' is not numeric\n", word);
1286 return (STATUS_SYNTAX);
1287 } else if (port < 1 || port > 65535) {
1288 fprintf(stderr, "port '%s' is out of range "
1289 "(1 to 65535)\n", word);
1290 return (STATUS_SYNTAX);
1294 if (localaddr == NULL) {
1295 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1296 if (localaddr == NULL)
1297 fatal("out of memory");
1300 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1301 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1302 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1303 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1305 fprintf(stderr, "invalid address %s", local);
1306 return (STATUS_SYNTAX);
1309 return (STATUS_MORE);
1313 evaluate_key(char *cmdline) {
1317 isc_result_t result;
1318 dns_fixedname_t fkeyname;
1319 dns_name_t *keyname;
1321 unsigned char *secret = NULL;
1322 isc_buffer_t secretbuf;
1323 dns_name_t *hmacname = NULL;
1324 isc_uint16_t digestbits = 0;
1327 namestr = nsu_strsep(&cmdline, " \t\r\n");
1328 if (*namestr == 0) {
1329 fprintf(stderr, "could not read key name\n");
1330 return (STATUS_SYNTAX);
1333 dns_fixedname_init(&fkeyname);
1334 keyname = dns_fixedname_name(&fkeyname);
1336 n = strchr(namestr, ':');
1338 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1341 hmacname = DNS_TSIG_HMACMD5_NAME;
1343 isc_buffer_init(&b, namestr, strlen(namestr));
1344 isc_buffer_add(&b, strlen(namestr));
1345 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
1346 if (result != ISC_R_SUCCESS) {
1347 fprintf(stderr, "could not parse key name\n");
1348 return (STATUS_SYNTAX);
1351 secretstr = nsu_strsep(&cmdline, "\r\n");
1352 if (*secretstr == 0) {
1353 fprintf(stderr, "could not read key secret\n");
1354 return (STATUS_SYNTAX);
1356 secretlen = strlen(secretstr) * 3 / 4;
1357 secret = isc_mem_allocate(mctx, secretlen);
1359 fatal("out of memory");
1361 isc_buffer_init(&secretbuf, secret, secretlen);
1362 result = isc_base64_decodestring(secretstr, &secretbuf);
1363 if (result != ISC_R_SUCCESS) {
1364 fprintf(stderr, "could not create key from %s: %s\n",
1365 secretstr, isc_result_totext(result));
1366 isc_mem_free(mctx, secret);
1367 return (STATUS_SYNTAX);
1369 secretlen = isc_buffer_usedlength(&secretbuf);
1371 if (tsigkey != NULL)
1372 dns_tsigkey_detach(&tsigkey);
1373 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1374 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1376 isc_mem_free(mctx, secret);
1377 if (result != ISC_R_SUCCESS) {
1378 fprintf(stderr, "could not create key from %s %s: %s\n",
1379 namestr, secretstr, dns_result_totext(result));
1380 return (STATUS_SYNTAX);
1382 dst_key_setbits(tsigkey->key, digestbits);
1383 return (STATUS_MORE);
1387 evaluate_zone(char *cmdline) {
1390 isc_result_t result;
1392 word = nsu_strsep(&cmdline, " \t\r\n");
1394 fprintf(stderr, "could not read zone name\n");
1395 return (STATUS_SYNTAX);
1398 dns_fixedname_init(&fuserzone);
1399 userzone = dns_fixedname_name(&fuserzone);
1400 isc_buffer_init(&b, word, strlen(word));
1401 isc_buffer_add(&b, strlen(word));
1402 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE,
1404 if (result != ISC_R_SUCCESS) {
1405 userzone = NULL; /* Lest it point to an invalid name */
1406 fprintf(stderr, "could not parse zone name\n");
1407 return (STATUS_SYNTAX);
1410 return (STATUS_MORE);
1414 evaluate_realm(char *cmdline) {
1419 word = nsu_strsep(&cmdline, " \t\r\n");
1422 isc_mem_free(mctx, realm);
1424 return (STATUS_MORE);
1427 snprintf(buf, sizeof(buf), "@%s", word);
1428 realm = isc_mem_strdup(mctx, buf);
1430 fatal("out of memory");
1431 return (STATUS_MORE);
1434 return (STATUS_SYNTAX);
1439 evaluate_ttl(char *cmdline) {
1441 isc_result_t result;
1444 word = nsu_strsep(&cmdline, " \t\r\n");
1446 fprintf(stderr, "could not ttl\n");
1447 return (STATUS_SYNTAX);
1450 if (!strcasecmp(word, "none")) {
1452 default_ttl_set = ISC_FALSE;
1453 return (STATUS_MORE);
1456 result = isc_parse_uint32(&ttl, word, 10);
1457 if (result != ISC_R_SUCCESS)
1458 return (STATUS_SYNTAX);
1460 if (ttl > TTL_MAX) {
1461 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1463 return (STATUS_SYNTAX);
1466 default_ttl_set = ISC_TRUE;
1468 return (STATUS_MORE);
1472 evaluate_class(char *cmdline) {
1475 isc_result_t result;
1476 dns_rdataclass_t rdclass;
1478 word = nsu_strsep(&cmdline, " \t\r\n");
1480 fprintf(stderr, "could not read class name\n");
1481 return (STATUS_SYNTAX);
1485 r.length = strlen(word);
1486 result = dns_rdataclass_fromtext(&rdclass, &r);
1487 if (result != ISC_R_SUCCESS) {
1488 fprintf(stderr, "could not parse class name: %s\n", word);
1489 return (STATUS_SYNTAX);
1492 case dns_rdataclass_none:
1493 case dns_rdataclass_any:
1494 case dns_rdataclass_reserved0:
1495 fprintf(stderr, "bad default class: %s\n", word);
1496 return (STATUS_SYNTAX);
1498 defaultclass = rdclass;
1501 return (STATUS_MORE);
1505 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1506 isc_result_t result;
1507 dns_name_t *name = NULL;
1510 dns_rdataclass_t rdataclass;
1511 dns_rdatatype_t rdatatype;
1512 dns_rdata_t *rdata = NULL;
1513 dns_rdatalist_t *rdatalist = NULL;
1514 dns_rdataset_t *rdataset = NULL;
1515 isc_textregion_t region;
1516 isc_uint16_t retval;
1518 ddebug("update_addordelete()");
1521 * Read the owner name.
1523 retval = parse_name(&cmdline, updatemsg, &name);
1524 if (retval != STATUS_MORE)
1527 result = dns_message_gettemprdata(updatemsg, &rdata);
1528 check_result(result, "dns_message_gettemprdata");
1530 dns_rdata_init(rdata);
1533 * If this is an add, read the TTL and verify that it's in range.
1534 * If it's a delete, ignore a TTL if present (for compatibility).
1536 word = nsu_strsep(&cmdline, " \t\r\n");
1539 fprintf(stderr, "could not read owner ttl\n");
1544 rdataclass = dns_rdataclass_any;
1545 rdatatype = dns_rdatatype_any;
1546 rdata->flags = DNS_RDATA_UPDATE;
1550 result = isc_parse_uint32(&ttl, word, 10);
1551 if (result != ISC_R_SUCCESS) {
1555 } else if (default_ttl_set) {
1559 fprintf(stderr, "ttl '%s': %s\n", word,
1560 isc_result_totext(result));
1567 else if (ttl > TTL_MAX) {
1568 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1574 * Read the class or type.
1576 word = nsu_strsep(&cmdline, " \t\r\n");
1580 rdataclass = dns_rdataclass_any;
1581 rdatatype = dns_rdatatype_any;
1582 rdata->flags = DNS_RDATA_UPDATE;
1585 fprintf(stderr, "could not read class or type\n");
1590 region.length = strlen(word);
1591 rdataclass = dns_rdataclass_any;
1592 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1593 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1594 if (!setzoneclass(rdataclass)) {
1595 fprintf(stderr, "class mismatch: %s\n", word);
1599 * Now read the type.
1601 word = nsu_strsep(&cmdline, " \t\r\n");
1604 rdataclass = dns_rdataclass_any;
1605 rdatatype = dns_rdatatype_any;
1606 rdata->flags = DNS_RDATA_UPDATE;
1609 fprintf(stderr, "could not read type\n");
1614 region.length = strlen(word);
1615 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1616 if (result != ISC_R_SUCCESS) {
1617 fprintf(stderr, "'%s' is not a valid type: %s\n",
1618 word, isc_result_totext(result));
1622 rdataclass = getzoneclass();
1623 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1624 if (result != ISC_R_SUCCESS) {
1625 fprintf(stderr, "'%s' is not a valid class or type: "
1626 "%s\n", word, isc_result_totext(result));
1631 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1633 if (retval != STATUS_MORE)
1637 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1638 rdataclass = dns_rdataclass_any;
1640 rdataclass = dns_rdataclass_none;
1642 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1643 fprintf(stderr, "could not read rdata\n");
1650 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1651 check_result(result, "dns_message_gettemprdatalist");
1652 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1653 check_result(result, "dns_message_gettemprdataset");
1654 dns_rdatalist_init(rdatalist);
1655 rdatalist->type = rdatatype;
1656 rdatalist->rdclass = rdataclass;
1657 rdatalist->covers = rdatatype;
1658 rdatalist->ttl = (dns_ttl_t)ttl;
1659 ISC_LIST_INIT(rdatalist->rdata);
1660 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1661 dns_rdataset_init(rdataset);
1662 dns_rdatalist_tordataset(rdatalist, rdataset);
1663 ISC_LIST_INIT(name->list);
1664 ISC_LIST_APPEND(name->list, rdataset, link);
1665 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1666 return (STATUS_MORE);
1670 dns_message_puttempname(updatemsg, &name);
1671 dns_message_puttemprdata(updatemsg, &rdata);
1672 return (STATUS_SYNTAX);
1676 evaluate_update(char *cmdline) {
1678 isc_boolean_t isdelete;
1680 ddebug("evaluate_update()");
1681 word = nsu_strsep(&cmdline, " \t\r\n");
1683 fprintf(stderr, "could not read operation code\n");
1684 return (STATUS_SYNTAX);
1686 if (strcasecmp(word, "delete") == 0)
1687 isdelete = ISC_TRUE;
1688 else if (strcasecmp(word, "add") == 0)
1689 isdelete = ISC_FALSE;
1691 fprintf(stderr, "incorrect operation code: %s\n", word);
1692 return (STATUS_SYNTAX);
1694 return (update_addordelete(cmdline, isdelete));
1698 setzone(dns_name_t *zonename) {
1699 isc_result_t result;
1700 dns_name_t *name = NULL;
1701 dns_rdataset_t *rdataset = NULL;
1703 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1704 if (result == ISC_R_SUCCESS) {
1705 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1706 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1707 for (rdataset = ISC_LIST_HEAD(name->list);
1709 rdataset = ISC_LIST_HEAD(name->list)) {
1710 ISC_LIST_UNLINK(name->list, rdataset, link);
1711 dns_rdataset_disassociate(rdataset);
1712 dns_message_puttemprdataset(updatemsg, &rdataset);
1714 dns_message_puttempname(updatemsg, &name);
1717 if (zonename != NULL) {
1718 result = dns_message_gettempname(updatemsg, &name);
1719 check_result(result, "dns_message_gettempname");
1720 dns_name_init(name, NULL);
1721 dns_name_clone(zonename, name);
1722 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1723 check_result(result, "dns_message_gettemprdataset");
1724 dns_rdataset_makequestion(rdataset, getzoneclass(),
1726 ISC_LIST_INIT(name->list);
1727 ISC_LIST_APPEND(name->list, rdataset, link);
1728 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1733 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1734 isc_result_t result;
1735 isc_buffer_t *buf = NULL;
1738 ddebug("show_message()");
1744 if (bufsz > MAXTEXT) {
1745 fprintf(stderr, "could not allocate large enough "
1746 "buffer to display message\n");
1750 isc_buffer_free(&buf);
1751 result = isc_buffer_allocate(mctx, &buf, bufsz);
1752 check_result(result, "isc_buffer_allocate");
1753 result = dns_message_totext(msg, style, 0, buf);
1755 } while (result == ISC_R_NOSPACE);
1756 if (result != ISC_R_SUCCESS) {
1757 fprintf(stderr, "could not convert message to text format.\n");
1758 isc_buffer_free(&buf);
1761 fprintf(stream, "%s\n%.*s", description,
1762 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1763 isc_buffer_free(&buf);
1768 get_next_command(void) {
1769 char cmdlinebuf[MAXCMD];
1773 ddebug("get_next_command()");
1775 fprintf(stdout, "> ");
1779 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1781 if (cmdline == NULL)
1782 return (STATUS_QUIT);
1783 word = nsu_strsep(&cmdline, " \t\r\n");
1786 return (STATUS_QUIT);
1788 return (STATUS_SEND);
1790 return (STATUS_MORE);
1791 if (strcasecmp(word, "quit") == 0)
1792 return (STATUS_QUIT);
1793 if (strcasecmp(word, "prereq") == 0)
1794 return (evaluate_prereq(cmdline));
1795 if (strcasecmp(word, "update") == 0)
1796 return (evaluate_update(cmdline));
1797 if (strcasecmp(word, "server") == 0)
1798 return (evaluate_server(cmdline));
1799 if (strcasecmp(word, "local") == 0)
1800 return (evaluate_local(cmdline));
1801 if (strcasecmp(word, "zone") == 0)
1802 return (evaluate_zone(cmdline));
1803 if (strcasecmp(word, "class") == 0)
1804 return (evaluate_class(cmdline));
1805 if (strcasecmp(word, "send") == 0)
1806 return (STATUS_SEND);
1807 if (strcasecmp(word, "debug") == 0) {
1809 ddebugging = ISC_TRUE;
1811 debugging = ISC_TRUE;
1812 return (STATUS_MORE);
1814 if (strcasecmp(word, "ttl") == 0)
1815 return (evaluate_ttl(cmdline));
1816 if (strcasecmp(word, "show") == 0) {
1817 show_message(stdout, updatemsg, "Outgoing update query:");
1818 return (STATUS_MORE);
1820 if (strcasecmp(word, "answer") == 0) {
1822 show_message(stdout, answer, "Answer:");
1823 return (STATUS_MORE);
1825 if (strcasecmp(word, "key") == 0) {
1826 usegsstsig = ISC_FALSE;
1827 return (evaluate_key(cmdline));
1829 if (strcasecmp(word, "realm") == 0)
1830 return (evaluate_realm(cmdline));
1831 if (strcasecmp(word, "gsstsig") == 0) {
1833 usegsstsig = ISC_TRUE;
1834 use_win2k_gsstsig = ISC_FALSE;
1836 fprintf(stderr, "gsstsig not supported\n");
1838 return (STATUS_MORE);
1840 if (strcasecmp(word, "oldgsstsig") == 0) {
1842 usegsstsig = ISC_TRUE;
1843 use_win2k_gsstsig = ISC_TRUE;
1845 fprintf(stderr, "gsstsig not supported\n");
1847 return (STATUS_MORE);
1849 if (strcasecmp(word, "help") == 0) {
1851 "local address [port] (set local resolver)\n"
1852 "server address [port] (set master server for zone)\n"
1853 "send (send the update request)\n"
1854 "show (show the update request)\n"
1855 "answer (show the answer to the last request)\n"
1856 "quit (quit, any pending update is not sent\n"
1857 "help (display this message_\n"
1858 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1859 "gsstsig (use GSS_TSIG to sign the request)\n"
1860 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1861 "zone name (set the zone to be updated)\n"
1862 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1863 "prereq nxdomain name (does this name not exist)\n"
1864 "prereq yxdomain name (does this name exist)\n"
1865 "prereq nxrrset .... (does this RRset exist)\n"
1866 "prereq yxrrset .... (does this RRset not exist)\n"
1867 "update add .... (add the given record to the zone)\n"
1868 "update delete .... (remove the given record(s) from the zone)\n");
1869 return (STATUS_MORE);
1871 fprintf(stderr, "incorrect section name: %s\n", word);
1872 return (STATUS_SYNTAX);
1875 static isc_boolean_t
1876 user_interaction(void) {
1877 isc_uint16_t result = STATUS_MORE;
1879 ddebug("user_interaction()");
1880 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
1881 result = get_next_command();
1882 if (!interactive && result == STATUS_SYNTAX)
1883 fatal("syntax error");
1885 if (result == STATUS_SEND)
1893 isc_event_t *event = global_event;
1894 ddebug("done_update()");
1895 isc_task_send(global_task, &event);
1899 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
1900 isc_result_t result;
1901 dns_rdata_t rdata = DNS_RDATA_INIT;
1902 dns_rdata_any_tsig_t tsig;
1904 result = dns_rdataset_first(rdataset);
1905 check_result(result, "dns_rdataset_first");
1906 dns_rdataset_current(rdataset, &rdata);
1907 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
1908 check_result(result, "dns_rdata_tostruct");
1909 if (tsig.error != 0) {
1910 if (isc_buffer_remaininglength(b) < 1)
1911 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1912 isc__buffer_putstr(b, "(" /*)*/);
1913 result = dns_tsigrcode_totext(tsig.error, b);
1914 check_result(result, "dns_tsigrcode_totext");
1915 if (isc_buffer_remaininglength(b) < 1)
1916 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1917 isc__buffer_putstr(b, /*(*/ ")");
1922 update_completed(isc_task_t *task, isc_event_t *event) {
1923 dns_requestevent_t *reqev = NULL;
1924 isc_result_t result;
1925 dns_request_t *request;
1929 ddebug("update_completed()");
1933 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1934 reqev = (dns_requestevent_t *)event;
1935 request = reqev->request;
1938 dns_request_destroy(&request);
1939 isc_event_free(&event);
1944 if (reqev->result != ISC_R_SUCCESS) {
1945 fprintf(stderr, "; Communication with server failed: %s\n",
1946 isc_result_totext(reqev->result));
1947 seenerror = ISC_TRUE;
1951 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
1952 check_result(result, "dns_message_create");
1953 result = dns_request_getresponse(request, answer,
1954 DNS_MESSAGEPARSE_PRESERVEORDER);
1957 if (answer->verify_attempted)
1958 ddebug("tsig verification successful");
1960 case DNS_R_CLOCKSKEW:
1961 case DNS_R_EXPECTEDTSIG:
1962 case DNS_R_TSIGERRORSET:
1963 case DNS_R_TSIGVERIFYFAILURE:
1964 case DNS_R_UNEXPECTEDTSIG:
1967 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
1969 * For MS DNS that violates RFC 2845, section 4.2
1974 fprintf(stderr, "; TSIG error with server: %s\n",
1975 isc_result_totext(result));
1976 seenerror = ISC_TRUE;
1979 check_result(result, "dns_request_getresponse");
1982 if (answer->rcode != dns_rcode_noerror) {
1983 seenerror = ISC_TRUE;
1987 dns_rdataset_t *rds;
1989 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1990 result = dns_rcode_totext(answer->rcode, &b);
1991 check_result(result, "dns_rcode_totext");
1992 rds = dns_message_gettsig(answer, NULL);
1994 check_tsig_error(rds, &b);
1995 fprintf(stderr, "update failed: %.*s\n",
1996 (int)isc_buffer_usedlength(&b), buf);
2000 show_message(stderr, answer, "\nReply from update query:");
2003 dns_request_destroy(&request);
2005 dns_name_free(&tmpzonename, mctx);
2006 dns_name_free(&restart_master, mctx);
2008 isc_event_free(&event);
2013 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2014 isc_sockaddr_t *srcaddr)
2016 isc_result_t result;
2017 dns_request_t *request = NULL;
2018 unsigned int options = 0;
2020 ddebug("send_update()");
2025 options |= DNS_REQUESTOPT_TCP;
2026 if (tsigkey == NULL && sig0key != NULL) {
2027 result = dns_message_setsig0key(updatemsg, sig0key);
2028 check_result(result, "dns_message_setsig0key");
2031 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2033 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2034 fprintf(stderr, "Sending update to %s\n", addrbuf);
2037 /* Windows doesn't like the tsig name to be compressed. */
2038 if (updatemsg->tsigname)
2039 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2041 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2042 master, options, tsigkey, timeout,
2043 udp_timeout, udp_retries, global_task,
2044 update_completed, NULL, &request);
2045 check_result(result, "dns_request_createvia3");
2048 show_message(stdout, updatemsg, "Outgoing update query:");
2054 recvsoa(isc_task_t *task, isc_event_t *event) {
2055 dns_requestevent_t *reqev = NULL;
2056 dns_request_t *request = NULL;
2057 isc_result_t result, eresult;
2058 dns_message_t *rcvmsg = NULL;
2059 dns_section_t section;
2060 dns_name_t *name = NULL;
2061 dns_rdataset_t *soaset = NULL;
2062 dns_rdata_soa_t soa;
2063 dns_rdata_t soarr = DNS_RDATA_INIT;
2066 nsu_requestinfo_t *reqinfo;
2067 dns_message_t *soaquery = NULL;
2068 isc_sockaddr_t *addr;
2069 isc_boolean_t seencname = ISC_FALSE;
2071 unsigned int nlabels;
2075 ddebug("recvsoa()");
2079 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2080 reqev = (dns_requestevent_t *)event;
2081 request = reqev->request;
2082 eresult = reqev->result;
2083 reqinfo = reqev->ev_arg;
2084 soaquery = reqinfo->msg;
2085 addr = reqinfo->addr;
2088 dns_request_destroy(&request);
2089 dns_message_destroy(&soaquery);
2090 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2091 isc_event_free(&event);
2096 if (eresult != ISC_R_SUCCESS) {
2097 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2099 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2100 fprintf(stderr, "; Communication with %s failed: %s\n",
2101 addrbuf, isc_result_totext(eresult));
2102 if (userserver != NULL)
2103 fatal("could not talk to specified name server");
2104 else if (++ns_inuse >= lwconf->nsnext)
2105 fatal("could not talk to any default name server");
2106 ddebug("Destroying request [%p]", request);
2107 dns_request_destroy(&request);
2108 dns_message_renderreset(soaquery);
2109 dns_message_settsigkey(soaquery, NULL);
2110 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2111 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2112 isc_event_free(&event);
2113 setzoneclass(dns_rdataclass_none);
2117 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2119 isc_event_free(&event);
2122 ddebug("About to create rcvmsg");
2123 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2124 check_result(result, "dns_message_create");
2125 result = dns_request_getresponse(request, rcvmsg,
2126 DNS_MESSAGEPARSE_PRESERVEORDER);
2127 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2128 dns_message_destroy(&rcvmsg);
2129 ddebug("Destroying request [%p]", request);
2130 dns_request_destroy(&request);
2131 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2132 if (reqinfo == NULL)
2133 fatal("out of memory");
2134 reqinfo->msg = soaquery;
2135 reqinfo->addr = addr;
2136 dns_message_renderreset(soaquery);
2137 ddebug("retrying soa request without TSIG");
2138 result = dns_request_createvia3(requestmgr, soaquery,
2139 localaddr, addr, 0, NULL,
2142 global_task, recvsoa, reqinfo,
2144 check_result(result, "dns_request_createvia");
2148 check_result(result, "dns_request_getresponse");
2149 section = DNS_SECTION_ANSWER;
2151 show_message(stderr, rcvmsg, "Reply from SOA query:");
2153 if (rcvmsg->rcode != dns_rcode_noerror &&
2154 rcvmsg->rcode != dns_rcode_nxdomain)
2155 fatal("response to SOA query was unsuccessful");
2157 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2158 char namebuf[DNS_NAME_FORMATSIZE];
2159 dns_name_format(userzone, namebuf, sizeof(namebuf));
2160 error("specified zone '%s' does not exist (NXDOMAIN)",
2162 dns_message_destroy(&rcvmsg);
2163 dns_request_destroy(&request);
2164 dns_message_destroy(&soaquery);
2165 ddebug("Out of recvsoa");
2172 section = DNS_SECTION_ANSWER;
2174 section = DNS_SECTION_AUTHORITY;
2178 result = dns_message_firstname(rcvmsg, section);
2179 if (result != ISC_R_SUCCESS) {
2183 while (result == ISC_R_SUCCESS) {
2185 dns_message_currentname(rcvmsg, section, &name);
2187 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2189 if (result == ISC_R_SUCCESS)
2191 if (section == DNS_SECTION_ANSWER) {
2192 dns_rdataset_t *tset = NULL;
2193 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2194 &tset) == ISC_R_SUCCESS ||
2195 dns_message_findtype(name, dns_rdatatype_dname, 0,
2196 &tset) == ISC_R_SUCCESS ) {
2197 seencname = ISC_TRUE;
2202 result = dns_message_nextname(rcvmsg, section);
2205 if (soaset == NULL && !seencname) {
2214 char namestr[DNS_NAME_FORMATSIZE];
2215 dns_name_format(name, namestr, sizeof(namestr));
2216 fprintf(stderr, "Found zone name: %s\n", namestr);
2219 result = dns_rdataset_first(soaset);
2220 check_result(result, "dns_rdataset_first");
2222 dns_rdata_init(&soarr);
2223 dns_rdataset_current(soaset, &soarr);
2224 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2225 check_result(result, "dns_rdata_tostruct");
2227 dns_name_init(&master, NULL);
2228 dns_name_clone(&soa.origin, &master);
2230 if (userzone != NULL)
2231 zonename = userzone;
2236 char namestr[DNS_NAME_FORMATSIZE];
2237 dns_name_format(&master, namestr, sizeof(namestr));
2238 fprintf(stderr, "The master is: %s\n", namestr);
2241 if (userserver != NULL)
2242 serveraddr = userserver;
2244 char serverstr[DNS_NAME_MAXTEXT+1];
2247 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2248 result = dns_name_totext(&master, ISC_TRUE, &buf);
2249 check_result(result, "dns_name_totext");
2250 serverstr[isc_buffer_usedlength(&buf)] = 0;
2251 get_address(serverstr, DNSDEFAULTPORT, &tempaddr);
2252 serveraddr = &tempaddr;
2254 dns_rdata_freestruct(&soa);
2258 dns_name_init(&tmpzonename, NULL);
2259 dns_name_dup(zonename, mctx, &tmpzonename);
2260 dns_name_init(&restart_master, NULL);
2261 dns_name_dup(&master, mctx, &restart_master);
2262 start_gssrequest(&master);
2264 send_update(zonename, serveraddr, localaddr);
2265 setzoneclass(dns_rdataclass_none);
2268 send_update(zonename, serveraddr, localaddr);
2269 setzoneclass(dns_rdataclass_none);
2272 dns_message_destroy(&soaquery);
2273 dns_request_destroy(&request);
2276 dns_message_destroy(&rcvmsg);
2277 ddebug("Out of recvsoa");
2281 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2282 INSIST(result == ISC_R_SUCCESS);
2284 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2285 nlabels = dns_name_countlabels(name);
2287 fatal("could not find enclosing zone");
2288 dns_name_init(&tname, NULL);
2289 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2290 dns_name_clone(&tname, name);
2291 dns_request_destroy(&request);
2292 dns_message_renderreset(soaquery);
2293 dns_message_settsigkey(soaquery, NULL);
2294 if (userserver != NULL)
2295 sendrequest(localaddr, userserver, soaquery, &request);
2297 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2302 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2303 dns_message_t *msg, dns_request_t **request)
2305 isc_result_t result;
2306 nsu_requestinfo_t *reqinfo;
2308 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2309 if (reqinfo == NULL)
2310 fatal("out of memory");
2312 reqinfo->addr = destaddr;
2313 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2314 (userserver != NULL) ? tsigkey : NULL,
2315 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2316 global_task, recvsoa, reqinfo, request);
2317 check_result(result, "dns_request_createvia");
2323 start_gssrequest(dns_name_t *master)
2325 gss_ctx_id_t context;
2327 isc_result_t result;
2328 isc_uint32_t val = 0;
2329 dns_message_t *rmsg;
2330 dns_request_t *request = NULL;
2331 dns_name_t *servname;
2332 dns_fixedname_t fname;
2333 char namestr[DNS_NAME_FORMATSIZE];
2334 char keystr[DNS_NAME_FORMATSIZE];
2336 debug("start_gssrequest");
2339 if (gssring != NULL)
2340 dns_tsigkeyring_destroy(&gssring);
2342 result = dns_tsigkeyring_create(mctx, &gssring);
2344 if (result != ISC_R_SUCCESS)
2345 fatal("dns_tsigkeyring_create failed: %s",
2346 isc_result_totext(result));
2348 dns_name_format(master, namestr, sizeof(namestr));
2349 if (kserver == NULL) {
2350 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2351 if (kserver == NULL)
2352 fatal("out of memory");
2354 if (userserver == NULL)
2355 get_address(namestr, DNSDEFAULTPORT, kserver);
2357 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2359 dns_fixedname_init(&fname);
2360 servname = dns_fixedname_name(&fname);
2362 result = isc_string_printf(servicename, sizeof(servicename),
2363 "DNS/%s%s", namestr, realm ? realm : "");
2364 if (result != ISC_R_SUCCESS)
2365 fatal("isc_string_printf(servicename) failed: %s",
2366 isc_result_totext(result));
2367 isc_buffer_init(&buf, servicename, strlen(servicename));
2368 isc_buffer_add(&buf, strlen(servicename));
2369 result = dns_name_fromtext(servname, &buf, dns_rootname,
2371 if (result != ISC_R_SUCCESS)
2372 fatal("dns_name_fromtext(servname) failed: %s",
2373 isc_result_totext(result));
2375 dns_fixedname_init(&fkname);
2376 keyname = dns_fixedname_name(&fkname);
2378 isc_random_get(&val);
2379 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2381 if (result != ISC_R_SUCCESS)
2382 fatal("isc_string_printf(keystr) failed: %s",
2383 isc_result_totext(result));
2384 isc_buffer_init(&buf, keystr, strlen(keystr));
2385 isc_buffer_add(&buf, strlen(keystr));
2387 result = dns_name_fromtext(keyname, &buf, dns_rootname,
2389 if (result != ISC_R_SUCCESS)
2390 fatal("dns_name_fromtext(keyname) failed: %s",
2391 isc_result_totext(result));
2393 /* Windows doesn't recognize name compression in the key name. */
2394 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2397 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2398 if (result != ISC_R_SUCCESS)
2399 fatal("dns_message_create failed: %s",
2400 isc_result_totext(result));
2402 /* Build first request. */
2403 context = GSS_C_NO_CONTEXT;
2404 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2405 &context, use_win2k_gsstsig);
2406 if (result == ISC_R_FAILURE)
2407 fatal("Check your Kerberos ticket, it may have expired.");
2408 if (result != ISC_R_SUCCESS)
2409 fatal("dns_tkey_buildgssquery failed: %s",
2410 isc_result_totext(result));
2412 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2416 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2417 dns_message_t *msg, dns_request_t **request,
2418 gss_ctx_id_t context)
2420 isc_result_t result;
2421 nsu_gssinfo_t *reqinfo;
2422 unsigned int options = 0;
2424 debug("send_gssrequest");
2425 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2426 if (reqinfo == NULL)
2427 fatal("out of memory");
2429 reqinfo->addr = destaddr;
2430 reqinfo->context = context;
2432 options |= DNS_REQUESTOPT_TCP;
2433 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2434 options, tsigkey, FIND_TIMEOUT * 20,
2435 FIND_TIMEOUT, 3, global_task, recvgss,
2437 check_result(result, "dns_request_createvia3");
2439 show_message(stdout, msg, "Outgoing update query:");
2444 recvgss(isc_task_t *task, isc_event_t *event) {
2445 dns_requestevent_t *reqev = NULL;
2446 dns_request_t *request = NULL;
2447 isc_result_t result, eresult;
2448 dns_message_t *rcvmsg = NULL;
2449 nsu_gssinfo_t *reqinfo;
2450 dns_message_t *tsigquery = NULL;
2451 isc_sockaddr_t *addr;
2452 gss_ctx_id_t context;
2454 dns_name_t *servname;
2455 dns_fixedname_t fname;
2459 ddebug("recvgss()");
2463 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2464 reqev = (dns_requestevent_t *)event;
2465 request = reqev->request;
2466 eresult = reqev->result;
2467 reqinfo = reqev->ev_arg;
2468 tsigquery = reqinfo->msg;
2469 context = reqinfo->context;
2470 addr = reqinfo->addr;
2473 dns_request_destroy(&request);
2474 dns_message_destroy(&tsigquery);
2475 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2476 isc_event_free(&event);
2481 if (eresult != ISC_R_SUCCESS) {
2482 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2484 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2485 fprintf(stderr, "; Communication with %s failed: %s\n",
2486 addrbuf, isc_result_totext(eresult));
2487 if (userserver != NULL)
2488 fatal("could not talk to specified name server");
2489 else if (++ns_inuse >= lwconf->nsnext)
2490 fatal("could not talk to any default name server");
2491 ddebug("Destroying request [%p]", request);
2492 dns_request_destroy(&request);
2493 dns_message_renderreset(tsigquery);
2494 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2496 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2497 isc_event_free(&event);
2500 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2502 isc_event_free(&event);
2505 ddebug("recvgss creating rcvmsg");
2506 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2507 check_result(result, "dns_message_create");
2509 result = dns_request_getresponse(request, rcvmsg,
2510 DNS_MESSAGEPARSE_PRESERVEORDER);
2511 check_result(result, "dns_request_getresponse");
2514 show_message(stderr, rcvmsg,
2515 "recvmsg reply from GSS-TSIG query");
2517 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2518 ddebug("recvgss trying %s GSS-TSIG",
2519 use_win2k_gsstsig ? "Standard" : "Win2k");
2520 if (use_win2k_gsstsig)
2521 use_win2k_gsstsig = ISC_FALSE;
2523 use_win2k_gsstsig = ISC_TRUE;
2524 tried_other_gsstsig = ISC_TRUE;
2525 start_gssrequest(&restart_master);
2529 if (rcvmsg->rcode != dns_rcode_noerror &&
2530 rcvmsg->rcode != dns_rcode_nxdomain)
2531 fatal("response to GSS-TSIG query was unsuccessful");
2534 dns_fixedname_init(&fname);
2535 servname = dns_fixedname_name(&fname);
2536 isc_buffer_init(&buf, servicename, strlen(servicename));
2537 isc_buffer_add(&buf, strlen(servicename));
2538 result = dns_name_fromtext(servname, &buf, dns_rootname,
2540 check_result(result, "dns_name_fromtext");
2543 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2544 &context, &tsigkey, gssring,
2548 case DNS_R_CONTINUE:
2549 send_gssrequest(localaddr, kserver, tsigquery, &request,
2555 * XXXSRA Waaay too much fun here. There's no good
2556 * reason why we need a TSIG here (the people who put
2557 * it into the spec admitted at the time that it was
2558 * not a security issue), and Windows clients don't
2559 * seem to work if named complies with the spec and
2560 * includes the gratuitous TSIG. So we're in the
2561 * bizarre situation of having to choose between
2562 * complying with a useless requirement in the spec
2563 * and interoperating. This is nuts. If we can
2564 * confirm this behavior, we should ask the WG to
2565 * consider removing the requirement for the
2566 * gratuitous TSIG here. For the moment, we ignore
2567 * the TSIG -- this too is a spec violation, but it's
2568 * the least insane thing to do.
2572 * Verify the signature.
2574 rcvmsg->state = DNS_SECTION_ANY;
2575 dns_message_setquerytsig(rcvmsg, NULL);
2576 result = dns_message_settsigkey(rcvmsg, tsigkey);
2577 check_result(result, "dns_message_settsigkey");
2578 result = dns_message_checksig(rcvmsg, NULL);
2579 ddebug("tsig verification: %s", dns_result_totext(result));
2580 check_result(result, "dns_message_checksig");
2583 send_update(&tmpzonename, serveraddr, localaddr);
2584 setzoneclass(dns_rdataclass_none);
2588 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
2592 dns_request_destroy(&request);
2593 dns_message_destroy(&tsigquery);
2595 dns_message_destroy(&rcvmsg);
2596 ddebug("Out of recvgss");
2601 start_update(void) {
2602 isc_result_t result;
2603 dns_rdataset_t *rdataset = NULL;
2604 dns_name_t *name = NULL;
2605 dns_request_t *request = NULL;
2606 dns_message_t *soaquery = NULL;
2607 dns_name_t *firstname;
2608 dns_section_t section = DNS_SECTION_UPDATE;
2610 ddebug("start_update()");
2613 dns_message_destroy(&answer);
2615 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2616 send_update(userzone, userserver, localaddr);
2617 setzoneclass(dns_rdataclass_none);
2621 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2623 check_result(result, "dns_message_create");
2625 if (userserver == NULL)
2626 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2628 result = dns_message_gettempname(soaquery, &name);
2629 check_result(result, "dns_message_gettempname");
2631 result = dns_message_gettemprdataset(soaquery, &rdataset);
2632 check_result(result, "dns_message_gettemprdataset");
2634 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2636 if (userzone != NULL) {
2637 dns_name_init(name, NULL);
2638 dns_name_clone(userzone, name);
2640 dns_rdataset_t *tmprdataset;
2641 result = dns_message_firstname(updatemsg, section);
2642 if (result == ISC_R_NOMORE) {
2643 section = DNS_SECTION_PREREQUISITE;
2644 result = dns_message_firstname(updatemsg, section);
2646 if (result != ISC_R_SUCCESS) {
2647 dns_message_puttempname(soaquery, &name);
2648 dns_rdataset_disassociate(rdataset);
2649 dns_message_puttemprdataset(soaquery, &rdataset);
2650 dns_message_destroy(&soaquery);
2655 dns_message_currentname(updatemsg, section, &firstname);
2656 dns_name_init(name, NULL);
2657 dns_name_clone(firstname, name);
2659 * Looks to see if the first name references a DS record
2660 * and if that name is not the root remove a label as DS
2661 * records live in the parent zone so we need to start our
2662 * search one label up.
2664 tmprdataset = ISC_LIST_HEAD(firstname->list);
2665 if (section == DNS_SECTION_UPDATE &&
2666 !dns_name_equal(firstname, dns_rootname) &&
2667 tmprdataset->type == dns_rdatatype_ds) {
2668 unsigned int labels = dns_name_countlabels(name);
2669 dns_name_getlabelsequence(name, 1, labels - 1, name);
2673 ISC_LIST_INIT(name->list);
2674 ISC_LIST_APPEND(name->list, rdataset, link);
2675 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2677 if (userserver != NULL)
2678 sendrequest(localaddr, userserver, soaquery, &request);
2681 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2687 ddebug("cleanup()");
2690 dns_message_destroy(&answer);
2693 if (tsigkey != NULL) {
2694 ddebug("detach tsigkey x%p", tsigkey);
2695 dns_tsigkey_detach(&tsigkey);
2697 if (gssring != NULL) {
2698 ddebug("Destroying GSS-TSIG keyring");
2699 dns_tsigkeyring_destroy(&gssring);
2701 if (kserver != NULL) {
2702 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2705 if (realm != NULL) {
2706 isc_mem_free(mctx, realm);
2711 ddebug("Shutting down task manager");
2712 isc_taskmgr_destroy(&taskmgr);
2714 ddebug("Destroying event");
2715 isc_event_free(&global_event);
2717 ddebug("Shutting down socket manager");
2718 isc_socketmgr_destroy(&socketmgr);
2720 ddebug("Shutting down timer manager");
2721 isc_timermgr_destroy(&timermgr);
2723 ddebug("Destroying hash context");
2726 ddebug("Destroying name state");
2729 ddebug("Removing log context");
2730 isc_log_destroy(&lctx);
2732 ddebug("Destroying memory context");
2734 isc_mem_stats(mctx, stderr);
2735 isc_mem_destroy(&mctx);
2739 getinput(isc_task_t *task, isc_event_t *event) {
2749 if (global_event == NULL)
2750 global_event = event;
2753 more = user_interaction();
2763 main(int argc, char **argv) {
2764 isc_result_t result;
2765 style = &dns_master_style_debug;
2769 interactive = ISC_TF(isatty(0));
2773 pre_parse_args(argc, argv);
2775 result = isc_mem_create(0, 0, &mctx);
2776 check_result(result, "isc_mem_create");
2778 parse_args(argc, argv, mctx, &entropy);
2782 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2783 check_result(result, "isc_app_onrun");
2785 (void)isc_app_run();