2 * Copyright (C) 2004-2011 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.193.12.3 2011-05-23 22:12:14 each 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>
41 #include <isc/parseint.h>
42 #include <isc/print.h>
43 #include <isc/random.h>
44 #include <isc/region.h>
45 #include <isc/sockaddr.h>
46 #include <isc/socket.h>
47 #include <isc/stdio.h>
48 #include <isc/string.h>
50 #include <isc/timer.h>
51 #include <isc/types.h>
54 #include <isccfg/namedconf.h>
56 #include <dns/callbacks.h>
57 #include <dns/dispatch.h>
58 #include <dns/dnssec.h>
59 #include <dns/events.h>
60 #include <dns/fixedname.h>
62 #include <dns/masterdump.h>
63 #include <dns/message.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatastruct.h>
71 #include <dns/rdatatype.h>
72 #include <dns/request.h>
73 #include <dns/result.h>
79 #include <lwres/lwres.h>
80 #include <lwres/net.h>
83 #include <dst/gssapi.h>
84 #include ISC_PLATFORM_KRB5HEADER
86 #include <bind9/getaddresses.h>
90 #ifdef HAVE_GETADDRINFO
91 #ifdef HAVE_GAISTRERROR
92 #define USE_GETADDRINFO
97 #ifndef USE_GETADDRINFO
98 #ifndef ISC_PLATFORM_NONSTDHERRNO
103 #define MAXCMD (4 * 1024)
104 #define MAXWIRE (64 * 1024)
105 #define PACKETSIZE ((64 * 1024) - 1)
106 #define INITTEXT (2 * 1024)
107 #define MAXTEXT (128 * 1024)
108 #define FIND_TIMEOUT 5
109 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
111 #define DNSDEFAULTPORT 53
113 static isc_uint16_t dnsport = DNSDEFAULTPORT;
116 #define RESOLV_CONF "/etc/resolv.conf"
119 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
120 static isc_boolean_t memdebugging = ISC_FALSE;
121 static isc_boolean_t have_ipv4 = ISC_FALSE;
122 static isc_boolean_t have_ipv6 = ISC_FALSE;
123 static isc_boolean_t is_dst_up = ISC_FALSE;
124 static isc_boolean_t usevc = ISC_FALSE;
125 static isc_boolean_t usegsstsig = ISC_FALSE;
126 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
127 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
128 static isc_boolean_t local_only = ISC_FALSE;
129 static isc_taskmgr_t *taskmgr = NULL;
130 static isc_task_t *global_task = NULL;
131 static isc_event_t *global_event = NULL;
132 static isc_log_t *lctx = NULL;
133 static isc_mem_t *mctx = NULL;
134 static dns_dispatchmgr_t *dispatchmgr = NULL;
135 static dns_requestmgr_t *requestmgr = NULL;
136 static isc_socketmgr_t *socketmgr = NULL;
137 static isc_timermgr_t *timermgr = NULL;
138 static dns_dispatch_t *dispatchv4 = NULL;
139 static dns_dispatch_t *dispatchv6 = NULL;
140 static dns_message_t *updatemsg = NULL;
141 static dns_fixedname_t fuserzone;
142 static dns_name_t *userzone = NULL;
143 static dns_name_t *zonename = NULL;
144 static dns_name_t tmpzonename;
145 static dns_name_t restart_master;
146 static dns_tsig_keyring_t *gssring = NULL;
147 static dns_tsigkey_t *tsigkey = NULL;
148 static dst_key_t *sig0key = NULL;
149 static lwres_context_t *lwctx = NULL;
150 static lwres_conf_t *lwconf;
151 static isc_sockaddr_t *servers;
152 static int ns_inuse = 0;
153 static int ns_total = 0;
154 static isc_sockaddr_t *userserver = NULL;
155 static isc_sockaddr_t *localaddr = NULL;
156 static isc_sockaddr_t *serveraddr = NULL;
157 static isc_sockaddr_t tempaddr;
158 static const char *keyfile = NULL;
159 static char *keystr = NULL;
160 static isc_entropy_t *entropy = NULL;
161 static isc_boolean_t shuttingdown = ISC_FALSE;
163 static isc_boolean_t interactive = ISC_TRUE;
164 static isc_boolean_t seenerror = ISC_FALSE;
165 static const dns_master_style_t *style;
166 static int requests = 0;
167 static unsigned int logdebuglevel = 0;
168 static unsigned int timeout = 300;
169 static unsigned int udp_timeout = 3;
170 static unsigned int udp_retries = 3;
171 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
172 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
173 static dns_message_t *answer = NULL;
174 static isc_uint32_t default_ttl = 0;
175 static isc_boolean_t default_ttl_set = ISC_FALSE;
177 typedef struct nsu_requestinfo {
179 isc_sockaddr_t *addr;
183 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
184 dns_message_t *msg, dns_request_t **request);
186 ISC_PLATFORM_NORETURN_PRE static void
187 fatal(const char *format, ...)
188 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
191 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
194 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
197 static dns_fixedname_t fkname;
198 static isc_sockaddr_t *kserver = NULL;
199 static char *realm = NULL;
200 static char servicename[DNS_NAME_FORMATSIZE];
201 static dns_name_t *keyname;
202 typedef struct nsu_gssinfo {
204 isc_sockaddr_t *addr;
205 gss_ctx_id_t context;
209 start_gssrequest(dns_name_t *master);
211 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
212 dns_message_t *msg, dns_request_t **request,
213 gss_ctx_id_t context);
215 recvgss(isc_task_t *task, isc_event_t *event);
219 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
221 #define STATUS_MORE (isc_uint16_t)0
222 #define STATUS_SEND (isc_uint16_t)1
223 #define STATUS_QUIT (isc_uint16_t)2
224 #define STATUS_SYNTAX (isc_uint16_t)3
226 typedef struct entropysource entropysource_t;
228 struct entropysource {
229 isc_entropysource_t *source;
231 ISC_LINK(entropysource_t) link;
234 static ISC_LIST(entropysource_t) sources;
237 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
240 isc_entropysource_t *source = NULL;
241 entropysource_t *elt;
242 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
244 REQUIRE(ectx != NULL);
247 result = isc_entropy_create(mctx, ectx);
248 if (result != ISC_R_SUCCESS)
249 fatal("could not create entropy object");
250 ISC_LIST_INIT(sources);
253 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
254 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
258 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
261 if (result != ISC_R_SUCCESS)
262 fatal("could not initialize entropy source: %s",
263 isc_result_totext(result));
265 if (source != NULL) {
266 elt = isc_mem_get(mctx, sizeof(*elt));
268 fatal("out of memory");
269 elt->source = source;
271 ISC_LINK_INIT(elt, link);
272 ISC_LIST_APPEND(sources, elt, link);
277 cleanup_entropy(isc_entropy_t **ectx) {
278 entropysource_t *source;
279 while (!ISC_LIST_EMPTY(sources)) {
280 source = ISC_LIST_HEAD(sources);
281 ISC_LIST_UNLINK(sources, source, link);
282 isc_entropy_destroysource(&source->source);
283 isc_mem_put(source->mctx, source, sizeof(*source));
285 isc_entropy_detach(ectx);
289 static dns_rdataclass_t
291 if (zoneclass == dns_rdataclass_none)
292 zoneclass = defaultclass;
297 setzoneclass(dns_rdataclass_t rdclass) {
298 if (zoneclass == dns_rdataclass_none ||
299 rdclass == dns_rdataclass_none)
301 if (zoneclass != rdclass)
307 fatal(const char *format, ...) {
310 va_start(args, format);
311 vfprintf(stderr, format, args);
313 fprintf(stderr, "\n");
318 error(const char *format, ...) {
321 va_start(args, format);
322 vfprintf(stderr, format, args);
324 fprintf(stderr, "\n");
328 debug(const char *format, ...) {
332 va_start(args, format);
333 vfprintf(stderr, format, args);
335 fprintf(stderr, "\n");
340 ddebug(const char *format, ...) {
344 va_start(args, format);
345 vfprintf(stderr, format, args);
347 fprintf(stderr, "\n");
352 check_result(isc_result_t result, const char *msg) {
353 if (result != ISC_R_SUCCESS)
354 fatal("%s: %s", msg, isc_result_totext(result));
358 mem_alloc(void *arg, size_t size) {
359 return (isc_mem_get(arg, size));
363 mem_free(void *arg, void *mem, size_t size) {
364 isc_mem_put(arg, mem, size);
368 nsu_strsep(char **stringp, const char *delim) {
369 char *string = *stringp;
377 for (; *string != '\0'; string++) {
379 for (d = delim; (dc = *d) != '\0'; d++) {
387 for (s = string; *s != '\0'; s++) {
389 for (d = delim; (dc = *d) != '\0'; d++) {
405 ddebug("reset_system()");
406 /* If the update message is still around, destroy it */
407 if (updatemsg != NULL)
408 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
410 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
412 check_result(result, "dns_message_create");
414 updatemsg->opcode = dns_opcode_update;
417 dns_tsigkey_detach(&tsigkey);
419 dns_tsigkeyring_detach(&gssring);
420 tried_other_gsstsig = ISC_FALSE;
425 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
426 isc_uint16_t digestbits = 0;
430 REQUIRE(hmac != NULL && *hmac == NULL);
431 REQUIRE(hmacstr != NULL);
433 if (len >= sizeof(buf))
434 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
436 strncpy(buf, hmacstr, len);
439 if (strcasecmp(buf, "hmac-md5") == 0) {
440 *hmac = DNS_TSIG_HMACMD5_NAME;
441 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
442 *hmac = DNS_TSIG_HMACMD5_NAME;
443 result = isc_parse_uint16(&digestbits, &buf[9], 10);
444 if (result != ISC_R_SUCCESS || digestbits > 128)
445 fatal("digest-bits out of range [0..128]");
446 digestbits = (digestbits +7) & ~0x7U;
447 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
448 *hmac = DNS_TSIG_HMACSHA1_NAME;
449 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
450 *hmac = DNS_TSIG_HMACSHA1_NAME;
451 result = isc_parse_uint16(&digestbits, &buf[10], 10);
452 if (result != ISC_R_SUCCESS || digestbits > 160)
453 fatal("digest-bits out of range [0..160]");
454 digestbits = (digestbits +7) & ~0x7U;
455 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
456 *hmac = DNS_TSIG_HMACSHA224_NAME;
457 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
458 *hmac = DNS_TSIG_HMACSHA224_NAME;
459 result = isc_parse_uint16(&digestbits, &buf[12], 10);
460 if (result != ISC_R_SUCCESS || digestbits > 224)
461 fatal("digest-bits out of range [0..224]");
462 digestbits = (digestbits +7) & ~0x7U;
463 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
464 *hmac = DNS_TSIG_HMACSHA256_NAME;
465 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
466 *hmac = DNS_TSIG_HMACSHA256_NAME;
467 result = isc_parse_uint16(&digestbits, &buf[12], 10);
468 if (result != ISC_R_SUCCESS || digestbits > 256)
469 fatal("digest-bits out of range [0..256]");
470 digestbits = (digestbits +7) & ~0x7U;
471 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
472 *hmac = DNS_TSIG_HMACSHA384_NAME;
473 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
474 *hmac = DNS_TSIG_HMACSHA384_NAME;
475 result = isc_parse_uint16(&digestbits, &buf[12], 10);
476 if (result != ISC_R_SUCCESS || digestbits > 384)
477 fatal("digest-bits out of range [0..384]");
478 digestbits = (digestbits +7) & ~0x7U;
479 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
480 *hmac = DNS_TSIG_HMACSHA512_NAME;
481 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
482 *hmac = DNS_TSIG_HMACSHA512_NAME;
483 result = isc_parse_uint16(&digestbits, &buf[12], 10);
484 if (result != ISC_R_SUCCESS || digestbits > 512)
485 fatal("digest-bits out of range [0..512]");
486 digestbits = (digestbits +7) & ~0x7U;
488 fatal("unknown key type '%s'", buf);
493 basenamelen(const char *file) {
494 int len = strlen(file);
496 if (len > 1 && file[len - 1] == '.')
498 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
500 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
507 unsigned char *secret = NULL;
509 isc_buffer_t secretbuf;
511 isc_buffer_t keynamesrc;
514 dns_fixedname_t fkeyname;
517 dns_name_t *hmacname = NULL;
518 isc_uint16_t digestbits = 0;
520 dns_fixedname_init(&fkeyname);
521 keyname = dns_fixedname_name(&fkeyname);
523 debug("Creating key...");
525 s = strchr(keystr, ':');
526 if (s == NULL || s == keystr || s[1] == 0)
527 fatal("key option must specify [hmac:]keyname:secret");
529 n = strchr(secretstr, ':');
531 if (n == secretstr || n[1] == 0)
532 fatal("key option must specify [hmac:]keyname:secret");
535 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
537 hmacname = DNS_TSIG_HMACMD5_NAME;
542 isc_buffer_init(&keynamesrc, name, n - name);
543 isc_buffer_add(&keynamesrc, n - name);
545 debug("namefromtext");
546 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, 0, NULL);
547 check_result(result, "dns_name_fromtext");
549 secretlen = strlen(secretstr) * 3 / 4;
550 secret = isc_mem_allocate(mctx, secretlen);
552 fatal("out of memory");
554 isc_buffer_init(&secretbuf, secret, secretlen);
555 result = isc_base64_decodestring(secretstr, &secretbuf);
556 if (result != ISC_R_SUCCESS) {
557 fprintf(stderr, "could not create key from %s: %s\n",
558 keystr, isc_result_totext(result));
562 secretlen = isc_buffer_usedlength(&secretbuf);
565 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
566 ISC_FALSE, NULL, 0, 0, mctx, NULL,
568 if (result != ISC_R_SUCCESS)
569 fprintf(stderr, "could not create key from %s: %s\n",
570 keystr, dns_result_totext(result));
572 dst_key_setbits(tsigkey->key, digestbits);
575 isc_mem_free(mctx, secret);
579 * Get a key from a named.conf format keyfile
582 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
583 cfg_parser_t *pctx = NULL;
584 cfg_obj_t *sessionkey = NULL;
585 const cfg_obj_t *key = NULL;
586 const cfg_obj_t *secretobj = NULL;
587 const cfg_obj_t *algorithmobj = NULL;
589 const char *secretstr;
590 const char *algorithm;
594 if (! isc_file_exists(keyfile))
595 return (ISC_R_FILENOTFOUND);
597 result = cfg_parser_create(mctx, lctx, &pctx);
598 if (result != ISC_R_SUCCESS)
601 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
603 if (result != ISC_R_SUCCESS)
606 result = cfg_map_get(sessionkey, "key", &key);
607 if (result != ISC_R_SUCCESS)
610 (void) cfg_map_get(key, "secret", &secretobj);
611 (void) cfg_map_get(key, "algorithm", &algorithmobj);
612 if (secretobj == NULL || algorithmobj == NULL)
613 fatal("key must have algorithm and secret");
615 keyname = cfg_obj_asstring(cfg_map_getname(key));
616 secretstr = cfg_obj_asstring(secretobj);
617 algorithm = cfg_obj_asstring(algorithmobj);
619 len = strlen(algorithm) + strlen(keyname) + strlen(secretstr) + 3;
620 keystr = isc_mem_allocate(mctx, len);
621 snprintf(keystr, len, "%s:%s:%s", algorithm, keyname, secretstr);
626 if (sessionkey != NULL)
627 cfg_obj_destroy(pctx, &sessionkey);
628 cfg_parser_destroy(&pctx);
632 isc_mem_free(mctx, keystr);
638 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
639 dst_key_t *dstkey = NULL;
641 dns_name_t *hmacname = NULL;
643 debug("Creating key...");
646 dst_key_free(&sig0key);
648 /* Try reading the key from a K* pair */
649 result = dst_key_fromnamedfile(keyfile, NULL,
650 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
653 /* If that didn't work, try reading it as a session.key keyfile */
654 if (result != ISC_R_SUCCESS) {
655 result = read_sessionkey(mctx, lctx);
656 if (result == ISC_R_SUCCESS)
660 if (result != ISC_R_SUCCESS) {
661 fprintf(stderr, "could not read key from %.*s.{private,key}: "
662 "%s\n", basenamelen(keyfile), keyfile,
663 isc_result_totext(result));
667 switch (dst_key_alg(dstkey)) {
668 case DST_ALG_HMACMD5:
669 hmacname = DNS_TSIG_HMACMD5_NAME;
671 case DST_ALG_HMACSHA1:
672 hmacname = DNS_TSIG_HMACSHA1_NAME;
674 case DST_ALG_HMACSHA224:
675 hmacname = DNS_TSIG_HMACSHA224_NAME;
677 case DST_ALG_HMACSHA256:
678 hmacname = DNS_TSIG_HMACSHA256_NAME;
680 case DST_ALG_HMACSHA384:
681 hmacname = DNS_TSIG_HMACSHA384_NAME;
683 case DST_ALG_HMACSHA512:
684 hmacname = DNS_TSIG_HMACSHA512_NAME;
687 if (hmacname != NULL) {
688 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
689 hmacname, dstkey, ISC_FALSE,
690 NULL, 0, 0, mctx, NULL,
692 dst_key_free(&dstkey);
693 if (result != ISC_R_SUCCESS) {
694 fprintf(stderr, "could not create key from %s: %s\n",
695 keyfile, isc_result_totext(result));
699 dst_key_attach(dstkey, &sig0key);
700 dst_key_free(&dstkey);
706 isc_task_detach(&global_task);
708 if (userserver != NULL)
709 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
711 if (localaddr != NULL)
712 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
714 if (tsigkey != NULL) {
715 ddebug("Freeing TSIG key");
716 dns_tsigkey_detach(&tsigkey);
719 if (sig0key != NULL) {
720 ddebug("Freeing SIG(0) key");
721 dst_key_free(&sig0key);
724 if (updatemsg != NULL)
725 dns_message_destroy(&updatemsg);
728 ddebug("Destroy DST lib");
730 is_dst_up = ISC_FALSE;
733 cleanup_entropy(&entropy);
735 lwres_conf_clear(lwctx);
736 lwres_context_destroy(&lwctx);
738 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
740 ddebug("Destroying request manager");
741 dns_requestmgr_detach(&requestmgr);
743 ddebug("Freeing the dispatchers");
745 dns_dispatch_detach(&dispatchv4);
747 dns_dispatch_detach(&dispatchv6);
749 ddebug("Shutting down dispatch manager");
750 dns_dispatchmgr_destroy(&dispatchmgr);
755 maybeshutdown(void) {
756 ddebug("Shutting down request manager");
757 dns_requestmgr_shutdown(requestmgr);
766 shutdown_program(isc_task_t *task, isc_event_t *event) {
767 REQUIRE(task == global_task);
770 ddebug("shutdown_program()");
771 isc_event_free(&event);
773 shuttingdown = ISC_TRUE;
780 isc_sockaddr_t bind_any, bind_any6;
781 lwres_result_t lwresult;
782 unsigned int attrs, attrmask;
784 isc_logconfig_t *logconfig = NULL;
786 ddebug("setup_system()");
788 dns_result_register();
790 result = isc_net_probeipv4();
791 if (result == ISC_R_SUCCESS)
792 have_ipv4 = ISC_TRUE;
794 result = isc_net_probeipv6();
795 if (result == ISC_R_SUCCESS)
796 have_ipv6 = ISC_TRUE;
798 if (!have_ipv4 && !have_ipv6)
799 fatal("could not find either IPv4 or IPv6");
801 result = isc_log_create(mctx, &lctx, &logconfig);
802 check_result(result, "isc_log_create");
804 isc_log_setcontext(lctx);
806 dns_log_setcontext(lctx);
808 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
809 check_result(result, "isc_log_usechannel");
811 isc_log_setdebuglevel(lctx, logdebuglevel);
813 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
814 if (lwresult != LWRES_R_SUCCESS)
815 fatal("lwres_context_create failed");
817 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
818 lwconf = lwres_conf_get(lwctx);
820 ns_total = lwconf->nsnext;
822 /* No name servers in resolv.conf; default to loopback. */
823 struct in_addr localhost;
825 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
827 fatal("out of memory");
828 localhost.s_addr = htonl(INADDR_LOOPBACK);
829 isc_sockaddr_fromin(&servers[0], &localhost, dnsport);
831 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
833 fatal("out of memory");
834 for (i = 0; i < ns_total; i++) {
835 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
837 memcpy(&in4, lwconf->nameservers[i].address, 4);
838 isc_sockaddr_fromin(&servers[i], &in4, dnsport);
841 memcpy(&in6, lwconf->nameservers[i].address, 16);
842 isc_sockaddr_fromin6(&servers[i], &in6,
848 setup_entropy(mctx, NULL, &entropy);
850 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
851 check_result(result, "isc_hash_create");
854 result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
855 check_result(result, "dns_dispatchmgr_create");
857 result = isc_socketmgr_create(mctx, &socketmgr);
858 check_result(result, "dns_socketmgr_create");
860 result = isc_timermgr_create(mctx, &timermgr);
861 check_result(result, "dns_timermgr_create");
863 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
864 check_result(result, "isc_taskmgr_create");
866 result = isc_task_create(taskmgr, 0, &global_task);
867 check_result(result, "isc_task_create");
869 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
870 check_result(result, "isc_task_onshutdown");
872 result = dst_lib_init(mctx, entropy, 0);
873 check_result(result, "dst_lib_init");
874 is_dst_up = ISC_TRUE;
876 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
877 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
880 attrs = DNS_DISPATCHATTR_UDP;
881 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
882 attrs |= DNS_DISPATCHATTR_IPV6;
883 isc_sockaddr_any6(&bind_any6);
884 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
885 &bind_any6, PACKETSIZE,
887 attrs, attrmask, &dispatchv6);
888 check_result(result, "dns_dispatch_getudp (v6)");
892 attrs = DNS_DISPATCHATTR_UDP;
893 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
894 attrs |= DNS_DISPATCHATTR_IPV4;
895 isc_sockaddr_any(&bind_any);
896 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
897 &bind_any, PACKETSIZE,
899 attrs, attrmask, &dispatchv4);
900 check_result(result, "dns_dispatch_getudp (v4)");
903 result = dns_requestmgr_create(mctx, timermgr,
904 socketmgr, taskmgr, dispatchmgr,
905 dispatchv4, dispatchv6, &requestmgr);
906 check_result(result, "dns_requestmgr_create");
910 else if (local_only) {
911 result = read_sessionkey(mctx, lctx);
912 if (result != ISC_R_SUCCESS)
913 fatal("can't read key from %s: %s\n",
914 keyfile, isc_result_totext(result));
915 } else if (keyfile != NULL)
916 setup_keyfile(mctx, lctx);
920 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
925 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
927 if (result != ISC_R_SUCCESS)
928 fatal("couldn't get address for '%s': %s",
929 host, isc_result_totext(result));
933 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:"
936 pre_parse_args(int argc, char **argv) {
939 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
941 case 'M': /* was -dm */
942 debugging = ISC_TRUE;
943 ddebugging = ISC_TRUE;
944 memdebugging = ISC_TRUE;
945 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
951 if (isc_commandline_option != '?')
952 fprintf(stderr, "%s: invalid argument -%c\n",
953 argv[0], isc_commandline_option);
954 fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
955 "[-g | -o | -y keyname:secret | -k keyfile] "
956 "[-v] [filename]\n");
963 isc_commandline_reset = ISC_TRUE;
964 isc_commandline_index = 1;
968 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
974 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
977 debugging = ISC_TRUE;
979 case 'D': /* was -dd */
980 debugging = ISC_TRUE;
981 ddebugging = ISC_TRUE;
986 local_only = ISC_TRUE;
989 result = isc_parse_uint32(&i, isc_commandline_argument,
991 if (result != ISC_R_SUCCESS) {
992 fprintf(stderr, "bad library debug value "
993 "'%s'\n", isc_commandline_argument);
999 keystr = isc_commandline_argument;
1005 keyfile = isc_commandline_argument;
1008 usegsstsig = ISC_TRUE;
1009 use_win2k_gsstsig = ISC_FALSE;
1012 usegsstsig = ISC_TRUE;
1013 use_win2k_gsstsig = ISC_TRUE;
1016 result = isc_parse_uint16(&dnsport,
1017 isc_commandline_argument, 10);
1018 if (result != ISC_R_SUCCESS) {
1019 fprintf(stderr, "bad port number "
1020 "'%s'\n", isc_commandline_argument);
1025 result = isc_parse_uint32(&timeout,
1026 isc_commandline_argument, 10);
1027 if (result != ISC_R_SUCCESS) {
1028 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
1035 result = isc_parse_uint32(&udp_timeout,
1036 isc_commandline_argument, 10);
1037 if (result != ISC_R_SUCCESS) {
1038 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
1041 if (udp_timeout == 0)
1042 udp_timeout = UINT_MAX;
1045 result = isc_parse_uint32(&udp_retries,
1046 isc_commandline_argument, 10);
1047 if (result != ISC_R_SUCCESS) {
1048 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
1054 setup_entropy(mctx, isc_commandline_argument, ectx);
1058 fprintf(stderr, "%s: unhandled option: %c\n",
1059 argv[0], isc_commandline_option);
1063 if (keyfile != NULL && keystr != NULL) {
1064 fprintf(stderr, "%s: cannot specify both -k and -y\n",
1070 struct in_addr localhost;
1072 if (keyfile == NULL)
1073 keyfile = SESSION_KEYFILE;
1075 if (userserver == NULL) {
1076 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1077 if (userserver == NULL)
1078 fatal("out of memory");
1081 localhost.s_addr = htonl(INADDR_LOOPBACK);
1082 isc_sockaddr_fromin(userserver, &localhost, dnsport);
1086 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1087 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1093 fprintf(stderr, "%s: cannot specify -g or -o, " \
1094 "program not linked with GSS API Library\n",
1100 if (argv[isc_commandline_index] != NULL) {
1101 if (strcmp(argv[isc_commandline_index], "-") == 0) {
1104 result = isc_stdio_open(argv[isc_commandline_index],
1106 if (result != ISC_R_SUCCESS) {
1107 fprintf(stderr, "could not open '%s': %s\n",
1108 argv[isc_commandline_index],
1109 isc_result_totext(result));
1113 interactive = ISC_FALSE;
1118 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1119 isc_result_t result;
1121 isc_buffer_t *namebuf = NULL;
1122 isc_buffer_t source;
1124 word = nsu_strsep(cmdlinep, " \t\r\n");
1126 fprintf(stderr, "could not read owner name\n");
1127 return (STATUS_SYNTAX);
1130 result = dns_message_gettempname(msg, namep);
1131 check_result(result, "dns_message_gettempname");
1132 result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
1133 check_result(result, "isc_buffer_allocate");
1134 dns_name_init(*namep, NULL);
1135 dns_name_setbuffer(*namep, namebuf);
1136 dns_message_takebuffer(msg, &namebuf);
1137 isc_buffer_init(&source, word, strlen(word));
1138 isc_buffer_add(&source, strlen(word));
1139 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
1140 check_result(result, "dns_name_fromtext");
1141 isc_buffer_invalidate(&source);
1142 return (STATUS_MORE);
1146 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1147 dns_rdatatype_t rdatatype, dns_message_t *msg,
1150 char *cmdline = *cmdlinep;
1151 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1153 isc_lex_t *lex = NULL;
1154 dns_rdatacallbacks_t callbacks;
1155 isc_result_t result;
1157 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1160 if (*cmdline != 0) {
1161 dns_rdatacallbacks_init(&callbacks);
1162 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1163 check_result(result, "isc_lex_create");
1164 isc_buffer_init(&source, cmdline, strlen(cmdline));
1165 isc_buffer_add(&source, strlen(cmdline));
1166 result = isc_lex_openbuffer(lex, &source);
1167 check_result(result, "isc_lex_openbuffer");
1168 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1169 check_result(result, "isc_buffer_allocate");
1170 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1171 dns_rootname, 0, mctx, buf,
1173 isc_lex_destroy(&lex);
1174 if (result == ISC_R_SUCCESS) {
1175 isc_buffer_usedregion(buf, &r);
1176 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1177 check_result(result, "isc_buffer_allocate");
1178 isc_buffer_putmem(newbuf, r.base, r.length);
1179 isc_buffer_usedregion(newbuf, &r);
1180 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1181 isc_buffer_free(&buf);
1182 dns_message_takebuffer(msg, &newbuf);
1184 fprintf(stderr, "invalid rdata format: %s\n",
1185 isc_result_totext(result));
1186 isc_buffer_free(&buf);
1187 return (STATUS_SYNTAX);
1190 rdata->flags = DNS_RDATA_UPDATE;
1192 *cmdlinep = cmdline;
1193 return (STATUS_MORE);
1197 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1198 isc_result_t result;
1200 dns_name_t *name = NULL;
1201 isc_textregion_t region;
1202 dns_rdataset_t *rdataset = NULL;
1203 dns_rdatalist_t *rdatalist = NULL;
1204 dns_rdataclass_t rdataclass;
1205 dns_rdatatype_t rdatatype;
1206 dns_rdata_t *rdata = NULL;
1207 isc_uint16_t retval;
1209 ddebug("make_prereq()");
1212 * Read the owner name
1214 retval = parse_name(&cmdline, updatemsg, &name);
1215 if (retval != STATUS_MORE)
1219 * If this is an rrset prereq, read the class or type.
1222 word = nsu_strsep(&cmdline, " \t\r\n");
1224 fprintf(stderr, "could not read class or type\n");
1228 region.length = strlen(word);
1229 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1230 if (result == ISC_R_SUCCESS) {
1231 if (!setzoneclass(rdataclass)) {
1232 fprintf(stderr, "class mismatch: %s\n", word);
1236 * Now read the type.
1238 word = nsu_strsep(&cmdline, " \t\r\n");
1240 fprintf(stderr, "could not read type\n");
1244 region.length = strlen(word);
1245 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1246 if (result != ISC_R_SUCCESS) {
1247 fprintf(stderr, "invalid type: %s\n", word);
1251 rdataclass = getzoneclass();
1252 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1253 if (result != ISC_R_SUCCESS) {
1254 fprintf(stderr, "invalid type: %s\n", word);
1259 rdatatype = dns_rdatatype_any;
1261 result = dns_message_gettemprdata(updatemsg, &rdata);
1262 check_result(result, "dns_message_gettemprdata");
1264 dns_rdata_init(rdata);
1266 if (isrrset && ispositive) {
1267 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1269 if (retval != STATUS_MORE)
1272 rdata->flags = DNS_RDATA_UPDATE;
1274 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1275 check_result(result, "dns_message_gettemprdatalist");
1276 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1277 check_result(result, "dns_message_gettemprdataset");
1278 dns_rdatalist_init(rdatalist);
1279 rdatalist->type = rdatatype;
1281 if (isrrset && rdata->data != NULL)
1282 rdatalist->rdclass = rdataclass;
1284 rdatalist->rdclass = dns_rdataclass_any;
1286 rdatalist->rdclass = dns_rdataclass_none;
1287 rdatalist->covers = 0;
1289 rdata->rdclass = rdatalist->rdclass;
1290 rdata->type = rdatatype;
1291 ISC_LIST_INIT(rdatalist->rdata);
1292 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1293 dns_rdataset_init(rdataset);
1294 dns_rdatalist_tordataset(rdatalist, rdataset);
1295 ISC_LIST_INIT(name->list);
1296 ISC_LIST_APPEND(name->list, rdataset, link);
1297 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1298 return (STATUS_MORE);
1302 dns_message_puttempname(updatemsg, &name);
1303 return (STATUS_SYNTAX);
1307 evaluate_prereq(char *cmdline) {
1309 isc_boolean_t ispositive, isrrset;
1311 ddebug("evaluate_prereq()");
1312 word = nsu_strsep(&cmdline, " \t\r\n");
1314 fprintf(stderr, "could not read operation code\n");
1315 return (STATUS_SYNTAX);
1317 if (strcasecmp(word, "nxdomain") == 0) {
1318 ispositive = ISC_FALSE;
1319 isrrset = ISC_FALSE;
1320 } else if (strcasecmp(word, "yxdomain") == 0) {
1321 ispositive = ISC_TRUE;
1322 isrrset = ISC_FALSE;
1323 } else if (strcasecmp(word, "nxrrset") == 0) {
1324 ispositive = ISC_FALSE;
1326 } else if (strcasecmp(word, "yxrrset") == 0) {
1327 ispositive = ISC_TRUE;
1330 fprintf(stderr, "incorrect operation code: %s\n", word);
1331 return (STATUS_SYNTAX);
1333 return (make_prereq(cmdline, ispositive, isrrset));
1337 evaluate_server(char *cmdline) {
1338 char *word, *server;
1342 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1343 return (STATUS_SYNTAX);
1346 word = nsu_strsep(&cmdline, " \t\r\n");
1348 fprintf(stderr, "could not read server name\n");
1349 return (STATUS_SYNTAX);
1353 word = nsu_strsep(&cmdline, " \t\r\n");
1358 port = strtol(word, &endp, 10);
1360 fprintf(stderr, "port '%s' is not numeric\n", word);
1361 return (STATUS_SYNTAX);
1362 } else if (port < 1 || port > 65535) {
1363 fprintf(stderr, "port '%s' is out of range "
1364 "(1 to 65535)\n", word);
1365 return (STATUS_SYNTAX);
1369 if (userserver == NULL) {
1370 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1371 if (userserver == NULL)
1372 fatal("out of memory");
1375 get_address(server, (in_port_t)port, userserver);
1377 return (STATUS_MORE);
1381 evaluate_local(char *cmdline) {
1385 struct in6_addr in6;
1387 word = nsu_strsep(&cmdline, " \t\r\n");
1389 fprintf(stderr, "could not read server name\n");
1390 return (STATUS_SYNTAX);
1394 word = nsu_strsep(&cmdline, " \t\r\n");
1399 port = strtol(word, &endp, 10);
1401 fprintf(stderr, "port '%s' is not numeric\n", word);
1402 return (STATUS_SYNTAX);
1403 } else if (port < 1 || port > 65535) {
1404 fprintf(stderr, "port '%s' is out of range "
1405 "(1 to 65535)\n", word);
1406 return (STATUS_SYNTAX);
1410 if (localaddr == NULL) {
1411 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1412 if (localaddr == NULL)
1413 fatal("out of memory");
1416 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1417 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1418 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1419 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1421 fprintf(stderr, "invalid address %s", local);
1422 return (STATUS_SYNTAX);
1425 return (STATUS_MORE);
1429 evaluate_key(char *cmdline) {
1433 isc_result_t result;
1434 dns_fixedname_t fkeyname;
1435 dns_name_t *keyname;
1437 unsigned char *secret = NULL;
1438 isc_buffer_t secretbuf;
1439 dns_name_t *hmacname = NULL;
1440 isc_uint16_t digestbits = 0;
1443 namestr = nsu_strsep(&cmdline, " \t\r\n");
1444 if (*namestr == 0) {
1445 fprintf(stderr, "could not read key name\n");
1446 return (STATUS_SYNTAX);
1449 dns_fixedname_init(&fkeyname);
1450 keyname = dns_fixedname_name(&fkeyname);
1452 n = strchr(namestr, ':');
1454 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1457 hmacname = DNS_TSIG_HMACMD5_NAME;
1459 isc_buffer_init(&b, namestr, strlen(namestr));
1460 isc_buffer_add(&b, strlen(namestr));
1461 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
1462 if (result != ISC_R_SUCCESS) {
1463 fprintf(stderr, "could not parse key name\n");
1464 return (STATUS_SYNTAX);
1467 secretstr = nsu_strsep(&cmdline, "\r\n");
1468 if (*secretstr == 0) {
1469 fprintf(stderr, "could not read key secret\n");
1470 return (STATUS_SYNTAX);
1472 secretlen = strlen(secretstr) * 3 / 4;
1473 secret = isc_mem_allocate(mctx, secretlen);
1475 fatal("out of memory");
1477 isc_buffer_init(&secretbuf, secret, secretlen);
1478 result = isc_base64_decodestring(secretstr, &secretbuf);
1479 if (result != ISC_R_SUCCESS) {
1480 fprintf(stderr, "could not create key from %s: %s\n",
1481 secretstr, isc_result_totext(result));
1482 isc_mem_free(mctx, secret);
1483 return (STATUS_SYNTAX);
1485 secretlen = isc_buffer_usedlength(&secretbuf);
1487 if (tsigkey != NULL)
1488 dns_tsigkey_detach(&tsigkey);
1489 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1490 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1492 isc_mem_free(mctx, secret);
1493 if (result != ISC_R_SUCCESS) {
1494 fprintf(stderr, "could not create key from %s %s: %s\n",
1495 namestr, secretstr, dns_result_totext(result));
1496 return (STATUS_SYNTAX);
1498 dst_key_setbits(tsigkey->key, digestbits);
1499 return (STATUS_MORE);
1503 evaluate_zone(char *cmdline) {
1506 isc_result_t result;
1508 word = nsu_strsep(&cmdline, " \t\r\n");
1510 fprintf(stderr, "could not read zone name\n");
1511 return (STATUS_SYNTAX);
1514 dns_fixedname_init(&fuserzone);
1515 userzone = dns_fixedname_name(&fuserzone);
1516 isc_buffer_init(&b, word, strlen(word));
1517 isc_buffer_add(&b, strlen(word));
1518 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1519 if (result != ISC_R_SUCCESS) {
1520 userzone = NULL; /* Lest it point to an invalid name */
1521 fprintf(stderr, "could not parse zone name\n");
1522 return (STATUS_SYNTAX);
1525 return (STATUS_MORE);
1529 evaluate_realm(char *cmdline) {
1534 word = nsu_strsep(&cmdline, " \t\r\n");
1537 isc_mem_free(mctx, realm);
1539 return (STATUS_MORE);
1542 snprintf(buf, sizeof(buf), "@%s", word);
1543 realm = isc_mem_strdup(mctx, buf);
1545 fatal("out of memory");
1546 return (STATUS_MORE);
1549 return (STATUS_SYNTAX);
1554 evaluate_ttl(char *cmdline) {
1556 isc_result_t result;
1559 word = nsu_strsep(&cmdline, " \t\r\n");
1561 fprintf(stderr, "could not ttl\n");
1562 return (STATUS_SYNTAX);
1565 if (!strcasecmp(word, "none")) {
1567 default_ttl_set = ISC_FALSE;
1568 return (STATUS_MORE);
1571 result = isc_parse_uint32(&ttl, word, 10);
1572 if (result != ISC_R_SUCCESS)
1573 return (STATUS_SYNTAX);
1575 if (ttl > TTL_MAX) {
1576 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1578 return (STATUS_SYNTAX);
1581 default_ttl_set = ISC_TRUE;
1583 return (STATUS_MORE);
1587 evaluate_class(char *cmdline) {
1590 isc_result_t result;
1591 dns_rdataclass_t rdclass;
1593 word = nsu_strsep(&cmdline, " \t\r\n");
1595 fprintf(stderr, "could not read class name\n");
1596 return (STATUS_SYNTAX);
1600 r.length = strlen(word);
1601 result = dns_rdataclass_fromtext(&rdclass, &r);
1602 if (result != ISC_R_SUCCESS) {
1603 fprintf(stderr, "could not parse class name: %s\n", word);
1604 return (STATUS_SYNTAX);
1607 case dns_rdataclass_none:
1608 case dns_rdataclass_any:
1609 case dns_rdataclass_reserved0:
1610 fprintf(stderr, "bad default class: %s\n", word);
1611 return (STATUS_SYNTAX);
1613 defaultclass = rdclass;
1616 return (STATUS_MORE);
1620 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1621 isc_result_t result;
1622 dns_name_t *name = NULL;
1625 dns_rdataclass_t rdataclass;
1626 dns_rdatatype_t rdatatype;
1627 dns_rdata_t *rdata = NULL;
1628 dns_rdatalist_t *rdatalist = NULL;
1629 dns_rdataset_t *rdataset = NULL;
1630 isc_textregion_t region;
1631 isc_uint16_t retval;
1633 ddebug("update_addordelete()");
1636 * Read the owner name.
1638 retval = parse_name(&cmdline, updatemsg, &name);
1639 if (retval != STATUS_MORE)
1642 result = dns_message_gettemprdata(updatemsg, &rdata);
1643 check_result(result, "dns_message_gettemprdata");
1645 dns_rdata_init(rdata);
1648 * If this is an add, read the TTL and verify that it's in range.
1649 * If it's a delete, ignore a TTL if present (for compatibility).
1651 word = nsu_strsep(&cmdline, " \t\r\n");
1654 fprintf(stderr, "could not read owner ttl\n");
1659 rdataclass = dns_rdataclass_any;
1660 rdatatype = dns_rdatatype_any;
1661 rdata->flags = DNS_RDATA_UPDATE;
1665 result = isc_parse_uint32(&ttl, word, 10);
1666 if (result != ISC_R_SUCCESS) {
1670 } else if (default_ttl_set) {
1674 fprintf(stderr, "ttl '%s': %s\n", word,
1675 isc_result_totext(result));
1682 else if (ttl > TTL_MAX) {
1683 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1689 * Read the class or type.
1691 word = nsu_strsep(&cmdline, " \t\r\n");
1695 rdataclass = dns_rdataclass_any;
1696 rdatatype = dns_rdatatype_any;
1697 rdata->flags = DNS_RDATA_UPDATE;
1700 fprintf(stderr, "could not read class or type\n");
1705 region.length = strlen(word);
1706 rdataclass = dns_rdataclass_any;
1707 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1708 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1709 if (!setzoneclass(rdataclass)) {
1710 fprintf(stderr, "class mismatch: %s\n", word);
1714 * Now read the type.
1716 word = nsu_strsep(&cmdline, " \t\r\n");
1719 rdataclass = dns_rdataclass_any;
1720 rdatatype = dns_rdatatype_any;
1721 rdata->flags = DNS_RDATA_UPDATE;
1724 fprintf(stderr, "could not read type\n");
1729 region.length = strlen(word);
1730 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1731 if (result != ISC_R_SUCCESS) {
1732 fprintf(stderr, "'%s' is not a valid type: %s\n",
1733 word, isc_result_totext(result));
1737 rdataclass = getzoneclass();
1738 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1739 if (result != ISC_R_SUCCESS) {
1740 fprintf(stderr, "'%s' is not a valid class or type: "
1741 "%s\n", word, isc_result_totext(result));
1746 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1748 if (retval != STATUS_MORE)
1752 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1753 rdataclass = dns_rdataclass_any;
1755 rdataclass = dns_rdataclass_none;
1757 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1758 fprintf(stderr, "could not read rdata\n");
1765 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1766 check_result(result, "dns_message_gettemprdatalist");
1767 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1768 check_result(result, "dns_message_gettemprdataset");
1769 dns_rdatalist_init(rdatalist);
1770 rdatalist->type = rdatatype;
1771 rdatalist->rdclass = rdataclass;
1772 rdatalist->covers = rdatatype;
1773 rdatalist->ttl = (dns_ttl_t)ttl;
1774 ISC_LIST_INIT(rdatalist->rdata);
1775 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1776 dns_rdataset_init(rdataset);
1777 dns_rdatalist_tordataset(rdatalist, rdataset);
1778 ISC_LIST_INIT(name->list);
1779 ISC_LIST_APPEND(name->list, rdataset, link);
1780 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1781 return (STATUS_MORE);
1785 dns_message_puttempname(updatemsg, &name);
1786 dns_message_puttemprdata(updatemsg, &rdata);
1787 return (STATUS_SYNTAX);
1791 evaluate_update(char *cmdline) {
1793 isc_boolean_t isdelete;
1795 ddebug("evaluate_update()");
1796 word = nsu_strsep(&cmdline, " \t\r\n");
1798 fprintf(stderr, "could not read operation code\n");
1799 return (STATUS_SYNTAX);
1801 if (strcasecmp(word, "delete") == 0)
1802 isdelete = ISC_TRUE;
1803 else if (strcasecmp(word, "add") == 0)
1804 isdelete = ISC_FALSE;
1806 fprintf(stderr, "incorrect operation code: %s\n", word);
1807 return (STATUS_SYNTAX);
1809 return (update_addordelete(cmdline, isdelete));
1813 setzone(dns_name_t *zonename) {
1814 isc_result_t result;
1815 dns_name_t *name = NULL;
1816 dns_rdataset_t *rdataset = NULL;
1818 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1819 if (result == ISC_R_SUCCESS) {
1820 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1821 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1822 for (rdataset = ISC_LIST_HEAD(name->list);
1824 rdataset = ISC_LIST_HEAD(name->list)) {
1825 ISC_LIST_UNLINK(name->list, rdataset, link);
1826 dns_rdataset_disassociate(rdataset);
1827 dns_message_puttemprdataset(updatemsg, &rdataset);
1829 dns_message_puttempname(updatemsg, &name);
1832 if (zonename != NULL) {
1833 result = dns_message_gettempname(updatemsg, &name);
1834 check_result(result, "dns_message_gettempname");
1835 dns_name_init(name, NULL);
1836 dns_name_clone(zonename, name);
1837 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1838 check_result(result, "dns_message_gettemprdataset");
1839 dns_rdataset_makequestion(rdataset, getzoneclass(),
1841 ISC_LIST_INIT(name->list);
1842 ISC_LIST_APPEND(name->list, rdataset, link);
1843 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1848 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1849 isc_result_t result;
1850 isc_buffer_t *buf = NULL;
1853 ddebug("show_message()");
1859 if (bufsz > MAXTEXT) {
1860 fprintf(stderr, "could not allocate large enough "
1861 "buffer to display message\n");
1865 isc_buffer_free(&buf);
1866 result = isc_buffer_allocate(mctx, &buf, bufsz);
1867 check_result(result, "isc_buffer_allocate");
1868 result = dns_message_totext(msg, style, 0, buf);
1870 } while (result == ISC_R_NOSPACE);
1871 if (result != ISC_R_SUCCESS) {
1872 fprintf(stderr, "could not convert message to text format.\n");
1873 isc_buffer_free(&buf);
1876 fprintf(stream, "%s\n%.*s", description,
1877 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1878 isc_buffer_free(&buf);
1883 get_next_command(void) {
1884 char cmdlinebuf[MAXCMD];
1888 ddebug("get_next_command()");
1890 fprintf(stdout, "> ");
1894 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1896 if (cmdline == NULL)
1897 return (STATUS_QUIT);
1898 word = nsu_strsep(&cmdline, " \t\r\n");
1901 return (STATUS_QUIT);
1903 return (STATUS_SEND);
1905 return (STATUS_MORE);
1906 if (strcasecmp(word, "quit") == 0)
1907 return (STATUS_QUIT);
1908 if (strcasecmp(word, "prereq") == 0)
1909 return (evaluate_prereq(cmdline));
1910 if (strcasecmp(word, "update") == 0)
1911 return (evaluate_update(cmdline));
1912 if (strcasecmp(word, "server") == 0)
1913 return (evaluate_server(cmdline));
1914 if (strcasecmp(word, "local") == 0)
1915 return (evaluate_local(cmdline));
1916 if (strcasecmp(word, "zone") == 0)
1917 return (evaluate_zone(cmdline));
1918 if (strcasecmp(word, "class") == 0)
1919 return (evaluate_class(cmdline));
1920 if (strcasecmp(word, "send") == 0)
1921 return (STATUS_SEND);
1922 if (strcasecmp(word, "debug") == 0) {
1924 ddebugging = ISC_TRUE;
1926 debugging = ISC_TRUE;
1927 return (STATUS_MORE);
1929 if (strcasecmp(word, "ttl") == 0)
1930 return (evaluate_ttl(cmdline));
1931 if (strcasecmp(word, "show") == 0) {
1932 show_message(stdout, updatemsg, "Outgoing update query:");
1933 return (STATUS_MORE);
1935 if (strcasecmp(word, "answer") == 0) {
1937 show_message(stdout, answer, "Answer:");
1938 return (STATUS_MORE);
1940 if (strcasecmp(word, "key") == 0) {
1941 usegsstsig = ISC_FALSE;
1942 return (evaluate_key(cmdline));
1944 if (strcasecmp(word, "realm") == 0)
1945 return (evaluate_realm(cmdline));
1946 if (strcasecmp(word, "gsstsig") == 0) {
1948 usegsstsig = ISC_TRUE;
1949 use_win2k_gsstsig = ISC_FALSE;
1951 fprintf(stderr, "gsstsig not supported\n");
1953 return (STATUS_MORE);
1955 if (strcasecmp(word, "oldgsstsig") == 0) {
1957 usegsstsig = ISC_TRUE;
1958 use_win2k_gsstsig = ISC_TRUE;
1960 fprintf(stderr, "gsstsig not supported\n");
1962 return (STATUS_MORE);
1964 if (strcasecmp(word, "help") == 0) {
1966 "local address [port] (set local resolver)\n"
1967 "server address [port] (set master server for zone)\n"
1968 "send (send the update request)\n"
1969 "show (show the update request)\n"
1970 "answer (show the answer to the last request)\n"
1971 "quit (quit, any pending update is not sent\n"
1972 "help (display this message_\n"
1973 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1974 "gsstsig (use GSS_TSIG to sign the request)\n"
1975 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1976 "zone name (set the zone to be updated)\n"
1977 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1978 "prereq nxdomain name (does this name not exist)\n"
1979 "prereq yxdomain name (does this name exist)\n"
1980 "prereq nxrrset .... (does this RRset exist)\n"
1981 "prereq yxrrset .... (does this RRset not exist)\n"
1982 "update add .... (add the given record to the zone)\n"
1983 "update delete .... (remove the given record(s) from the zone)\n");
1984 return (STATUS_MORE);
1986 fprintf(stderr, "incorrect section name: %s\n", word);
1987 return (STATUS_SYNTAX);
1990 static isc_boolean_t
1991 user_interaction(void) {
1992 isc_uint16_t result = STATUS_MORE;
1994 ddebug("user_interaction()");
1995 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
1996 result = get_next_command();
1997 if (!interactive && result == STATUS_SYNTAX)
1998 fatal("syntax error");
2000 if (result == STATUS_SEND)
2008 isc_event_t *event = global_event;
2009 ddebug("done_update()");
2010 isc_task_send(global_task, &event);
2014 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2015 isc_result_t result;
2016 dns_rdata_t rdata = DNS_RDATA_INIT;
2017 dns_rdata_any_tsig_t tsig;
2019 result = dns_rdataset_first(rdataset);
2020 check_result(result, "dns_rdataset_first");
2021 dns_rdataset_current(rdataset, &rdata);
2022 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2023 check_result(result, "dns_rdata_tostruct");
2024 if (tsig.error != 0) {
2025 if (isc_buffer_remaininglength(b) < 1)
2026 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2027 isc__buffer_putstr(b, "(" /*)*/);
2028 result = dns_tsigrcode_totext(tsig.error, b);
2029 check_result(result, "dns_tsigrcode_totext");
2030 if (isc_buffer_remaininglength(b) < 1)
2031 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2032 isc__buffer_putstr(b, /*(*/ ")");
2037 update_completed(isc_task_t *task, isc_event_t *event) {
2038 dns_requestevent_t *reqev = NULL;
2039 isc_result_t result;
2040 dns_request_t *request;
2044 ddebug("update_completed()");
2048 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2049 reqev = (dns_requestevent_t *)event;
2050 request = reqev->request;
2053 dns_request_destroy(&request);
2054 isc_event_free(&event);
2059 if (reqev->result != ISC_R_SUCCESS) {
2060 fprintf(stderr, "; Communication with server failed: %s\n",
2061 isc_result_totext(reqev->result));
2062 seenerror = ISC_TRUE;
2066 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
2067 check_result(result, "dns_message_create");
2068 result = dns_request_getresponse(request, answer,
2069 DNS_MESSAGEPARSE_PRESERVEORDER);
2072 if (answer->verify_attempted)
2073 ddebug("tsig verification successful");
2075 case DNS_R_CLOCKSKEW:
2076 case DNS_R_EXPECTEDTSIG:
2077 case DNS_R_TSIGERRORSET:
2078 case DNS_R_TSIGVERIFYFAILURE:
2079 case DNS_R_UNEXPECTEDTSIG:
2082 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2084 * For MS DNS that violates RFC 2845, section 4.2
2089 fprintf(stderr, "; TSIG error with server: %s\n",
2090 isc_result_totext(result));
2091 seenerror = ISC_TRUE;
2094 check_result(result, "dns_request_getresponse");
2097 if (answer->rcode != dns_rcode_noerror) {
2098 seenerror = ISC_TRUE;
2102 dns_rdataset_t *rds;
2104 isc_buffer_init(&b, buf, sizeof(buf) - 1);
2105 result = dns_rcode_totext(answer->rcode, &b);
2106 check_result(result, "dns_rcode_totext");
2107 rds = dns_message_gettsig(answer, NULL);
2109 check_tsig_error(rds, &b);
2110 fprintf(stderr, "update failed: %.*s\n",
2111 (int)isc_buffer_usedlength(&b), buf);
2115 show_message(stderr, answer, "\nReply from update query:");
2118 dns_request_destroy(&request);
2120 dns_name_free(&tmpzonename, mctx);
2121 dns_name_free(&restart_master, mctx);
2123 isc_event_free(&event);
2128 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2129 isc_sockaddr_t *srcaddr)
2131 isc_result_t result;
2132 dns_request_t *request = NULL;
2133 unsigned int options = DNS_REQUESTOPT_CASE;
2135 ddebug("send_update()");
2140 options |= DNS_REQUESTOPT_TCP;
2141 if (tsigkey == NULL && sig0key != NULL) {
2142 result = dns_message_setsig0key(updatemsg, sig0key);
2143 check_result(result, "dns_message_setsig0key");
2146 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2148 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2149 fprintf(stderr, "Sending update to %s\n", addrbuf);
2152 /* Windows doesn't like the tsig name to be compressed. */
2153 if (updatemsg->tsigname)
2154 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2156 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2157 master, options, tsigkey, timeout,
2158 udp_timeout, udp_retries, global_task,
2159 update_completed, NULL, &request);
2160 check_result(result, "dns_request_createvia3");
2163 show_message(stdout, updatemsg, "Outgoing update query:");
2169 recvsoa(isc_task_t *task, isc_event_t *event) {
2170 dns_requestevent_t *reqev = NULL;
2171 dns_request_t *request = NULL;
2172 isc_result_t result, eresult;
2173 dns_message_t *rcvmsg = NULL;
2174 dns_section_t section;
2175 dns_name_t *name = NULL;
2176 dns_rdataset_t *soaset = NULL;
2177 dns_rdata_soa_t soa;
2178 dns_rdata_t soarr = DNS_RDATA_INIT;
2181 nsu_requestinfo_t *reqinfo;
2182 dns_message_t *soaquery = NULL;
2183 isc_sockaddr_t *addr;
2184 isc_boolean_t seencname = ISC_FALSE;
2186 unsigned int nlabels;
2190 ddebug("recvsoa()");
2194 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2195 reqev = (dns_requestevent_t *)event;
2196 request = reqev->request;
2197 eresult = reqev->result;
2198 reqinfo = reqev->ev_arg;
2199 soaquery = reqinfo->msg;
2200 addr = reqinfo->addr;
2203 dns_request_destroy(&request);
2204 dns_message_destroy(&soaquery);
2205 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2206 isc_event_free(&event);
2211 if (eresult != ISC_R_SUCCESS) {
2212 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2214 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2215 fprintf(stderr, "; Communication with %s failed: %s\n",
2216 addrbuf, isc_result_totext(eresult));
2217 if (userserver != NULL)
2218 fatal("could not talk to specified name server");
2219 else if (++ns_inuse >= lwconf->nsnext)
2220 fatal("could not talk to any default name server");
2221 ddebug("Destroying request [%p]", request);
2222 dns_request_destroy(&request);
2223 dns_message_renderreset(soaquery);
2224 dns_message_settsigkey(soaquery, NULL);
2225 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2226 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2227 isc_event_free(&event);
2228 setzoneclass(dns_rdataclass_none);
2232 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2234 isc_event_free(&event);
2237 ddebug("About to create rcvmsg");
2238 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2239 check_result(result, "dns_message_create");
2240 result = dns_request_getresponse(request, rcvmsg,
2241 DNS_MESSAGEPARSE_PRESERVEORDER);
2242 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2243 dns_message_destroy(&rcvmsg);
2244 ddebug("Destroying request [%p]", request);
2245 dns_request_destroy(&request);
2246 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2247 if (reqinfo == NULL)
2248 fatal("out of memory");
2249 reqinfo->msg = soaquery;
2250 reqinfo->addr = addr;
2251 dns_message_renderreset(soaquery);
2252 ddebug("retrying soa request without TSIG");
2253 result = dns_request_createvia3(requestmgr, soaquery,
2254 localaddr, addr, 0, NULL,
2257 global_task, recvsoa, reqinfo,
2259 check_result(result, "dns_request_createvia");
2263 check_result(result, "dns_request_getresponse");
2264 section = DNS_SECTION_ANSWER;
2267 show_message(stderr, rcvmsg, "Reply from SOA query:");
2269 if (rcvmsg->rcode != dns_rcode_noerror &&
2270 rcvmsg->rcode != dns_rcode_nxdomain)
2271 fatal("response to SOA query was unsuccessful");
2273 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2274 char namebuf[DNS_NAME_FORMATSIZE];
2275 dns_name_format(userzone, namebuf, sizeof(namebuf));
2276 error("specified zone '%s' does not exist (NXDOMAIN)",
2278 dns_message_destroy(&rcvmsg);
2279 dns_request_destroy(&request);
2280 dns_message_destroy(&soaquery);
2281 ddebug("Out of recvsoa");
2288 section = DNS_SECTION_ANSWER;
2290 section = DNS_SECTION_AUTHORITY;
2294 result = dns_message_firstname(rcvmsg, section);
2295 if (result != ISC_R_SUCCESS) {
2299 while (result == ISC_R_SUCCESS) {
2301 dns_message_currentname(rcvmsg, section, &name);
2303 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2305 if (result == ISC_R_SUCCESS)
2307 if (section == DNS_SECTION_ANSWER) {
2308 dns_rdataset_t *tset = NULL;
2309 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2310 &tset) == ISC_R_SUCCESS ||
2311 dns_message_findtype(name, dns_rdatatype_dname, 0,
2312 &tset) == ISC_R_SUCCESS ) {
2313 seencname = ISC_TRUE;
2318 result = dns_message_nextname(rcvmsg, section);
2321 if (soaset == NULL && !seencname) {
2330 char namestr[DNS_NAME_FORMATSIZE];
2331 dns_name_format(name, namestr, sizeof(namestr));
2332 fprintf(stderr, "Found zone name: %s\n", namestr);
2335 result = dns_rdataset_first(soaset);
2336 check_result(result, "dns_rdataset_first");
2338 dns_rdata_init(&soarr);
2339 dns_rdataset_current(soaset, &soarr);
2340 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2341 check_result(result, "dns_rdata_tostruct");
2343 dns_name_init(&master, NULL);
2344 dns_name_clone(&soa.origin, &master);
2346 if (userzone != NULL)
2347 zonename = userzone;
2352 char namestr[DNS_NAME_FORMATSIZE];
2353 dns_name_format(&master, namestr, sizeof(namestr));
2354 fprintf(stderr, "The master is: %s\n", namestr);
2357 if (userserver != NULL)
2358 serveraddr = userserver;
2360 char serverstr[DNS_NAME_MAXTEXT+1];
2363 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2364 result = dns_name_totext(&master, ISC_TRUE, &buf);
2365 check_result(result, "dns_name_totext");
2366 serverstr[isc_buffer_usedlength(&buf)] = 0;
2367 get_address(serverstr, dnsport, &tempaddr);
2368 serveraddr = &tempaddr;
2370 dns_rdata_freestruct(&soa);
2374 dns_name_init(&tmpzonename, NULL);
2375 dns_name_dup(zonename, mctx, &tmpzonename);
2376 dns_name_init(&restart_master, NULL);
2377 dns_name_dup(&master, mctx, &restart_master);
2378 start_gssrequest(&master);
2380 send_update(zonename, serveraddr, localaddr);
2381 setzoneclass(dns_rdataclass_none);
2384 send_update(zonename, serveraddr, localaddr);
2385 setzoneclass(dns_rdataclass_none);
2388 dns_message_destroy(&soaquery);
2389 dns_request_destroy(&request);
2392 dns_message_destroy(&rcvmsg);
2393 ddebug("Out of recvsoa");
2397 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2398 INSIST(result == ISC_R_SUCCESS);
2400 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2401 nlabels = dns_name_countlabels(name);
2403 fatal("could not find enclosing zone");
2404 dns_name_init(&tname, NULL);
2405 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2406 dns_name_clone(&tname, name);
2407 dns_request_destroy(&request);
2408 dns_message_renderreset(soaquery);
2409 dns_message_settsigkey(soaquery, NULL);
2410 if (userserver != NULL)
2411 sendrequest(localaddr, userserver, soaquery, &request);
2413 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2418 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2419 dns_message_t *msg, dns_request_t **request)
2421 isc_result_t result;
2422 nsu_requestinfo_t *reqinfo;
2424 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2425 if (reqinfo == NULL)
2426 fatal("out of memory");
2428 reqinfo->addr = destaddr;
2429 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2430 (userserver != NULL) ? tsigkey : NULL,
2431 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2432 global_task, recvsoa, reqinfo, request);
2433 check_result(result, "dns_request_createvia");
2440 * Get the realm from the users kerberos ticket if possible
2443 get_ticket_realm(isc_mem_t *mctx)
2448 krb5_principal princ;
2449 char *name, *ticket_realm;
2451 rc = krb5_init_context(&ctx);
2455 rc = krb5_cc_default(ctx, &ccache);
2457 krb5_free_context(ctx);
2461 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2463 krb5_cc_close(ctx, ccache);
2464 krb5_free_context(ctx);
2468 rc = krb5_unparse_name(ctx, princ, &name);
2470 krb5_free_principal(ctx, princ);
2471 krb5_cc_close(ctx, ccache);
2472 krb5_free_context(ctx);
2476 ticket_realm = strrchr(name, '@');
2477 if (ticket_realm != NULL) {
2478 realm = isc_mem_strdup(mctx, ticket_realm);
2482 krb5_free_principal(ctx, princ);
2483 krb5_cc_close(ctx, ccache);
2484 krb5_free_context(ctx);
2485 if (realm != NULL && debugging)
2486 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
2491 start_gssrequest(dns_name_t *master) {
2492 gss_ctx_id_t context;
2494 isc_result_t result;
2495 isc_uint32_t val = 0;
2496 dns_message_t *rmsg;
2497 dns_request_t *request = NULL;
2498 dns_name_t *servname;
2499 dns_fixedname_t fname;
2500 char namestr[DNS_NAME_FORMATSIZE];
2501 char keystr[DNS_NAME_FORMATSIZE];
2502 char *err_message = NULL;
2504 debug("start_gssrequest");
2507 if (gssring != NULL)
2508 dns_tsigkeyring_detach(&gssring);
2510 result = dns_tsigkeyring_create(mctx, &gssring);
2512 if (result != ISC_R_SUCCESS)
2513 fatal("dns_tsigkeyring_create failed: %s",
2514 isc_result_totext(result));
2516 dns_name_format(master, namestr, sizeof(namestr));
2517 if (kserver == NULL) {
2518 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2519 if (kserver == NULL)
2520 fatal("out of memory");
2522 if (userserver == NULL)
2523 get_address(namestr, dnsport, kserver);
2525 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2527 dns_fixedname_init(&fname);
2528 servname = dns_fixedname_name(&fname);
2531 get_ticket_realm(mctx);
2533 result = isc_string_printf(servicename, sizeof(servicename),
2534 "DNS/%s%s", namestr, realm ? realm : "");
2535 if (result != ISC_R_SUCCESS)
2536 fatal("isc_string_printf(servicename) failed: %s",
2537 isc_result_totext(result));
2538 isc_buffer_init(&buf, servicename, strlen(servicename));
2539 isc_buffer_add(&buf, strlen(servicename));
2540 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2541 if (result != ISC_R_SUCCESS)
2542 fatal("dns_name_fromtext(servname) failed: %s",
2543 isc_result_totext(result));
2545 dns_fixedname_init(&fkname);
2546 keyname = dns_fixedname_name(&fkname);
2548 isc_random_get(&val);
2549 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2551 if (result != ISC_R_SUCCESS)
2552 fatal("isc_string_printf(keystr) failed: %s",
2553 isc_result_totext(result));
2554 isc_buffer_init(&buf, keystr, strlen(keystr));
2555 isc_buffer_add(&buf, strlen(keystr));
2557 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
2558 if (result != ISC_R_SUCCESS)
2559 fatal("dns_name_fromtext(keyname) failed: %s",
2560 isc_result_totext(result));
2562 /* Windows doesn't recognize name compression in the key name. */
2563 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2566 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2567 if (result != ISC_R_SUCCESS)
2568 fatal("dns_message_create failed: %s",
2569 isc_result_totext(result));
2571 /* Build first request. */
2572 context = GSS_C_NO_CONTEXT;
2573 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2574 &context, use_win2k_gsstsig,
2575 mctx, &err_message);
2576 if (result == ISC_R_FAILURE)
2577 fatal("tkey query failed: %s",
2578 err_message != NULL ? err_message : "unknown error");
2579 if (result != ISC_R_SUCCESS)
2580 fatal("dns_tkey_buildgssquery failed: %s",
2581 isc_result_totext(result));
2583 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2587 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2588 dns_message_t *msg, dns_request_t **request,
2589 gss_ctx_id_t context)
2591 isc_result_t result;
2592 nsu_gssinfo_t *reqinfo;
2593 unsigned int options = 0;
2595 debug("send_gssrequest");
2596 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2597 if (reqinfo == NULL)
2598 fatal("out of memory");
2600 reqinfo->addr = destaddr;
2601 reqinfo->context = context;
2603 options |= DNS_REQUESTOPT_TCP;
2604 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2605 options, tsigkey, FIND_TIMEOUT * 20,
2606 FIND_TIMEOUT, 3, global_task, recvgss,
2608 check_result(result, "dns_request_createvia3");
2610 show_message(stdout, msg, "Outgoing update query:");
2615 recvgss(isc_task_t *task, isc_event_t *event) {
2616 dns_requestevent_t *reqev = NULL;
2617 dns_request_t *request = NULL;
2618 isc_result_t result, eresult;
2619 dns_message_t *rcvmsg = NULL;
2620 nsu_gssinfo_t *reqinfo;
2621 dns_message_t *tsigquery = NULL;
2622 isc_sockaddr_t *addr;
2623 gss_ctx_id_t context;
2625 dns_name_t *servname;
2626 dns_fixedname_t fname;
2627 char *err_message = NULL;
2631 ddebug("recvgss()");
2635 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2636 reqev = (dns_requestevent_t *)event;
2637 request = reqev->request;
2638 eresult = reqev->result;
2639 reqinfo = reqev->ev_arg;
2640 tsigquery = reqinfo->msg;
2641 context = reqinfo->context;
2642 addr = reqinfo->addr;
2645 dns_request_destroy(&request);
2646 dns_message_destroy(&tsigquery);
2647 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2648 isc_event_free(&event);
2653 if (eresult != ISC_R_SUCCESS) {
2654 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2656 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2657 fprintf(stderr, "; Communication with %s failed: %s\n",
2658 addrbuf, isc_result_totext(eresult));
2659 if (userserver != NULL)
2660 fatal("could not talk to specified name server");
2661 else if (++ns_inuse >= lwconf->nsnext)
2662 fatal("could not talk to any default name server");
2663 ddebug("Destroying request [%p]", request);
2664 dns_request_destroy(&request);
2665 dns_message_renderreset(tsigquery);
2666 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2668 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2669 isc_event_free(&event);
2672 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2674 isc_event_free(&event);
2677 ddebug("recvgss creating rcvmsg");
2678 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2679 check_result(result, "dns_message_create");
2681 result = dns_request_getresponse(request, rcvmsg,
2682 DNS_MESSAGEPARSE_PRESERVEORDER);
2683 check_result(result, "dns_request_getresponse");
2686 show_message(stderr, rcvmsg,
2687 "recvmsg reply from GSS-TSIG query");
2689 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2690 ddebug("recvgss trying %s GSS-TSIG",
2691 use_win2k_gsstsig ? "Standard" : "Win2k");
2692 if (use_win2k_gsstsig)
2693 use_win2k_gsstsig = ISC_FALSE;
2695 use_win2k_gsstsig = ISC_TRUE;
2696 tried_other_gsstsig = ISC_TRUE;
2697 start_gssrequest(&restart_master);
2701 if (rcvmsg->rcode != dns_rcode_noerror &&
2702 rcvmsg->rcode != dns_rcode_nxdomain)
2703 fatal("response to GSS-TSIG query was unsuccessful");
2706 dns_fixedname_init(&fname);
2707 servname = dns_fixedname_name(&fname);
2708 isc_buffer_init(&buf, servicename, strlen(servicename));
2709 isc_buffer_add(&buf, strlen(servicename));
2710 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2711 check_result(result, "dns_name_fromtext");
2714 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2715 &context, &tsigkey, gssring,
2720 case DNS_R_CONTINUE:
2721 send_gssrequest(localaddr, kserver, tsigquery, &request,
2727 * XXXSRA Waaay too much fun here. There's no good
2728 * reason why we need a TSIG here (the people who put
2729 * it into the spec admitted at the time that it was
2730 * not a security issue), and Windows clients don't
2731 * seem to work if named complies with the spec and
2732 * includes the gratuitous TSIG. So we're in the
2733 * bizarre situation of having to choose between
2734 * complying with a useless requirement in the spec
2735 * and interoperating. This is nuts. If we can
2736 * confirm this behavior, we should ask the WG to
2737 * consider removing the requirement for the
2738 * gratuitous TSIG here. For the moment, we ignore
2739 * the TSIG -- this too is a spec violation, but it's
2740 * the least insane thing to do.
2744 * Verify the signature.
2746 rcvmsg->state = DNS_SECTION_ANY;
2747 dns_message_setquerytsig(rcvmsg, NULL);
2748 result = dns_message_settsigkey(rcvmsg, tsigkey);
2749 check_result(result, "dns_message_settsigkey");
2750 result = dns_message_checksig(rcvmsg, NULL);
2751 ddebug("tsig verification: %s", dns_result_totext(result));
2752 check_result(result, "dns_message_checksig");
2755 send_update(&tmpzonename, serveraddr, localaddr);
2756 setzoneclass(dns_rdataclass_none);
2760 fatal("dns_tkey_negotiategss: %s %s",
2761 isc_result_totext(result),
2762 err_message != NULL ? err_message : "");
2766 dns_request_destroy(&request);
2767 dns_message_destroy(&tsigquery);
2769 dns_message_destroy(&rcvmsg);
2770 ddebug("Out of recvgss");
2775 start_update(void) {
2776 isc_result_t result;
2777 dns_rdataset_t *rdataset = NULL;
2778 dns_name_t *name = NULL;
2779 dns_request_t *request = NULL;
2780 dns_message_t *soaquery = NULL;
2781 dns_name_t *firstname;
2782 dns_section_t section = DNS_SECTION_UPDATE;
2784 ddebug("start_update()");
2787 dns_message_destroy(&answer);
2789 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2790 send_update(userzone, userserver, localaddr);
2791 setzoneclass(dns_rdataclass_none);
2795 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2797 check_result(result, "dns_message_create");
2799 if (userserver == NULL)
2800 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2802 result = dns_message_gettempname(soaquery, &name);
2803 check_result(result, "dns_message_gettempname");
2805 result = dns_message_gettemprdataset(soaquery, &rdataset);
2806 check_result(result, "dns_message_gettemprdataset");
2808 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2810 if (userzone != NULL) {
2811 dns_name_init(name, NULL);
2812 dns_name_clone(userzone, name);
2814 dns_rdataset_t *tmprdataset;
2815 result = dns_message_firstname(updatemsg, section);
2816 if (result == ISC_R_NOMORE) {
2817 section = DNS_SECTION_PREREQUISITE;
2818 result = dns_message_firstname(updatemsg, section);
2820 if (result != ISC_R_SUCCESS) {
2821 dns_message_puttempname(soaquery, &name);
2822 dns_rdataset_disassociate(rdataset);
2823 dns_message_puttemprdataset(soaquery, &rdataset);
2824 dns_message_destroy(&soaquery);
2829 dns_message_currentname(updatemsg, section, &firstname);
2830 dns_name_init(name, NULL);
2831 dns_name_clone(firstname, name);
2833 * Looks to see if the first name references a DS record
2834 * and if that name is not the root remove a label as DS
2835 * records live in the parent zone so we need to start our
2836 * search one label up.
2838 tmprdataset = ISC_LIST_HEAD(firstname->list);
2839 if (section == DNS_SECTION_UPDATE &&
2840 !dns_name_equal(firstname, dns_rootname) &&
2841 tmprdataset->type == dns_rdatatype_ds) {
2842 unsigned int labels = dns_name_countlabels(name);
2843 dns_name_getlabelsequence(name, 1, labels - 1, name);
2847 ISC_LIST_INIT(name->list);
2848 ISC_LIST_APPEND(name->list, rdataset, link);
2849 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2851 if (userserver != NULL)
2852 sendrequest(localaddr, userserver, soaquery, &request);
2855 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2861 ddebug("cleanup()");
2864 dns_message_destroy(&answer);
2867 if (tsigkey != NULL) {
2868 ddebug("detach tsigkey x%p", tsigkey);
2869 dns_tsigkey_detach(&tsigkey);
2871 if (gssring != NULL) {
2872 ddebug("Detaching GSS-TSIG keyring");
2873 dns_tsigkeyring_detach(&gssring);
2875 if (kserver != NULL) {
2876 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2879 if (realm != NULL) {
2880 isc_mem_free(mctx, realm);
2885 if (sig0key != NULL)
2886 dst_key_free(&sig0key);
2888 ddebug("Shutting down task manager");
2889 isc_taskmgr_destroy(&taskmgr);
2891 ddebug("Destroying event");
2892 isc_event_free(&global_event);
2894 ddebug("Shutting down socket manager");
2895 isc_socketmgr_destroy(&socketmgr);
2897 ddebug("Shutting down timer manager");
2898 isc_timermgr_destroy(&timermgr);
2900 ddebug("Destroying hash context");
2903 ddebug("Destroying name state");
2906 ddebug("Removing log context");
2907 isc_log_destroy(&lctx);
2909 ddebug("Destroying memory context");
2911 isc_mem_stats(mctx, stderr);
2912 isc_mem_destroy(&mctx);
2916 getinput(isc_task_t *task, isc_event_t *event) {
2926 if (global_event == NULL)
2927 global_event = event;
2930 more = user_interaction();
2940 main(int argc, char **argv) {
2941 isc_result_t result;
2942 style = &dns_master_style_debug;
2946 interactive = ISC_TF(isatty(0));
2950 pre_parse_args(argc, argv);
2952 result = isc_mem_create(0, 0, &mctx);
2953 check_result(result, "isc_mem_create");
2955 parse_args(argc, argv, mctx, &entropy);
2959 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2960 check_result(result, "isc_app_onrun");
2962 (void)isc_app_run();