2 * Copyright (C) 2004-2013 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.4 2011/11/03 04:30:09 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:r:R::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");
1125 if (word == NULL || *word == 0) {
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 if (cmdline == NULL) {
1158 rdata->flags = DNS_RDATA_UPDATE;
1159 return (STATUS_MORE);
1162 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1165 if (*cmdline != 0) {
1166 dns_rdatacallbacks_init(&callbacks);
1167 result = isc_lex_create(mctx, strlen(cmdline), &lex);
1168 check_result(result, "isc_lex_create");
1169 isc_buffer_init(&source, cmdline, strlen(cmdline));
1170 isc_buffer_add(&source, strlen(cmdline));
1171 result = isc_lex_openbuffer(lex, &source);
1172 check_result(result, "isc_lex_openbuffer");
1173 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
1174 check_result(result, "isc_buffer_allocate");
1175 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1176 dns_rootname, 0, mctx, buf,
1178 isc_lex_destroy(&lex);
1179 if (result == ISC_R_SUCCESS) {
1180 isc_buffer_usedregion(buf, &r);
1181 result = isc_buffer_allocate(mctx, &newbuf, r.length);
1182 check_result(result, "isc_buffer_allocate");
1183 isc_buffer_putmem(newbuf, r.base, r.length);
1184 isc_buffer_usedregion(newbuf, &r);
1185 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1186 isc_buffer_free(&buf);
1187 dns_message_takebuffer(msg, &newbuf);
1189 fprintf(stderr, "invalid rdata format: %s\n",
1190 isc_result_totext(result));
1191 isc_buffer_free(&buf);
1192 return (STATUS_SYNTAX);
1195 rdata->flags = DNS_RDATA_UPDATE;
1197 *cmdlinep = cmdline;
1198 return (STATUS_MORE);
1202 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1203 isc_result_t result;
1205 dns_name_t *name = NULL;
1206 isc_textregion_t region;
1207 dns_rdataset_t *rdataset = NULL;
1208 dns_rdatalist_t *rdatalist = NULL;
1209 dns_rdataclass_t rdataclass;
1210 dns_rdatatype_t rdatatype;
1211 dns_rdata_t *rdata = NULL;
1212 isc_uint16_t retval;
1214 ddebug("make_prereq()");
1217 * Read the owner name
1219 retval = parse_name(&cmdline, updatemsg, &name);
1220 if (retval != STATUS_MORE)
1224 * If this is an rrset prereq, read the class or type.
1227 word = nsu_strsep(&cmdline, " \t\r\n");
1228 if (word == NULL || *word == 0) {
1229 fprintf(stderr, "could not read class or type\n");
1233 region.length = strlen(word);
1234 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1235 if (result == ISC_R_SUCCESS) {
1236 if (!setzoneclass(rdataclass)) {
1237 fprintf(stderr, "class mismatch: %s\n", word);
1241 * Now read the type.
1243 word = nsu_strsep(&cmdline, " \t\r\n");
1244 if (word == NULL || *word == 0) {
1245 fprintf(stderr, "could not read type\n");
1249 region.length = strlen(word);
1250 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1251 if (result != ISC_R_SUCCESS) {
1252 fprintf(stderr, "invalid type: %s\n", word);
1256 rdataclass = getzoneclass();
1257 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1258 if (result != ISC_R_SUCCESS) {
1259 fprintf(stderr, "invalid type: %s\n", word);
1264 rdatatype = dns_rdatatype_any;
1266 result = dns_message_gettemprdata(updatemsg, &rdata);
1267 check_result(result, "dns_message_gettemprdata");
1269 dns_rdata_init(rdata);
1271 if (isrrset && ispositive) {
1272 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1274 if (retval != STATUS_MORE)
1277 rdata->flags = DNS_RDATA_UPDATE;
1279 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1280 check_result(result, "dns_message_gettemprdatalist");
1281 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1282 check_result(result, "dns_message_gettemprdataset");
1283 dns_rdatalist_init(rdatalist);
1284 rdatalist->type = rdatatype;
1286 if (isrrset && rdata->data != NULL)
1287 rdatalist->rdclass = rdataclass;
1289 rdatalist->rdclass = dns_rdataclass_any;
1291 rdatalist->rdclass = dns_rdataclass_none;
1292 rdatalist->covers = 0;
1294 rdata->rdclass = rdatalist->rdclass;
1295 rdata->type = rdatatype;
1296 ISC_LIST_INIT(rdatalist->rdata);
1297 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1298 dns_rdataset_init(rdataset);
1299 dns_rdatalist_tordataset(rdatalist, rdataset);
1300 ISC_LIST_INIT(name->list);
1301 ISC_LIST_APPEND(name->list, rdataset, link);
1302 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1303 return (STATUS_MORE);
1307 dns_message_puttempname(updatemsg, &name);
1308 return (STATUS_SYNTAX);
1312 evaluate_prereq(char *cmdline) {
1314 isc_boolean_t ispositive, isrrset;
1316 ddebug("evaluate_prereq()");
1317 word = nsu_strsep(&cmdline, " \t\r\n");
1318 if (word == NULL || *word == 0) {
1319 fprintf(stderr, "could not read operation code\n");
1320 return (STATUS_SYNTAX);
1322 if (strcasecmp(word, "nxdomain") == 0) {
1323 ispositive = ISC_FALSE;
1324 isrrset = ISC_FALSE;
1325 } else if (strcasecmp(word, "yxdomain") == 0) {
1326 ispositive = ISC_TRUE;
1327 isrrset = ISC_FALSE;
1328 } else if (strcasecmp(word, "nxrrset") == 0) {
1329 ispositive = ISC_FALSE;
1331 } else if (strcasecmp(word, "yxrrset") == 0) {
1332 ispositive = ISC_TRUE;
1335 fprintf(stderr, "incorrect operation code: %s\n", word);
1336 return (STATUS_SYNTAX);
1338 return (make_prereq(cmdline, ispositive, isrrset));
1342 evaluate_server(char *cmdline) {
1343 char *word, *server;
1347 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1348 return (STATUS_SYNTAX);
1351 word = nsu_strsep(&cmdline, " \t\r\n");
1352 if (word == NULL || *word == 0) {
1353 fprintf(stderr, "could not read server name\n");
1354 return (STATUS_SYNTAX);
1358 word = nsu_strsep(&cmdline, " \t\r\n");
1359 if (word == NULL || *word == 0)
1363 port = strtol(word, &endp, 10);
1365 fprintf(stderr, "port '%s' is not numeric\n", word);
1366 return (STATUS_SYNTAX);
1367 } else if (port < 1 || port > 65535) {
1368 fprintf(stderr, "port '%s' is out of range "
1369 "(1 to 65535)\n", word);
1370 return (STATUS_SYNTAX);
1374 if (userserver == NULL) {
1375 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1376 if (userserver == NULL)
1377 fatal("out of memory");
1380 get_address(server, (in_port_t)port, userserver);
1382 return (STATUS_MORE);
1386 evaluate_local(char *cmdline) {
1390 struct in6_addr in6;
1392 word = nsu_strsep(&cmdline, " \t\r\n");
1393 if (word == NULL || *word == 0) {
1394 fprintf(stderr, "could not read server name\n");
1395 return (STATUS_SYNTAX);
1399 word = nsu_strsep(&cmdline, " \t\r\n");
1400 if (word == NULL || *word == 0)
1404 port = strtol(word, &endp, 10);
1406 fprintf(stderr, "port '%s' is not numeric\n", word);
1407 return (STATUS_SYNTAX);
1408 } else if (port < 1 || port > 65535) {
1409 fprintf(stderr, "port '%s' is out of range "
1410 "(1 to 65535)\n", word);
1411 return (STATUS_SYNTAX);
1415 if (localaddr == NULL) {
1416 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
1417 if (localaddr == NULL)
1418 fatal("out of memory");
1421 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
1422 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
1423 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
1424 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
1426 fprintf(stderr, "invalid address %s", local);
1427 return (STATUS_SYNTAX);
1430 return (STATUS_MORE);
1434 evaluate_key(char *cmdline) {
1438 isc_result_t result;
1439 dns_fixedname_t fkeyname;
1440 dns_name_t *keyname;
1442 unsigned char *secret = NULL;
1443 isc_buffer_t secretbuf;
1444 dns_name_t *hmacname = NULL;
1445 isc_uint16_t digestbits = 0;
1448 namestr = nsu_strsep(&cmdline, " \t\r\n");
1449 if (namestr == NULL || *namestr == 0) {
1450 fprintf(stderr, "could not read key name\n");
1451 return (STATUS_SYNTAX);
1454 dns_fixedname_init(&fkeyname);
1455 keyname = dns_fixedname_name(&fkeyname);
1457 n = strchr(namestr, ':');
1459 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1462 hmacname = DNS_TSIG_HMACMD5_NAME;
1464 isc_buffer_init(&b, namestr, strlen(namestr));
1465 isc_buffer_add(&b, strlen(namestr));
1466 result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
1467 if (result != ISC_R_SUCCESS) {
1468 fprintf(stderr, "could not parse key name\n");
1469 return (STATUS_SYNTAX);
1472 secretstr = nsu_strsep(&cmdline, "\r\n");
1473 if (secretstr == NULL || *secretstr == 0) {
1474 fprintf(stderr, "could not read key secret\n");
1475 return (STATUS_SYNTAX);
1477 secretlen = strlen(secretstr) * 3 / 4;
1478 secret = isc_mem_allocate(mctx, secretlen);
1480 fatal("out of memory");
1482 isc_buffer_init(&secretbuf, secret, secretlen);
1483 result = isc_base64_decodestring(secretstr, &secretbuf);
1484 if (result != ISC_R_SUCCESS) {
1485 fprintf(stderr, "could not create key from %s: %s\n",
1486 secretstr, isc_result_totext(result));
1487 isc_mem_free(mctx, secret);
1488 return (STATUS_SYNTAX);
1490 secretlen = isc_buffer_usedlength(&secretbuf);
1492 if (tsigkey != NULL)
1493 dns_tsigkey_detach(&tsigkey);
1494 result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
1495 ISC_FALSE, NULL, 0, 0, mctx, NULL,
1497 isc_mem_free(mctx, secret);
1498 if (result != ISC_R_SUCCESS) {
1499 fprintf(stderr, "could not create key from %s %s: %s\n",
1500 namestr, secretstr, dns_result_totext(result));
1501 return (STATUS_SYNTAX);
1503 dst_key_setbits(tsigkey->key, digestbits);
1504 return (STATUS_MORE);
1508 evaluate_zone(char *cmdline) {
1511 isc_result_t result;
1513 word = nsu_strsep(&cmdline, " \t\r\n");
1514 if (word == NULL || *word == 0) {
1515 fprintf(stderr, "could not read zone name\n");
1516 return (STATUS_SYNTAX);
1519 dns_fixedname_init(&fuserzone);
1520 userzone = dns_fixedname_name(&fuserzone);
1521 isc_buffer_init(&b, word, strlen(word));
1522 isc_buffer_add(&b, strlen(word));
1523 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1524 if (result != ISC_R_SUCCESS) {
1525 userzone = NULL; /* Lest it point to an invalid name */
1526 fprintf(stderr, "could not parse zone name\n");
1527 return (STATUS_SYNTAX);
1530 return (STATUS_MORE);
1534 evaluate_realm(char *cmdline) {
1539 word = nsu_strsep(&cmdline, " \t\r\n");
1540 if (word == NULL || *word == 0) {
1542 isc_mem_free(mctx, realm);
1544 return (STATUS_MORE);
1547 snprintf(buf, sizeof(buf), "@%s", word);
1548 realm = isc_mem_strdup(mctx, buf);
1550 fatal("out of memory");
1551 return (STATUS_MORE);
1554 return (STATUS_SYNTAX);
1559 evaluate_ttl(char *cmdline) {
1561 isc_result_t result;
1564 word = nsu_strsep(&cmdline, " \t\r\n");
1565 if (word == NULL || *word == 0) {
1566 fprintf(stderr, "could not ttl\n");
1567 return (STATUS_SYNTAX);
1570 if (!strcasecmp(word, "none")) {
1572 default_ttl_set = ISC_FALSE;
1573 return (STATUS_MORE);
1576 result = isc_parse_uint32(&ttl, word, 10);
1577 if (result != ISC_R_SUCCESS)
1578 return (STATUS_SYNTAX);
1580 if (ttl > TTL_MAX) {
1581 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1583 return (STATUS_SYNTAX);
1586 default_ttl_set = ISC_TRUE;
1588 return (STATUS_MORE);
1592 evaluate_class(char *cmdline) {
1595 isc_result_t result;
1596 dns_rdataclass_t rdclass;
1598 word = nsu_strsep(&cmdline, " \t\r\n");
1599 if (word == NULL || *word == 0) {
1600 fprintf(stderr, "could not read class name\n");
1601 return (STATUS_SYNTAX);
1605 r.length = strlen(word);
1606 result = dns_rdataclass_fromtext(&rdclass, &r);
1607 if (result != ISC_R_SUCCESS) {
1608 fprintf(stderr, "could not parse class name: %s\n", word);
1609 return (STATUS_SYNTAX);
1612 case dns_rdataclass_none:
1613 case dns_rdataclass_any:
1614 case dns_rdataclass_reserved0:
1615 fprintf(stderr, "bad default class: %s\n", word);
1616 return (STATUS_SYNTAX);
1618 defaultclass = rdclass;
1621 return (STATUS_MORE);
1625 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1626 isc_result_t result;
1627 dns_name_t *name = NULL;
1630 dns_rdataclass_t rdataclass;
1631 dns_rdatatype_t rdatatype;
1632 dns_rdata_t *rdata = NULL;
1633 dns_rdatalist_t *rdatalist = NULL;
1634 dns_rdataset_t *rdataset = NULL;
1635 isc_textregion_t region;
1636 isc_uint16_t retval;
1638 ddebug("update_addordelete()");
1641 * Read the owner name.
1643 retval = parse_name(&cmdline, updatemsg, &name);
1644 if (retval != STATUS_MORE)
1647 result = dns_message_gettemprdata(updatemsg, &rdata);
1648 check_result(result, "dns_message_gettemprdata");
1650 dns_rdata_init(rdata);
1653 * If this is an add, read the TTL and verify that it's in range.
1654 * If it's a delete, ignore a TTL if present (for compatibility).
1656 word = nsu_strsep(&cmdline, " \t\r\n");
1657 if (word == NULL || *word == 0) {
1659 fprintf(stderr, "could not read owner ttl\n");
1664 rdataclass = dns_rdataclass_any;
1665 rdatatype = dns_rdatatype_any;
1666 rdata->flags = DNS_RDATA_UPDATE;
1670 result = isc_parse_uint32(&ttl, word, 10);
1671 if (result != ISC_R_SUCCESS) {
1675 } else if (default_ttl_set) {
1679 fprintf(stderr, "ttl '%s': %s\n", word,
1680 isc_result_totext(result));
1687 else if (ttl > TTL_MAX) {
1688 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1694 * Read the class or type.
1696 word = nsu_strsep(&cmdline, " \t\r\n");
1698 if (word == NULL || *word == 0) {
1700 rdataclass = dns_rdataclass_any;
1701 rdatatype = dns_rdatatype_any;
1702 rdata->flags = DNS_RDATA_UPDATE;
1705 fprintf(stderr, "could not read class or type\n");
1710 region.length = strlen(word);
1711 rdataclass = dns_rdataclass_any;
1712 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1713 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1714 if (!setzoneclass(rdataclass)) {
1715 fprintf(stderr, "class mismatch: %s\n", word);
1719 * Now read the type.
1721 word = nsu_strsep(&cmdline, " \t\r\n");
1722 if (word == NULL || *word == 0) {
1724 rdataclass = dns_rdataclass_any;
1725 rdatatype = dns_rdatatype_any;
1726 rdata->flags = DNS_RDATA_UPDATE;
1729 fprintf(stderr, "could not read type\n");
1734 region.length = strlen(word);
1735 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1736 if (result != ISC_R_SUCCESS) {
1737 fprintf(stderr, "'%s' is not a valid type: %s\n",
1738 word, isc_result_totext(result));
1742 rdataclass = getzoneclass();
1743 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1744 if (result != ISC_R_SUCCESS) {
1745 fprintf(stderr, "'%s' is not a valid class or type: "
1746 "%s\n", word, isc_result_totext(result));
1751 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1753 if (retval != STATUS_MORE)
1757 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1758 rdataclass = dns_rdataclass_any;
1760 rdataclass = dns_rdataclass_none;
1762 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1763 fprintf(stderr, "could not read rdata\n");
1770 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1771 check_result(result, "dns_message_gettemprdatalist");
1772 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1773 check_result(result, "dns_message_gettemprdataset");
1774 dns_rdatalist_init(rdatalist);
1775 rdatalist->type = rdatatype;
1776 rdatalist->rdclass = rdataclass;
1777 rdatalist->covers = rdatatype;
1778 rdatalist->ttl = (dns_ttl_t)ttl;
1779 ISC_LIST_INIT(rdatalist->rdata);
1780 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1781 dns_rdataset_init(rdataset);
1782 dns_rdatalist_tordataset(rdatalist, rdataset);
1783 ISC_LIST_INIT(name->list);
1784 ISC_LIST_APPEND(name->list, rdataset, link);
1785 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1786 return (STATUS_MORE);
1790 dns_message_puttempname(updatemsg, &name);
1791 dns_message_puttemprdata(updatemsg, &rdata);
1792 return (STATUS_SYNTAX);
1796 evaluate_update(char *cmdline) {
1798 isc_boolean_t isdelete;
1800 ddebug("evaluate_update()");
1801 word = nsu_strsep(&cmdline, " \t\r\n");
1802 if (word == NULL || *word == 0) {
1803 fprintf(stderr, "could not read operation code\n");
1804 return (STATUS_SYNTAX);
1806 if (strcasecmp(word, "delete") == 0)
1807 isdelete = ISC_TRUE;
1808 else if (strcasecmp(word, "add") == 0)
1809 isdelete = ISC_FALSE;
1811 fprintf(stderr, "incorrect operation code: %s\n", word);
1812 return (STATUS_SYNTAX);
1814 return (update_addordelete(cmdline, isdelete));
1818 setzone(dns_name_t *zonename) {
1819 isc_result_t result;
1820 dns_name_t *name = NULL;
1821 dns_rdataset_t *rdataset = NULL;
1823 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1824 if (result == ISC_R_SUCCESS) {
1825 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1826 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1827 for (rdataset = ISC_LIST_HEAD(name->list);
1829 rdataset = ISC_LIST_HEAD(name->list)) {
1830 ISC_LIST_UNLINK(name->list, rdataset, link);
1831 dns_rdataset_disassociate(rdataset);
1832 dns_message_puttemprdataset(updatemsg, &rdataset);
1834 dns_message_puttempname(updatemsg, &name);
1837 if (zonename != NULL) {
1838 result = dns_message_gettempname(updatemsg, &name);
1839 check_result(result, "dns_message_gettempname");
1840 dns_name_init(name, NULL);
1841 dns_name_clone(zonename, name);
1842 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1843 check_result(result, "dns_message_gettemprdataset");
1844 dns_rdataset_makequestion(rdataset, getzoneclass(),
1846 ISC_LIST_INIT(name->list);
1847 ISC_LIST_APPEND(name->list, rdataset, link);
1848 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1853 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1854 isc_result_t result;
1855 isc_buffer_t *buf = NULL;
1858 ddebug("show_message()");
1864 if (bufsz > MAXTEXT) {
1865 fprintf(stderr, "could not allocate large enough "
1866 "buffer to display message\n");
1870 isc_buffer_free(&buf);
1871 result = isc_buffer_allocate(mctx, &buf, bufsz);
1872 check_result(result, "isc_buffer_allocate");
1873 result = dns_message_totext(msg, style, 0, buf);
1875 } while (result == ISC_R_NOSPACE);
1876 if (result != ISC_R_SUCCESS) {
1877 fprintf(stderr, "could not convert message to text format.\n");
1878 isc_buffer_free(&buf);
1881 fprintf(stream, "%s\n%.*s", description,
1882 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1883 isc_buffer_free(&buf);
1888 get_next_command(void) {
1889 char cmdlinebuf[MAXCMD];
1894 ddebug("get_next_command()");
1896 fprintf(stdout, "> ");
1900 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1902 if (cmdline == NULL)
1903 return (STATUS_QUIT);
1906 * Normalize input by removing any eol.
1909 (void)nsu_strsep(&tmp, "\r\n");
1911 word = nsu_strsep(&cmdline, " \t\r\n");
1914 return (STATUS_QUIT);
1915 if (word == NULL || *word == 0)
1916 return (STATUS_SEND);
1918 return (STATUS_MORE);
1919 if (strcasecmp(word, "quit") == 0)
1920 return (STATUS_QUIT);
1921 if (strcasecmp(word, "prereq") == 0)
1922 return (evaluate_prereq(cmdline));
1923 if (strcasecmp(word, "update") == 0)
1924 return (evaluate_update(cmdline));
1925 if (strcasecmp(word, "server") == 0)
1926 return (evaluate_server(cmdline));
1927 if (strcasecmp(word, "local") == 0)
1928 return (evaluate_local(cmdline));
1929 if (strcasecmp(word, "zone") == 0)
1930 return (evaluate_zone(cmdline));
1931 if (strcasecmp(word, "class") == 0)
1932 return (evaluate_class(cmdline));
1933 if (strcasecmp(word, "send") == 0)
1934 return (STATUS_SEND);
1935 if (strcasecmp(word, "debug") == 0) {
1937 ddebugging = ISC_TRUE;
1939 debugging = ISC_TRUE;
1940 return (STATUS_MORE);
1942 if (strcasecmp(word, "ttl") == 0)
1943 return (evaluate_ttl(cmdline));
1944 if (strcasecmp(word, "show") == 0) {
1945 show_message(stdout, updatemsg, "Outgoing update query:");
1946 return (STATUS_MORE);
1948 if (strcasecmp(word, "answer") == 0) {
1950 show_message(stdout, answer, "Answer:");
1951 return (STATUS_MORE);
1953 if (strcasecmp(word, "key") == 0) {
1954 usegsstsig = ISC_FALSE;
1955 return (evaluate_key(cmdline));
1957 if (strcasecmp(word, "realm") == 0)
1958 return (evaluate_realm(cmdline));
1959 if (strcasecmp(word, "gsstsig") == 0) {
1961 usegsstsig = ISC_TRUE;
1962 use_win2k_gsstsig = ISC_FALSE;
1964 fprintf(stderr, "gsstsig not supported\n");
1966 return (STATUS_MORE);
1968 if (strcasecmp(word, "oldgsstsig") == 0) {
1970 usegsstsig = ISC_TRUE;
1971 use_win2k_gsstsig = ISC_TRUE;
1973 fprintf(stderr, "gsstsig not supported\n");
1975 return (STATUS_MORE);
1977 if (strcasecmp(word, "help") == 0) {
1979 "local address [port] (set local resolver)\n"
1980 "server address [port] (set master server for zone)\n"
1981 "send (send the update request)\n"
1982 "show (show the update request)\n"
1983 "answer (show the answer to the last request)\n"
1984 "quit (quit, any pending update is not sent\n"
1985 "help (display this message_\n"
1986 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1987 "gsstsig (use GSS_TSIG to sign the request)\n"
1988 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1989 "zone name (set the zone to be updated)\n"
1990 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1991 "prereq nxdomain name (does this name not exist)\n"
1992 "prereq yxdomain name (does this name exist)\n"
1993 "prereq nxrrset .... (does this RRset exist)\n"
1994 "prereq yxrrset .... (does this RRset not exist)\n"
1995 "update add .... (add the given record to the zone)\n"
1996 "update delete .... (remove the given record(s) from the zone)\n");
1997 return (STATUS_MORE);
1999 fprintf(stderr, "incorrect section name: %s\n", word);
2000 return (STATUS_SYNTAX);
2003 static isc_boolean_t
2004 user_interaction(void) {
2005 isc_uint16_t result = STATUS_MORE;
2007 ddebug("user_interaction()");
2008 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
2009 result = get_next_command();
2010 if (!interactive && result == STATUS_SYNTAX)
2011 fatal("syntax error");
2013 if (result == STATUS_SEND)
2021 isc_event_t *event = global_event;
2022 ddebug("done_update()");
2023 isc_task_send(global_task, &event);
2027 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2028 isc_result_t result;
2029 dns_rdata_t rdata = DNS_RDATA_INIT;
2030 dns_rdata_any_tsig_t tsig;
2032 result = dns_rdataset_first(rdataset);
2033 check_result(result, "dns_rdataset_first");
2034 dns_rdataset_current(rdataset, &rdata);
2035 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2036 check_result(result, "dns_rdata_tostruct");
2037 if (tsig.error != 0) {
2038 if (isc_buffer_remaininglength(b) < 1)
2039 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2040 isc__buffer_putstr(b, "(" /*)*/);
2041 result = dns_tsigrcode_totext(tsig.error, b);
2042 check_result(result, "dns_tsigrcode_totext");
2043 if (isc_buffer_remaininglength(b) < 1)
2044 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2045 isc__buffer_putstr(b, /*(*/ ")");
2050 update_completed(isc_task_t *task, isc_event_t *event) {
2051 dns_requestevent_t *reqev = NULL;
2052 isc_result_t result;
2053 dns_request_t *request;
2057 ddebug("update_completed()");
2061 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2062 reqev = (dns_requestevent_t *)event;
2063 request = reqev->request;
2066 dns_request_destroy(&request);
2067 isc_event_free(&event);
2072 if (reqev->result != ISC_R_SUCCESS) {
2073 fprintf(stderr, "; Communication with server failed: %s\n",
2074 isc_result_totext(reqev->result));
2075 seenerror = ISC_TRUE;
2079 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
2080 check_result(result, "dns_message_create");
2081 result = dns_request_getresponse(request, answer,
2082 DNS_MESSAGEPARSE_PRESERVEORDER);
2085 if (answer->verify_attempted)
2086 ddebug("tsig verification successful");
2088 case DNS_R_CLOCKSKEW:
2089 case DNS_R_EXPECTEDTSIG:
2090 case DNS_R_TSIGERRORSET:
2091 case DNS_R_TSIGVERIFYFAILURE:
2092 case DNS_R_UNEXPECTEDTSIG:
2095 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2097 * For MS DNS that violates RFC 2845, section 4.2
2102 fprintf(stderr, "; TSIG error with server: %s\n",
2103 isc_result_totext(result));
2104 seenerror = ISC_TRUE;
2107 check_result(result, "dns_request_getresponse");
2110 if (answer->rcode != dns_rcode_noerror) {
2111 seenerror = ISC_TRUE;
2115 dns_rdataset_t *rds;
2117 isc_buffer_init(&b, buf, sizeof(buf) - 1);
2118 result = dns_rcode_totext(answer->rcode, &b);
2119 check_result(result, "dns_rcode_totext");
2120 rds = dns_message_gettsig(answer, NULL);
2122 check_tsig_error(rds, &b);
2123 fprintf(stderr, "update failed: %.*s\n",
2124 (int)isc_buffer_usedlength(&b), buf);
2128 show_message(stderr, answer, "\nReply from update query:");
2131 dns_request_destroy(&request);
2133 dns_name_free(&tmpzonename, mctx);
2134 dns_name_free(&restart_master, mctx);
2136 isc_event_free(&event);
2141 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
2142 isc_sockaddr_t *srcaddr)
2144 isc_result_t result;
2145 dns_request_t *request = NULL;
2146 unsigned int options = DNS_REQUESTOPT_CASE;
2148 ddebug("send_update()");
2153 options |= DNS_REQUESTOPT_TCP;
2154 if (tsigkey == NULL && sig0key != NULL) {
2155 result = dns_message_setsig0key(updatemsg, sig0key);
2156 check_result(result, "dns_message_setsig0key");
2159 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2161 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2162 fprintf(stderr, "Sending update to %s\n", addrbuf);
2165 /* Windows doesn't like the tsig name to be compressed. */
2166 if (updatemsg->tsigname)
2167 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2169 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2170 master, options, tsigkey, timeout,
2171 udp_timeout, udp_retries, global_task,
2172 update_completed, NULL, &request);
2173 check_result(result, "dns_request_createvia3");
2176 show_message(stdout, updatemsg, "Outgoing update query:");
2182 recvsoa(isc_task_t *task, isc_event_t *event) {
2183 dns_requestevent_t *reqev = NULL;
2184 dns_request_t *request = NULL;
2185 isc_result_t result, eresult;
2186 dns_message_t *rcvmsg = NULL;
2187 dns_section_t section;
2188 dns_name_t *name = NULL;
2189 dns_rdataset_t *soaset = NULL;
2190 dns_rdata_soa_t soa;
2191 dns_rdata_t soarr = DNS_RDATA_INIT;
2194 nsu_requestinfo_t *reqinfo;
2195 dns_message_t *soaquery = NULL;
2196 isc_sockaddr_t *addr;
2197 isc_boolean_t seencname = ISC_FALSE;
2199 unsigned int nlabels;
2203 ddebug("recvsoa()");
2207 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2208 reqev = (dns_requestevent_t *)event;
2209 request = reqev->request;
2210 eresult = reqev->result;
2211 reqinfo = reqev->ev_arg;
2212 soaquery = reqinfo->msg;
2213 addr = reqinfo->addr;
2216 dns_request_destroy(&request);
2217 dns_message_destroy(&soaquery);
2218 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2219 isc_event_free(&event);
2224 if (eresult != ISC_R_SUCCESS) {
2225 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2227 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2228 fprintf(stderr, "; Communication with %s failed: %s\n",
2229 addrbuf, isc_result_totext(eresult));
2230 if (userserver != NULL)
2231 fatal("could not talk to specified name server");
2232 else if (++ns_inuse >= lwconf->nsnext)
2233 fatal("could not talk to any default name server");
2234 ddebug("Destroying request [%p]", request);
2235 dns_request_destroy(&request);
2236 dns_message_renderreset(soaquery);
2237 dns_message_settsigkey(soaquery, NULL);
2238 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2239 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2240 isc_event_free(&event);
2241 setzoneclass(dns_rdataclass_none);
2245 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2247 isc_event_free(&event);
2250 ddebug("About to create rcvmsg");
2251 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2252 check_result(result, "dns_message_create");
2253 result = dns_request_getresponse(request, rcvmsg,
2254 DNS_MESSAGEPARSE_PRESERVEORDER);
2255 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
2256 dns_message_destroy(&rcvmsg);
2257 ddebug("Destroying request [%p]", request);
2258 dns_request_destroy(&request);
2259 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2260 if (reqinfo == NULL)
2261 fatal("out of memory");
2262 reqinfo->msg = soaquery;
2263 reqinfo->addr = addr;
2264 dns_message_renderreset(soaquery);
2265 ddebug("retrying soa request without TSIG");
2266 result = dns_request_createvia3(requestmgr, soaquery,
2267 localaddr, addr, 0, NULL,
2270 global_task, recvsoa, reqinfo,
2272 check_result(result, "dns_request_createvia");
2276 check_result(result, "dns_request_getresponse");
2277 section = DNS_SECTION_ANSWER;
2280 show_message(stderr, rcvmsg, "Reply from SOA query:");
2282 if (rcvmsg->rcode != dns_rcode_noerror &&
2283 rcvmsg->rcode != dns_rcode_nxdomain)
2284 fatal("response to SOA query was unsuccessful");
2286 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2287 char namebuf[DNS_NAME_FORMATSIZE];
2288 dns_name_format(userzone, namebuf, sizeof(namebuf));
2289 error("specified zone '%s' does not exist (NXDOMAIN)",
2291 dns_message_destroy(&rcvmsg);
2292 dns_request_destroy(&request);
2293 dns_message_destroy(&soaquery);
2294 ddebug("Out of recvsoa");
2296 seenerror = ISC_TRUE;
2302 section = DNS_SECTION_ANSWER;
2304 section = DNS_SECTION_AUTHORITY;
2308 result = dns_message_firstname(rcvmsg, section);
2309 if (result != ISC_R_SUCCESS) {
2313 while (result == ISC_R_SUCCESS) {
2315 dns_message_currentname(rcvmsg, section, &name);
2317 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2319 if (result == ISC_R_SUCCESS)
2321 if (section == DNS_SECTION_ANSWER) {
2322 dns_rdataset_t *tset = NULL;
2323 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2324 &tset) == ISC_R_SUCCESS ||
2325 dns_message_findtype(name, dns_rdatatype_dname, 0,
2326 &tset) == ISC_R_SUCCESS ) {
2327 seencname = ISC_TRUE;
2332 result = dns_message_nextname(rcvmsg, section);
2335 if (soaset == NULL && !seencname) {
2344 char namestr[DNS_NAME_FORMATSIZE];
2345 dns_name_format(name, namestr, sizeof(namestr));
2346 fprintf(stderr, "Found zone name: %s\n", namestr);
2349 result = dns_rdataset_first(soaset);
2350 check_result(result, "dns_rdataset_first");
2352 dns_rdata_init(&soarr);
2353 dns_rdataset_current(soaset, &soarr);
2354 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2355 check_result(result, "dns_rdata_tostruct");
2357 dns_name_init(&master, NULL);
2358 dns_name_clone(&soa.origin, &master);
2360 if (userzone != NULL)
2361 zonename = userzone;
2366 char namestr[DNS_NAME_FORMATSIZE];
2367 dns_name_format(&master, namestr, sizeof(namestr));
2368 fprintf(stderr, "The master is: %s\n", namestr);
2371 if (userserver != NULL)
2372 serveraddr = userserver;
2374 char serverstr[DNS_NAME_MAXTEXT+1];
2377 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2378 result = dns_name_totext(&master, ISC_TRUE, &buf);
2379 check_result(result, "dns_name_totext");
2380 serverstr[isc_buffer_usedlength(&buf)] = 0;
2381 get_address(serverstr, dnsport, &tempaddr);
2382 serveraddr = &tempaddr;
2384 dns_rdata_freestruct(&soa);
2388 dns_name_init(&tmpzonename, NULL);
2389 dns_name_dup(zonename, mctx, &tmpzonename);
2390 dns_name_init(&restart_master, NULL);
2391 dns_name_dup(&master, mctx, &restart_master);
2392 start_gssrequest(&master);
2394 send_update(zonename, serveraddr, localaddr);
2395 setzoneclass(dns_rdataclass_none);
2398 send_update(zonename, serveraddr, localaddr);
2399 setzoneclass(dns_rdataclass_none);
2402 dns_message_destroy(&soaquery);
2403 dns_request_destroy(&request);
2406 dns_message_destroy(&rcvmsg);
2407 ddebug("Out of recvsoa");
2411 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2412 INSIST(result == ISC_R_SUCCESS);
2414 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2415 nlabels = dns_name_countlabels(name);
2417 fatal("could not find enclosing zone");
2418 dns_name_init(&tname, NULL);
2419 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2420 dns_name_clone(&tname, name);
2421 dns_request_destroy(&request);
2422 dns_message_renderreset(soaquery);
2423 dns_message_settsigkey(soaquery, NULL);
2424 if (userserver != NULL)
2425 sendrequest(localaddr, userserver, soaquery, &request);
2427 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2432 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2433 dns_message_t *msg, dns_request_t **request)
2435 isc_result_t result;
2436 nsu_requestinfo_t *reqinfo;
2438 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2439 if (reqinfo == NULL)
2440 fatal("out of memory");
2442 reqinfo->addr = destaddr;
2443 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2444 (userserver != NULL) ? tsigkey : NULL,
2445 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2446 global_task, recvsoa, reqinfo, request);
2447 check_result(result, "dns_request_createvia");
2454 * Get the realm from the users kerberos ticket if possible
2457 get_ticket_realm(isc_mem_t *mctx)
2462 krb5_principal princ;
2463 char *name, *ticket_realm;
2465 rc = krb5_init_context(&ctx);
2469 rc = krb5_cc_default(ctx, &ccache);
2471 krb5_free_context(ctx);
2475 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2477 krb5_cc_close(ctx, ccache);
2478 krb5_free_context(ctx);
2482 rc = krb5_unparse_name(ctx, princ, &name);
2484 krb5_free_principal(ctx, princ);
2485 krb5_cc_close(ctx, ccache);
2486 krb5_free_context(ctx);
2490 ticket_realm = strrchr(name, '@');
2491 if (ticket_realm != NULL) {
2492 realm = isc_mem_strdup(mctx, ticket_realm);
2496 krb5_free_principal(ctx, princ);
2497 krb5_cc_close(ctx, ccache);
2498 krb5_free_context(ctx);
2499 if (realm != NULL && debugging)
2500 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
2505 start_gssrequest(dns_name_t *master) {
2506 gss_ctx_id_t context;
2508 isc_result_t result;
2509 isc_uint32_t val = 0;
2510 dns_message_t *rmsg;
2511 dns_request_t *request = NULL;
2512 dns_name_t *servname;
2513 dns_fixedname_t fname;
2514 char namestr[DNS_NAME_FORMATSIZE];
2515 char keystr[DNS_NAME_FORMATSIZE];
2516 char *err_message = NULL;
2518 debug("start_gssrequest");
2521 if (gssring != NULL)
2522 dns_tsigkeyring_detach(&gssring);
2524 result = dns_tsigkeyring_create(mctx, &gssring);
2526 if (result != ISC_R_SUCCESS)
2527 fatal("dns_tsigkeyring_create failed: %s",
2528 isc_result_totext(result));
2530 dns_name_format(master, namestr, sizeof(namestr));
2531 if (kserver == NULL) {
2532 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2533 if (kserver == NULL)
2534 fatal("out of memory");
2536 if (userserver == NULL)
2537 get_address(namestr, dnsport, kserver);
2539 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2541 dns_fixedname_init(&fname);
2542 servname = dns_fixedname_name(&fname);
2545 get_ticket_realm(mctx);
2547 result = isc_string_printf(servicename, sizeof(servicename),
2548 "DNS/%s%s", namestr, realm ? realm : "");
2549 if (result != ISC_R_SUCCESS)
2550 fatal("isc_string_printf(servicename) failed: %s",
2551 isc_result_totext(result));
2552 isc_buffer_init(&buf, servicename, strlen(servicename));
2553 isc_buffer_add(&buf, strlen(servicename));
2554 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2555 if (result != ISC_R_SUCCESS)
2556 fatal("dns_name_fromtext(servname) failed: %s",
2557 isc_result_totext(result));
2559 dns_fixedname_init(&fkname);
2560 keyname = dns_fixedname_name(&fkname);
2562 isc_random_get(&val);
2563 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2565 if (result != ISC_R_SUCCESS)
2566 fatal("isc_string_printf(keystr) failed: %s",
2567 isc_result_totext(result));
2568 isc_buffer_init(&buf, keystr, strlen(keystr));
2569 isc_buffer_add(&buf, strlen(keystr));
2571 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
2572 if (result != ISC_R_SUCCESS)
2573 fatal("dns_name_fromtext(keyname) failed: %s",
2574 isc_result_totext(result));
2576 /* Windows doesn't recognize name compression in the key name. */
2577 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2580 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2581 if (result != ISC_R_SUCCESS)
2582 fatal("dns_message_create failed: %s",
2583 isc_result_totext(result));
2585 /* Build first request. */
2586 context = GSS_C_NO_CONTEXT;
2587 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2588 &context, use_win2k_gsstsig,
2589 mctx, &err_message);
2590 if (result == ISC_R_FAILURE)
2591 fatal("tkey query failed: %s",
2592 err_message != NULL ? err_message : "unknown error");
2593 if (result != ISC_R_SUCCESS)
2594 fatal("dns_tkey_buildgssquery failed: %s",
2595 isc_result_totext(result));
2597 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2601 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2602 dns_message_t *msg, dns_request_t **request,
2603 gss_ctx_id_t context)
2605 isc_result_t result;
2606 nsu_gssinfo_t *reqinfo;
2607 unsigned int options = 0;
2609 debug("send_gssrequest");
2610 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2611 if (reqinfo == NULL)
2612 fatal("out of memory");
2614 reqinfo->addr = destaddr;
2615 reqinfo->context = context;
2617 options |= DNS_REQUESTOPT_TCP;
2618 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2619 options, tsigkey, FIND_TIMEOUT * 20,
2620 FIND_TIMEOUT, 3, global_task, recvgss,
2622 check_result(result, "dns_request_createvia3");
2624 show_message(stdout, msg, "Outgoing update query:");
2629 recvgss(isc_task_t *task, isc_event_t *event) {
2630 dns_requestevent_t *reqev = NULL;
2631 dns_request_t *request = NULL;
2632 isc_result_t result, eresult;
2633 dns_message_t *rcvmsg = NULL;
2634 nsu_gssinfo_t *reqinfo;
2635 dns_message_t *tsigquery = NULL;
2636 isc_sockaddr_t *addr;
2637 gss_ctx_id_t context;
2639 dns_name_t *servname;
2640 dns_fixedname_t fname;
2641 char *err_message = NULL;
2645 ddebug("recvgss()");
2649 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2650 reqev = (dns_requestevent_t *)event;
2651 request = reqev->request;
2652 eresult = reqev->result;
2653 reqinfo = reqev->ev_arg;
2654 tsigquery = reqinfo->msg;
2655 context = reqinfo->context;
2656 addr = reqinfo->addr;
2659 dns_request_destroy(&request);
2660 dns_message_destroy(&tsigquery);
2661 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2662 isc_event_free(&event);
2667 if (eresult != ISC_R_SUCCESS) {
2668 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2670 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2671 fprintf(stderr, "; Communication with %s failed: %s\n",
2672 addrbuf, isc_result_totext(eresult));
2673 if (userserver != NULL)
2674 fatal("could not talk to specified name server");
2675 else if (++ns_inuse >= lwconf->nsnext)
2676 fatal("could not talk to any default name server");
2677 ddebug("Destroying request [%p]", request);
2678 dns_request_destroy(&request);
2679 dns_message_renderreset(tsigquery);
2680 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2682 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2683 isc_event_free(&event);
2686 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2688 isc_event_free(&event);
2691 ddebug("recvgss creating rcvmsg");
2692 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2693 check_result(result, "dns_message_create");
2695 result = dns_request_getresponse(request, rcvmsg,
2696 DNS_MESSAGEPARSE_PRESERVEORDER);
2697 check_result(result, "dns_request_getresponse");
2700 show_message(stderr, rcvmsg,
2701 "recvmsg reply from GSS-TSIG query");
2703 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2704 ddebug("recvgss trying %s GSS-TSIG",
2705 use_win2k_gsstsig ? "Standard" : "Win2k");
2706 if (use_win2k_gsstsig)
2707 use_win2k_gsstsig = ISC_FALSE;
2709 use_win2k_gsstsig = ISC_TRUE;
2710 tried_other_gsstsig = ISC_TRUE;
2711 start_gssrequest(&restart_master);
2715 if (rcvmsg->rcode != dns_rcode_noerror &&
2716 rcvmsg->rcode != dns_rcode_nxdomain)
2717 fatal("response to GSS-TSIG query was unsuccessful");
2720 dns_fixedname_init(&fname);
2721 servname = dns_fixedname_name(&fname);
2722 isc_buffer_init(&buf, servicename, strlen(servicename));
2723 isc_buffer_add(&buf, strlen(servicename));
2724 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2725 check_result(result, "dns_name_fromtext");
2728 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2729 &context, &tsigkey, gssring,
2734 case DNS_R_CONTINUE:
2735 send_gssrequest(localaddr, kserver, tsigquery, &request,
2741 * XXXSRA Waaay too much fun here. There's no good
2742 * reason why we need a TSIG here (the people who put
2743 * it into the spec admitted at the time that it was
2744 * not a security issue), and Windows clients don't
2745 * seem to work if named complies with the spec and
2746 * includes the gratuitous TSIG. So we're in the
2747 * bizarre situation of having to choose between
2748 * complying with a useless requirement in the spec
2749 * and interoperating. This is nuts. If we can
2750 * confirm this behavior, we should ask the WG to
2751 * consider removing the requirement for the
2752 * gratuitous TSIG here. For the moment, we ignore
2753 * the TSIG -- this too is a spec violation, but it's
2754 * the least insane thing to do.
2758 * Verify the signature.
2760 rcvmsg->state = DNS_SECTION_ANY;
2761 dns_message_setquerytsig(rcvmsg, NULL);
2762 result = dns_message_settsigkey(rcvmsg, tsigkey);
2763 check_result(result, "dns_message_settsigkey");
2764 result = dns_message_checksig(rcvmsg, NULL);
2765 ddebug("tsig verification: %s", dns_result_totext(result));
2766 check_result(result, "dns_message_checksig");
2769 send_update(&tmpzonename, serveraddr, localaddr);
2770 setzoneclass(dns_rdataclass_none);
2774 fatal("dns_tkey_negotiategss: %s %s",
2775 isc_result_totext(result),
2776 err_message != NULL ? err_message : "");
2780 dns_request_destroy(&request);
2781 dns_message_destroy(&tsigquery);
2783 dns_message_destroy(&rcvmsg);
2784 ddebug("Out of recvgss");
2789 start_update(void) {
2790 isc_result_t result;
2791 dns_rdataset_t *rdataset = NULL;
2792 dns_name_t *name = NULL;
2793 dns_request_t *request = NULL;
2794 dns_message_t *soaquery = NULL;
2795 dns_name_t *firstname;
2796 dns_section_t section = DNS_SECTION_UPDATE;
2798 ddebug("start_update()");
2801 dns_message_destroy(&answer);
2803 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2804 send_update(userzone, userserver, localaddr);
2805 setzoneclass(dns_rdataclass_none);
2809 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2811 check_result(result, "dns_message_create");
2813 if (userserver == NULL)
2814 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2816 result = dns_message_gettempname(soaquery, &name);
2817 check_result(result, "dns_message_gettempname");
2819 result = dns_message_gettemprdataset(soaquery, &rdataset);
2820 check_result(result, "dns_message_gettemprdataset");
2822 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2824 if (userzone != NULL) {
2825 dns_name_init(name, NULL);
2826 dns_name_clone(userzone, name);
2828 dns_rdataset_t *tmprdataset;
2829 result = dns_message_firstname(updatemsg, section);
2830 if (result == ISC_R_NOMORE) {
2831 section = DNS_SECTION_PREREQUISITE;
2832 result = dns_message_firstname(updatemsg, section);
2834 if (result != ISC_R_SUCCESS) {
2835 dns_message_puttempname(soaquery, &name);
2836 dns_rdataset_disassociate(rdataset);
2837 dns_message_puttemprdataset(soaquery, &rdataset);
2838 dns_message_destroy(&soaquery);
2843 dns_message_currentname(updatemsg, section, &firstname);
2844 dns_name_init(name, NULL);
2845 dns_name_clone(firstname, name);
2847 * Looks to see if the first name references a DS record
2848 * and if that name is not the root remove a label as DS
2849 * records live in the parent zone so we need to start our
2850 * search one label up.
2852 tmprdataset = ISC_LIST_HEAD(firstname->list);
2853 if (section == DNS_SECTION_UPDATE &&
2854 !dns_name_equal(firstname, dns_rootname) &&
2855 tmprdataset->type == dns_rdatatype_ds) {
2856 unsigned int labels = dns_name_countlabels(name);
2857 dns_name_getlabelsequence(name, 1, labels - 1, name);
2861 ISC_LIST_INIT(name->list);
2862 ISC_LIST_APPEND(name->list, rdataset, link);
2863 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2865 if (userserver != NULL)
2866 sendrequest(localaddr, userserver, soaquery, &request);
2869 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2875 ddebug("cleanup()");
2878 dns_message_destroy(&answer);
2881 if (tsigkey != NULL) {
2882 ddebug("detach tsigkey x%p", tsigkey);
2883 dns_tsigkey_detach(&tsigkey);
2885 if (gssring != NULL) {
2886 ddebug("Detaching GSS-TSIG keyring");
2887 dns_tsigkeyring_detach(&gssring);
2889 if (kserver != NULL) {
2890 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2893 if (realm != NULL) {
2894 isc_mem_free(mctx, realm);
2899 if (sig0key != NULL)
2900 dst_key_free(&sig0key);
2902 ddebug("Shutting down task manager");
2903 isc_taskmgr_destroy(&taskmgr);
2905 ddebug("Destroying event");
2906 isc_event_free(&global_event);
2908 ddebug("Shutting down socket manager");
2909 isc_socketmgr_destroy(&socketmgr);
2911 ddebug("Shutting down timer manager");
2912 isc_timermgr_destroy(&timermgr);
2914 ddebug("Destroying hash context");
2917 ddebug("Destroying name state");
2920 ddebug("Removing log context");
2921 isc_log_destroy(&lctx);
2923 ddebug("Destroying memory context");
2925 isc_mem_stats(mctx, stderr);
2926 isc_mem_destroy(&mctx);
2930 getinput(isc_task_t *task, isc_event_t *event) {
2940 if (global_event == NULL)
2941 global_event = event;
2944 more = user_interaction();
2954 main(int argc, char **argv) {
2955 isc_result_t result;
2956 style = &dns_master_style_debug;
2960 interactive = ISC_TF(isatty(0));
2964 pre_parse_args(argc, argv);
2966 result = isc_mem_create(0, 0, &mctx);
2967 check_result(result, "isc_mem_create");
2969 parse_args(argc, argv, mctx, &entropy);
2973 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2974 check_result(result, "isc_app_onrun");
2976 (void)isc_app_run();