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.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: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");
2283 seenerror = ISC_TRUE;
2289 section = DNS_SECTION_ANSWER;
2291 section = DNS_SECTION_AUTHORITY;
2295 result = dns_message_firstname(rcvmsg, section);
2296 if (result != ISC_R_SUCCESS) {
2300 while (result == ISC_R_SUCCESS) {
2302 dns_message_currentname(rcvmsg, section, &name);
2304 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2306 if (result == ISC_R_SUCCESS)
2308 if (section == DNS_SECTION_ANSWER) {
2309 dns_rdataset_t *tset = NULL;
2310 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2311 &tset) == ISC_R_SUCCESS ||
2312 dns_message_findtype(name, dns_rdatatype_dname, 0,
2313 &tset) == ISC_R_SUCCESS ) {
2314 seencname = ISC_TRUE;
2319 result = dns_message_nextname(rcvmsg, section);
2322 if (soaset == NULL && !seencname) {
2331 char namestr[DNS_NAME_FORMATSIZE];
2332 dns_name_format(name, namestr, sizeof(namestr));
2333 fprintf(stderr, "Found zone name: %s\n", namestr);
2336 result = dns_rdataset_first(soaset);
2337 check_result(result, "dns_rdataset_first");
2339 dns_rdata_init(&soarr);
2340 dns_rdataset_current(soaset, &soarr);
2341 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2342 check_result(result, "dns_rdata_tostruct");
2344 dns_name_init(&master, NULL);
2345 dns_name_clone(&soa.origin, &master);
2347 if (userzone != NULL)
2348 zonename = userzone;
2353 char namestr[DNS_NAME_FORMATSIZE];
2354 dns_name_format(&master, namestr, sizeof(namestr));
2355 fprintf(stderr, "The master is: %s\n", namestr);
2358 if (userserver != NULL)
2359 serveraddr = userserver;
2361 char serverstr[DNS_NAME_MAXTEXT+1];
2364 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2365 result = dns_name_totext(&master, ISC_TRUE, &buf);
2366 check_result(result, "dns_name_totext");
2367 serverstr[isc_buffer_usedlength(&buf)] = 0;
2368 get_address(serverstr, dnsport, &tempaddr);
2369 serveraddr = &tempaddr;
2371 dns_rdata_freestruct(&soa);
2375 dns_name_init(&tmpzonename, NULL);
2376 dns_name_dup(zonename, mctx, &tmpzonename);
2377 dns_name_init(&restart_master, NULL);
2378 dns_name_dup(&master, mctx, &restart_master);
2379 start_gssrequest(&master);
2381 send_update(zonename, serveraddr, localaddr);
2382 setzoneclass(dns_rdataclass_none);
2385 send_update(zonename, serveraddr, localaddr);
2386 setzoneclass(dns_rdataclass_none);
2389 dns_message_destroy(&soaquery);
2390 dns_request_destroy(&request);
2393 dns_message_destroy(&rcvmsg);
2394 ddebug("Out of recvsoa");
2398 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2399 INSIST(result == ISC_R_SUCCESS);
2401 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2402 nlabels = dns_name_countlabels(name);
2404 fatal("could not find enclosing zone");
2405 dns_name_init(&tname, NULL);
2406 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2407 dns_name_clone(&tname, name);
2408 dns_request_destroy(&request);
2409 dns_message_renderreset(soaquery);
2410 dns_message_settsigkey(soaquery, NULL);
2411 if (userserver != NULL)
2412 sendrequest(localaddr, userserver, soaquery, &request);
2414 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2419 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2420 dns_message_t *msg, dns_request_t **request)
2422 isc_result_t result;
2423 nsu_requestinfo_t *reqinfo;
2425 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
2426 if (reqinfo == NULL)
2427 fatal("out of memory");
2429 reqinfo->addr = destaddr;
2430 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2431 (userserver != NULL) ? tsigkey : NULL,
2432 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2433 global_task, recvsoa, reqinfo, request);
2434 check_result(result, "dns_request_createvia");
2441 * Get the realm from the users kerberos ticket if possible
2444 get_ticket_realm(isc_mem_t *mctx)
2449 krb5_principal princ;
2450 char *name, *ticket_realm;
2452 rc = krb5_init_context(&ctx);
2456 rc = krb5_cc_default(ctx, &ccache);
2458 krb5_free_context(ctx);
2462 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2464 krb5_cc_close(ctx, ccache);
2465 krb5_free_context(ctx);
2469 rc = krb5_unparse_name(ctx, princ, &name);
2471 krb5_free_principal(ctx, princ);
2472 krb5_cc_close(ctx, ccache);
2473 krb5_free_context(ctx);
2477 ticket_realm = strrchr(name, '@');
2478 if (ticket_realm != NULL) {
2479 realm = isc_mem_strdup(mctx, ticket_realm);
2483 krb5_free_principal(ctx, princ);
2484 krb5_cc_close(ctx, ccache);
2485 krb5_free_context(ctx);
2486 if (realm != NULL && debugging)
2487 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
2492 start_gssrequest(dns_name_t *master) {
2493 gss_ctx_id_t context;
2495 isc_result_t result;
2496 isc_uint32_t val = 0;
2497 dns_message_t *rmsg;
2498 dns_request_t *request = NULL;
2499 dns_name_t *servname;
2500 dns_fixedname_t fname;
2501 char namestr[DNS_NAME_FORMATSIZE];
2502 char keystr[DNS_NAME_FORMATSIZE];
2503 char *err_message = NULL;
2505 debug("start_gssrequest");
2508 if (gssring != NULL)
2509 dns_tsigkeyring_detach(&gssring);
2511 result = dns_tsigkeyring_create(mctx, &gssring);
2513 if (result != ISC_R_SUCCESS)
2514 fatal("dns_tsigkeyring_create failed: %s",
2515 isc_result_totext(result));
2517 dns_name_format(master, namestr, sizeof(namestr));
2518 if (kserver == NULL) {
2519 kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
2520 if (kserver == NULL)
2521 fatal("out of memory");
2523 if (userserver == NULL)
2524 get_address(namestr, dnsport, kserver);
2526 (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
2528 dns_fixedname_init(&fname);
2529 servname = dns_fixedname_name(&fname);
2532 get_ticket_realm(mctx);
2534 result = isc_string_printf(servicename, sizeof(servicename),
2535 "DNS/%s%s", namestr, realm ? realm : "");
2536 if (result != ISC_R_SUCCESS)
2537 fatal("isc_string_printf(servicename) failed: %s",
2538 isc_result_totext(result));
2539 isc_buffer_init(&buf, servicename, strlen(servicename));
2540 isc_buffer_add(&buf, strlen(servicename));
2541 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2542 if (result != ISC_R_SUCCESS)
2543 fatal("dns_name_fromtext(servname) failed: %s",
2544 isc_result_totext(result));
2546 dns_fixedname_init(&fkname);
2547 keyname = dns_fixedname_name(&fkname);
2549 isc_random_get(&val);
2550 result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
2552 if (result != ISC_R_SUCCESS)
2553 fatal("isc_string_printf(keystr) failed: %s",
2554 isc_result_totext(result));
2555 isc_buffer_init(&buf, keystr, strlen(keystr));
2556 isc_buffer_add(&buf, strlen(keystr));
2558 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
2559 if (result != ISC_R_SUCCESS)
2560 fatal("dns_name_fromtext(keyname) failed: %s",
2561 isc_result_totext(result));
2563 /* Windows doesn't recognize name compression in the key name. */
2564 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2567 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2568 if (result != ISC_R_SUCCESS)
2569 fatal("dns_message_create failed: %s",
2570 isc_result_totext(result));
2572 /* Build first request. */
2573 context = GSS_C_NO_CONTEXT;
2574 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2575 &context, use_win2k_gsstsig,
2576 mctx, &err_message);
2577 if (result == ISC_R_FAILURE)
2578 fatal("tkey query failed: %s",
2579 err_message != NULL ? err_message : "unknown error");
2580 if (result != ISC_R_SUCCESS)
2581 fatal("dns_tkey_buildgssquery failed: %s",
2582 isc_result_totext(result));
2584 send_gssrequest(localaddr, kserver, rmsg, &request, context);
2588 send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
2589 dns_message_t *msg, dns_request_t **request,
2590 gss_ctx_id_t context)
2592 isc_result_t result;
2593 nsu_gssinfo_t *reqinfo;
2594 unsigned int options = 0;
2596 debug("send_gssrequest");
2597 reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
2598 if (reqinfo == NULL)
2599 fatal("out of memory");
2601 reqinfo->addr = destaddr;
2602 reqinfo->context = context;
2604 options |= DNS_REQUESTOPT_TCP;
2605 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2606 options, tsigkey, FIND_TIMEOUT * 20,
2607 FIND_TIMEOUT, 3, global_task, recvgss,
2609 check_result(result, "dns_request_createvia3");
2611 show_message(stdout, msg, "Outgoing update query:");
2616 recvgss(isc_task_t *task, isc_event_t *event) {
2617 dns_requestevent_t *reqev = NULL;
2618 dns_request_t *request = NULL;
2619 isc_result_t result, eresult;
2620 dns_message_t *rcvmsg = NULL;
2621 nsu_gssinfo_t *reqinfo;
2622 dns_message_t *tsigquery = NULL;
2623 isc_sockaddr_t *addr;
2624 gss_ctx_id_t context;
2626 dns_name_t *servname;
2627 dns_fixedname_t fname;
2628 char *err_message = NULL;
2632 ddebug("recvgss()");
2636 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2637 reqev = (dns_requestevent_t *)event;
2638 request = reqev->request;
2639 eresult = reqev->result;
2640 reqinfo = reqev->ev_arg;
2641 tsigquery = reqinfo->msg;
2642 context = reqinfo->context;
2643 addr = reqinfo->addr;
2646 dns_request_destroy(&request);
2647 dns_message_destroy(&tsigquery);
2648 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2649 isc_event_free(&event);
2654 if (eresult != ISC_R_SUCCESS) {
2655 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2657 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2658 fprintf(stderr, "; Communication with %s failed: %s\n",
2659 addrbuf, isc_result_totext(eresult));
2660 if (userserver != NULL)
2661 fatal("could not talk to specified name server");
2662 else if (++ns_inuse >= lwconf->nsnext)
2663 fatal("could not talk to any default name server");
2664 ddebug("Destroying request [%p]", request);
2665 dns_request_destroy(&request);
2666 dns_message_renderreset(tsigquery);
2667 sendrequest(localaddr, &servers[ns_inuse], tsigquery,
2669 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2670 isc_event_free(&event);
2673 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2675 isc_event_free(&event);
2678 ddebug("recvgss creating rcvmsg");
2679 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2680 check_result(result, "dns_message_create");
2682 result = dns_request_getresponse(request, rcvmsg,
2683 DNS_MESSAGEPARSE_PRESERVEORDER);
2684 check_result(result, "dns_request_getresponse");
2687 show_message(stderr, rcvmsg,
2688 "recvmsg reply from GSS-TSIG query");
2690 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2691 ddebug("recvgss trying %s GSS-TSIG",
2692 use_win2k_gsstsig ? "Standard" : "Win2k");
2693 if (use_win2k_gsstsig)
2694 use_win2k_gsstsig = ISC_FALSE;
2696 use_win2k_gsstsig = ISC_TRUE;
2697 tried_other_gsstsig = ISC_TRUE;
2698 start_gssrequest(&restart_master);
2702 if (rcvmsg->rcode != dns_rcode_noerror &&
2703 rcvmsg->rcode != dns_rcode_nxdomain)
2704 fatal("response to GSS-TSIG query was unsuccessful");
2707 dns_fixedname_init(&fname);
2708 servname = dns_fixedname_name(&fname);
2709 isc_buffer_init(&buf, servicename, strlen(servicename));
2710 isc_buffer_add(&buf, strlen(servicename));
2711 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2712 check_result(result, "dns_name_fromtext");
2715 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2716 &context, &tsigkey, gssring,
2721 case DNS_R_CONTINUE:
2722 send_gssrequest(localaddr, kserver, tsigquery, &request,
2728 * XXXSRA Waaay too much fun here. There's no good
2729 * reason why we need a TSIG here (the people who put
2730 * it into the spec admitted at the time that it was
2731 * not a security issue), and Windows clients don't
2732 * seem to work if named complies with the spec and
2733 * includes the gratuitous TSIG. So we're in the
2734 * bizarre situation of having to choose between
2735 * complying with a useless requirement in the spec
2736 * and interoperating. This is nuts. If we can
2737 * confirm this behavior, we should ask the WG to
2738 * consider removing the requirement for the
2739 * gratuitous TSIG here. For the moment, we ignore
2740 * the TSIG -- this too is a spec violation, but it's
2741 * the least insane thing to do.
2745 * Verify the signature.
2747 rcvmsg->state = DNS_SECTION_ANY;
2748 dns_message_setquerytsig(rcvmsg, NULL);
2749 result = dns_message_settsigkey(rcvmsg, tsigkey);
2750 check_result(result, "dns_message_settsigkey");
2751 result = dns_message_checksig(rcvmsg, NULL);
2752 ddebug("tsig verification: %s", dns_result_totext(result));
2753 check_result(result, "dns_message_checksig");
2756 send_update(&tmpzonename, serveraddr, localaddr);
2757 setzoneclass(dns_rdataclass_none);
2761 fatal("dns_tkey_negotiategss: %s %s",
2762 isc_result_totext(result),
2763 err_message != NULL ? err_message : "");
2767 dns_request_destroy(&request);
2768 dns_message_destroy(&tsigquery);
2770 dns_message_destroy(&rcvmsg);
2771 ddebug("Out of recvgss");
2776 start_update(void) {
2777 isc_result_t result;
2778 dns_rdataset_t *rdataset = NULL;
2779 dns_name_t *name = NULL;
2780 dns_request_t *request = NULL;
2781 dns_message_t *soaquery = NULL;
2782 dns_name_t *firstname;
2783 dns_section_t section = DNS_SECTION_UPDATE;
2785 ddebug("start_update()");
2788 dns_message_destroy(&answer);
2790 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2791 send_update(userzone, userserver, localaddr);
2792 setzoneclass(dns_rdataclass_none);
2796 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2798 check_result(result, "dns_message_create");
2800 if (userserver == NULL)
2801 soaquery->flags |= DNS_MESSAGEFLAG_RD;
2803 result = dns_message_gettempname(soaquery, &name);
2804 check_result(result, "dns_message_gettempname");
2806 result = dns_message_gettemprdataset(soaquery, &rdataset);
2807 check_result(result, "dns_message_gettemprdataset");
2809 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
2811 if (userzone != NULL) {
2812 dns_name_init(name, NULL);
2813 dns_name_clone(userzone, name);
2815 dns_rdataset_t *tmprdataset;
2816 result = dns_message_firstname(updatemsg, section);
2817 if (result == ISC_R_NOMORE) {
2818 section = DNS_SECTION_PREREQUISITE;
2819 result = dns_message_firstname(updatemsg, section);
2821 if (result != ISC_R_SUCCESS) {
2822 dns_message_puttempname(soaquery, &name);
2823 dns_rdataset_disassociate(rdataset);
2824 dns_message_puttemprdataset(soaquery, &rdataset);
2825 dns_message_destroy(&soaquery);
2830 dns_message_currentname(updatemsg, section, &firstname);
2831 dns_name_init(name, NULL);
2832 dns_name_clone(firstname, name);
2834 * Looks to see if the first name references a DS record
2835 * and if that name is not the root remove a label as DS
2836 * records live in the parent zone so we need to start our
2837 * search one label up.
2839 tmprdataset = ISC_LIST_HEAD(firstname->list);
2840 if (section == DNS_SECTION_UPDATE &&
2841 !dns_name_equal(firstname, dns_rootname) &&
2842 tmprdataset->type == dns_rdatatype_ds) {
2843 unsigned int labels = dns_name_countlabels(name);
2844 dns_name_getlabelsequence(name, 1, labels - 1, name);
2848 ISC_LIST_INIT(name->list);
2849 ISC_LIST_APPEND(name->list, rdataset, link);
2850 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
2852 if (userserver != NULL)
2853 sendrequest(localaddr, userserver, soaquery, &request);
2856 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2862 ddebug("cleanup()");
2865 dns_message_destroy(&answer);
2868 if (tsigkey != NULL) {
2869 ddebug("detach tsigkey x%p", tsigkey);
2870 dns_tsigkey_detach(&tsigkey);
2872 if (gssring != NULL) {
2873 ddebug("Detaching GSS-TSIG keyring");
2874 dns_tsigkeyring_detach(&gssring);
2876 if (kserver != NULL) {
2877 isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
2880 if (realm != NULL) {
2881 isc_mem_free(mctx, realm);
2886 if (sig0key != NULL)
2887 dst_key_free(&sig0key);
2889 ddebug("Shutting down task manager");
2890 isc_taskmgr_destroy(&taskmgr);
2892 ddebug("Destroying event");
2893 isc_event_free(&global_event);
2895 ddebug("Shutting down socket manager");
2896 isc_socketmgr_destroy(&socketmgr);
2898 ddebug("Shutting down timer manager");
2899 isc_timermgr_destroy(&timermgr);
2901 ddebug("Destroying hash context");
2904 ddebug("Destroying name state");
2907 ddebug("Removing log context");
2908 isc_log_destroy(&lctx);
2910 ddebug("Destroying memory context");
2912 isc_mem_stats(mctx, stderr);
2913 isc_mem_destroy(&mctx);
2917 getinput(isc_task_t *task, isc_event_t *event) {
2927 if (global_event == NULL)
2928 global_event = event;
2931 more = user_interaction();
2941 main(int argc, char **argv) {
2942 isc_result_t result;
2943 style = &dns_master_style_debug;
2947 interactive = ISC_TF(isatty(0));
2951 pre_parse_args(argc, argv);
2953 result = isc_mem_create(0, 0, &mctx);
2954 check_result(result, "isc_mem_create");
2956 parse_args(argc, argv, mctx, &entropy);
2960 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2961 check_result(result, "isc_app_onrun");
2963 (void)isc_app_run();