2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and 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.103.2.23 2004/05/12 04:46:17 marka Exp $ */
30 #include <isc/base64.h>
31 #include <isc/buffer.h>
32 #include <isc/commandline.h>
33 #include <isc/entropy.h>
34 #include <isc/event.h>
38 #include <isc/region.h>
39 #include <isc/sockaddr.h>
40 #include <isc/socket.h>
41 #include <isc/stdio.h>
42 #include <isc/string.h>
44 #include <isc/timer.h>
45 #include <isc/types.h>
48 #include <dns/callbacks.h>
49 #include <dns/dispatch.h>
50 #include <dns/events.h>
51 #include <dns/fixedname.h>
52 #include <dns/masterdump.h>
53 #include <dns/message.h>
55 #include <dns/rcode.h>
56 #include <dns/rdata.h>
57 #include <dns/rdataclass.h>
58 #include <dns/rdatalist.h>
59 #include <dns/rdataset.h>
60 #include <dns/rdatastruct.h>
61 #include <dns/rdatatype.h>
62 #include <dns/request.h>
63 #include <dns/result.h>
68 #include <lwres/lwres.h>
69 #include <lwres/net.h>
72 #ifdef HAVE_GETADDRINFO
73 #ifdef HAVE_GAISTRERROR
74 #define USE_GETADDRINFO
79 #ifndef USE_GETADDRINFO
80 #ifndef ISC_PLATFORM_NONSTDHERRNO
85 #define MAXCMD (4 * 1024)
86 #define MAXWIRE (64 * 1024)
89 #define PACKETSIZE ((64 * 1024) - 1)
90 #define INITTEXT (2 * 1024)
91 #define MAXTEXT (128 * 1024)
92 #define FIND_TIMEOUT 5
93 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
95 #define DNSDEFAULTPORT 53
98 #define RESOLV_CONF "/etc/resolv.conf"
101 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
102 static isc_boolean_t memdebugging = ISC_FALSE;
103 static isc_boolean_t have_ipv4 = ISC_FALSE;
104 static isc_boolean_t have_ipv6 = ISC_FALSE;
105 static isc_boolean_t is_dst_up = ISC_FALSE;
106 static isc_boolean_t usevc = ISC_FALSE;
107 static isc_taskmgr_t *taskmgr = NULL;
108 static isc_task_t *global_task = NULL;
109 static isc_event_t *global_event = NULL;
110 static isc_mem_t *mctx = NULL;
111 static dns_dispatchmgr_t *dispatchmgr = NULL;
112 static dns_requestmgr_t *requestmgr = NULL;
113 static isc_socketmgr_t *socketmgr = NULL;
114 static isc_timermgr_t *timermgr = NULL;
115 static dns_dispatch_t *dispatchv4 = NULL;
116 static dns_dispatch_t *dispatchv6 = NULL;
117 static dns_message_t *updatemsg = NULL;
118 static dns_fixedname_t fuserzone;
119 static dns_name_t *userzone = NULL;
120 static dns_tsigkey_t *key = NULL;
121 static lwres_context_t *lwctx = NULL;
122 static lwres_conf_t *lwconf;
123 static isc_sockaddr_t *servers;
124 static int ns_inuse = 0;
125 static int ns_total = 0;
126 static isc_sockaddr_t *userserver = NULL;
127 static isc_sockaddr_t *localaddr = NULL;
128 static char *keystr = NULL, *keyfile = NULL;
129 static isc_entropy_t *entp = NULL;
130 static isc_boolean_t shuttingdown = ISC_FALSE;
132 static isc_boolean_t interactive = ISC_TRUE;
133 static isc_boolean_t seenerror = ISC_FALSE;
134 static const dns_master_style_t *style;
135 static int requests = 0;
136 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
137 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
139 typedef struct nsu_requestinfo {
141 isc_sockaddr_t *addr;
145 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
146 dns_message_t *msg, dns_request_t **request);
148 fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
151 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
154 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
156 #define STATUS_MORE (isc_uint16_t)0
157 #define STATUS_SEND (isc_uint16_t)1
158 #define STATUS_QUIT (isc_uint16_t)2
159 #define STATUS_SYNTAX (isc_uint16_t)3
161 static dns_rdataclass_t
163 if (zoneclass == dns_rdataclass_none)
164 zoneclass = defaultclass;
169 setzoneclass(dns_rdataclass_t rdclass) {
170 if (zoneclass == dns_rdataclass_none ||
171 rdclass == dns_rdataclass_none)
173 if (zoneclass != rdclass)
179 fatal(const char *format, ...) {
182 va_start(args, format);
183 vfprintf(stderr, format, args);
185 fprintf(stderr, "\n");
190 debug(const char *format, ...) {
194 va_start(args, format);
195 vfprintf(stderr, format, args);
197 fprintf(stderr, "\n");
202 ddebug(const char *format, ...) {
206 va_start(args, format);
207 vfprintf(stderr, format, args);
209 fprintf(stderr, "\n");
214 check_result(isc_result_t result, const char *msg) {
215 if (result != ISC_R_SUCCESS)
216 fatal("%s: %s", msg, isc_result_totext(result));
220 mem_alloc(void *arg, size_t size) {
221 return (isc_mem_get(arg, size));
225 mem_free(void *arg, void *mem, size_t size) {
226 isc_mem_put(arg, mem, size);
230 nsu_strsep(char **stringp, const char *delim) {
231 char *string = *stringp;
239 for (; *string != '\0'; string++) {
241 for (d = delim; (dc = *d) != '\0'; d++) {
249 for (s = string; *s != '\0'; s++) {
251 for (d = delim; (dc = *d) != '\0'; d++) {
267 ddebug("reset_system()");
268 /* If the update message is still around, destroy it */
269 if (updatemsg != NULL)
270 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
272 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
274 check_result(result, "dns_message_create");
276 updatemsg->opcode = dns_opcode_update;
281 unsigned char *secret = NULL;
283 isc_buffer_t secretbuf;
285 isc_buffer_t keynamesrc;
288 dns_fixedname_t fkeyname;
291 dns_fixedname_init(&fkeyname);
292 keyname = dns_fixedname_name(&fkeyname);
294 debug("Creating key...");
296 s = strchr(keystr, ':');
297 if (s == NULL || s == keystr || *s == 0)
298 fatal("key option must specify keyname:secret");
301 isc_buffer_init(&keynamesrc, keystr, s - keystr);
302 isc_buffer_add(&keynamesrc, s - keystr);
304 debug("namefromtext");
305 result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname,
307 check_result(result, "dns_name_fromtext");
309 secretlen = strlen(secretstr) * 3 / 4;
310 secret = isc_mem_allocate(mctx, secretlen);
312 fatal("out of memory");
314 isc_buffer_init(&secretbuf, secret, secretlen);
315 result = isc_base64_decodestring(secretstr, &secretbuf);
316 if (result != ISC_R_SUCCESS) {
317 fprintf(stderr, "could not create key from %s: %s\n",
318 keystr, isc_result_totext(result));
322 secretlen = isc_buffer_usedlength(&secretbuf);
325 result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name,
326 secret, secretlen, ISC_TRUE, NULL,
327 0, 0, mctx, NULL, &key);
328 if (result != ISC_R_SUCCESS)
329 fprintf(stderr, "could not create key from %s: %s\n",
330 keystr, dns_result_totext(result));
333 isc_mem_free(mctx, secret);
337 setup_keyfile(void) {
338 dst_key_t *dstkey = NULL;
341 debug("Creating key...");
343 result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE, mctx,
345 if (result != ISC_R_SUCCESS) {
346 fprintf(stderr, "could not read key from %s: %s\n",
347 keyfile, isc_result_totext(result));
350 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
351 dns_tsig_hmacmd5_name,
352 dstkey, ISC_FALSE, NULL,
353 0, 0, mctx, NULL, &key);
354 if (result != ISC_R_SUCCESS) {
355 fprintf(stderr, "could not create key from %s: %s\n",
356 keyfile, isc_result_totext(result));
357 dst_key_free(&dstkey);
364 isc_task_detach(&global_task);
366 if (userserver != NULL)
367 isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
369 if (localaddr != NULL)
370 isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
373 ddebug("Freeing key");
374 dns_tsigkey_detach(&key);
377 if (updatemsg != NULL)
378 dns_message_destroy(&updatemsg);
381 ddebug("Destroy DST lib");
383 is_dst_up = ISC_FALSE;
387 ddebug("Detach from entropy");
388 isc_entropy_detach(&entp);
391 lwres_conf_clear(lwctx);
392 lwres_context_destroy(&lwctx);
394 isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
396 ddebug("Destroying request manager");
397 dns_requestmgr_detach(&requestmgr);
399 ddebug("Freeing the dispatchers");
401 dns_dispatch_detach(&dispatchv4);
403 dns_dispatch_detach(&dispatchv6);
405 ddebug("Shutting down dispatch manager");
406 dns_dispatchmgr_destroy(&dispatchmgr);
411 maybeshutdown(void) {
412 ddebug("Shutting down request manager");
413 dns_requestmgr_shutdown(requestmgr);
422 shutdown_program(isc_task_t *task, isc_event_t *event) {
423 REQUIRE(task == global_task);
426 ddebug("shutdown_program()");
427 isc_event_free(&event);
429 shuttingdown = ISC_TRUE;
436 isc_sockaddr_t bind_any, bind_any6;
437 lwres_result_t lwresult;
438 unsigned int attrs, attrmask;
441 ddebug("setup_system()");
443 dns_result_register();
445 result = isc_net_probeipv4();
446 if (result == ISC_R_SUCCESS)
447 have_ipv4 = ISC_TRUE;
449 result = isc_net_probeipv6();
450 if (result == ISC_R_SUCCESS)
451 have_ipv6 = ISC_TRUE;
453 if (!have_ipv4 && !have_ipv6)
454 fatal("could not find either IPv4 or IPv6");
456 result = isc_mem_create(0, 0, &mctx);
457 check_result(result, "isc_mem_create");
459 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
460 if (lwresult != LWRES_R_SUCCESS)
461 fatal("lwres_context_create failed");
463 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
464 lwconf = lwres_conf_get(lwctx);
466 ns_total = lwconf->nsnext;
468 /* No name servers in resolv.conf; default to loopback. */
469 struct in_addr localhost;
471 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
473 fatal("out of memory");
474 localhost.s_addr = htonl(INADDR_LOOPBACK);
475 isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
477 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
479 fatal("out of memory");
480 for (i = 0; i < ns_total; i++) {
481 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
483 memcpy(&in4, lwconf->nameservers[i].address, 4);
484 isc_sockaddr_fromin(&servers[i], &in4, DNSDEFAULTPORT);
487 memcpy(&in6, lwconf->nameservers[i].address, 16);
488 isc_sockaddr_fromin6(&servers[i], &in6,
494 result = isc_entropy_create(mctx, &entp);
495 check_result(result, "isc_entropy_create");
497 result = isc_hash_create(mctx, entp, DNS_NAME_MAXWIRE);
498 check_result(result, "isc_hash_create");
501 result = dns_dispatchmgr_create(mctx, entp, &dispatchmgr);
502 check_result(result, "dns_dispatchmgr_create");
504 result = isc_socketmgr_create(mctx, &socketmgr);
505 check_result(result, "dns_socketmgr_create");
507 result = isc_timermgr_create(mctx, &timermgr);
508 check_result(result, "dns_timermgr_create");
510 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
511 check_result(result, "isc_taskmgr_create");
513 result = isc_task_create(taskmgr, 0, &global_task);
514 check_result(result, "isc_task_create");
516 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
517 check_result(result, "isc_task_onshutdown");
519 result = dst_lib_init(mctx, entp, 0);
520 check_result(result, "dst_lib_init");
521 is_dst_up = ISC_TRUE;
523 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
524 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
527 attrs = DNS_DISPATCHATTR_UDP;
528 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
529 attrs |= DNS_DISPATCHATTR_IPV6;
530 isc_sockaddr_any6(&bind_any6);
531 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
532 &bind_any6, PACKETSIZE,
534 attrs, attrmask, &dispatchv6);
535 check_result(result, "dns_dispatch_getudp (v6)");
539 attrs = DNS_DISPATCHATTR_UDP;
540 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
541 attrs |= DNS_DISPATCHATTR_IPV4;
542 isc_sockaddr_any(&bind_any);
543 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
544 &bind_any, PACKETSIZE,
546 attrs, attrmask, &dispatchv4);
547 check_result(result, "dns_dispatch_getudp (v4)");
550 result = dns_requestmgr_create(mctx, timermgr,
551 socketmgr, taskmgr, dispatchmgr,
552 dispatchv4, dispatchv6, &requestmgr);
553 check_result(result, "dns_requestmgr_create");
557 else if (keyfile != NULL)
562 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
565 #ifdef USE_GETADDRINFO
566 struct addrinfo *res = NULL, hints;
572 ddebug("get_address()");
575 * Assume we have v4 if we don't have v6, since setup_libs
576 * fatal()'s out if we don't have either.
578 if (have_ipv6 && inet_pton(AF_INET6, host, &in6) == 1)
579 isc_sockaddr_fromin6(sockaddr, &in6, port);
580 else if (inet_pton(AF_INET, host, &in4) == 1)
581 isc_sockaddr_fromin(sockaddr, &in4, port);
583 #ifdef USE_GETADDRINFO
584 memset(&hints, 0, sizeof(hints));
586 hints.ai_family = PF_INET;
588 hints.ai_family = PF_INET6;
590 hints.ai_family = PF_UNSPEC;
592 hints.ai_flags = AI_ADDRCONFIG;
595 debug ("before getaddrinfo()");
600 result = getaddrinfo(host, NULL, &hints, &res);
602 if (result == EAI_BADFLAGS &&
603 (hints.ai_flags & AI_ADDRCONFIG) != 0) {
604 hints.ai_flags &= ~AI_ADDRCONFIG;
610 fatal("couldn't find server '%s': %s",
611 host, gai_strerror(result));
613 memcpy(&sockaddr->type.sa,res->ai_addr, res->ai_addrlen);
614 sockaddr->length = res->ai_addrlen;
615 isc_sockaddr_setport(sockaddr, port);
618 debug ("before gethostbyname()");
620 he = gethostbyname(host);
623 fatal("couldn't find server '%s' (h_errno=%d)",
625 INSIST(he->h_addrtype == AF_INET);
626 isc_sockaddr_fromin(sockaddr,
627 (struct in_addr *)(he->h_addr_list[0]),
634 parse_args(int argc, char **argv) {
639 while ((ch = isc_commandline_parse(argc, argv, "dDMy:vk:")) != -1) {
642 debugging = ISC_TRUE;
644 case 'D': /* was -dd */
645 debugging = ISC_TRUE;
646 ddebugging = ISC_TRUE;
648 case 'M': /* was -dm */
649 debugging = ISC_TRUE;
650 ddebugging = ISC_TRUE;
651 memdebugging = ISC_TRUE;
652 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
656 keystr = isc_commandline_argument;
662 keyfile = isc_commandline_argument;
665 fprintf(stderr, "%s: invalid argument -%c\n",
667 fprintf(stderr, "usage: nsupdate [-d] "
668 "[-y keyname:secret | -k keyfile] [-v] "
673 if (keyfile != NULL && keystr != NULL) {
674 fprintf(stderr, "%s: cannot specify both -k and -y\n",
679 if (argv[isc_commandline_index] != NULL) {
680 if (strcmp(argv[isc_commandline_index], "-") == 0) {
683 result = isc_stdio_open(argv[isc_commandline_index],
685 if (result != ISC_R_SUCCESS) {
686 fprintf(stderr, "could not open '%s': %s\n",
687 argv[isc_commandline_index],
688 isc_result_totext(result));
692 interactive = ISC_FALSE;
697 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
700 isc_buffer_t *namebuf = NULL;
703 word = nsu_strsep(cmdlinep, " \t\r\n");
705 fprintf(stderr, "could not read owner name\n");
706 return (STATUS_SYNTAX);
709 result = dns_message_gettempname(msg, namep);
710 check_result(result, "dns_message_gettempname");
711 result = isc_buffer_allocate(mctx, &namebuf, NAMEBUF);
712 check_result(result, "isc_buffer_allocate");
713 dns_name_init(*namep, NULL);
714 dns_name_setbuffer(*namep, namebuf);
715 dns_message_takebuffer(msg, &namebuf);
716 isc_buffer_init(&source, word, strlen(word));
717 isc_buffer_add(&source, strlen(word));
718 result = dns_name_fromtext(*namep, &source, dns_rootname,
720 check_result(result, "dns_name_fromtext");
721 isc_buffer_invalidate(&source);
722 return (STATUS_MORE);
726 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
727 dns_rdatatype_t rdatatype, dns_message_t *msg,
730 char *cmdline = *cmdlinep;
731 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
733 isc_lex_t *lex = NULL;
734 dns_rdatacallbacks_t callbacks;
737 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
741 dns_rdatacallbacks_init(&callbacks);
742 result = isc_lex_create(mctx, strlen(cmdline), &lex);
743 check_result(result, "isc_lex_create");
744 isc_buffer_init(&source, cmdline, strlen(cmdline));
745 isc_buffer_add(&source, strlen(cmdline));
746 result = isc_lex_openbuffer(lex, &source);
747 check_result(result, "isc_lex_openbuffer");
748 result = isc_buffer_allocate(mctx, &buf, MAXWIRE);
749 check_result(result, "isc_buffer_allocate");
750 result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, lex,
751 dns_rootname, ISC_FALSE, mctx, buf,
753 isc_lex_destroy(&lex);
754 if (result == ISC_R_SUCCESS) {
755 isc_buffer_usedregion(buf, &r);
756 result = isc_buffer_allocate(mctx, &newbuf, r.length);
757 check_result(result, "isc_buffer_allocate");
758 isc_buffer_putmem(newbuf, r.base, r.length);
759 isc_buffer_usedregion(newbuf, &r);
760 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
761 isc_buffer_free(&buf);
762 dns_message_takebuffer(msg, &newbuf);
764 fprintf(stderr, "invalid rdata format: %s\n",
765 isc_result_totext(result));
766 isc_buffer_free(&buf);
767 return (STATUS_SYNTAX);
770 rdata->flags = DNS_RDATA_UPDATE;
773 return (STATUS_MORE);
777 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
780 dns_name_t *name = NULL;
781 isc_textregion_t region;
782 dns_rdataset_t *rdataset = NULL;
783 dns_rdatalist_t *rdatalist = NULL;
784 dns_rdataclass_t rdataclass;
785 dns_rdatatype_t rdatatype;
786 dns_rdata_t *rdata = NULL;
789 ddebug("make_prereq()");
792 * Read the owner name
794 retval = parse_name(&cmdline, updatemsg, &name);
795 if (retval != STATUS_MORE)
799 * If this is an rrset prereq, read the class or type.
802 word = nsu_strsep(&cmdline, " \t\r\n");
804 fprintf(stderr, "could not read class or type\n");
808 region.length = strlen(word);
809 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
810 if (result == ISC_R_SUCCESS) {
811 if (!setzoneclass(rdataclass)) {
812 fprintf(stderr, "class mismatch: %s\n", word);
818 word = nsu_strsep(&cmdline, " \t\r\n");
820 fprintf(stderr, "could not read type\n");
824 region.length = strlen(word);
825 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
826 if (result != ISC_R_SUCCESS) {
827 fprintf(stderr, "invalid type: %s\n", word);
831 rdataclass = getzoneclass();
832 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
833 if (result != ISC_R_SUCCESS) {
834 fprintf(stderr, "invalid type: %s\n", word);
839 rdatatype = dns_rdatatype_any;
841 result = dns_message_gettemprdata(updatemsg, &rdata);
842 check_result(result, "dns_message_gettemprdata");
847 if (isrrset && ispositive) {
848 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
850 if (retval != STATUS_MORE)
853 rdata->flags = DNS_RDATA_UPDATE;
855 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
856 check_result(result, "dns_message_gettemprdatalist");
857 result = dns_message_gettemprdataset(updatemsg, &rdataset);
858 check_result(result, "dns_message_gettemprdataset");
859 dns_rdatalist_init(rdatalist);
860 rdatalist->type = rdatatype;
862 if (isrrset && rdata->data != NULL)
863 rdatalist->rdclass = rdataclass;
865 rdatalist->rdclass = dns_rdataclass_any;
867 rdatalist->rdclass = dns_rdataclass_none;
868 rdatalist->covers = 0;
870 rdata->rdclass = rdatalist->rdclass;
871 rdata->type = rdatatype;
872 ISC_LIST_INIT(rdatalist->rdata);
873 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
874 dns_rdataset_init(rdataset);
875 dns_rdatalist_tordataset(rdatalist, rdataset);
876 ISC_LIST_INIT(name->list);
877 ISC_LIST_APPEND(name->list, rdataset, link);
878 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
879 return (STATUS_MORE);
883 dns_message_puttempname(updatemsg, &name);
884 return (STATUS_SYNTAX);
888 evaluate_prereq(char *cmdline) {
890 isc_boolean_t ispositive, isrrset;
892 ddebug("evaluate_prereq()");
893 word = nsu_strsep(&cmdline, " \t\r\n");
895 fprintf(stderr, "could not read operation code\n");
896 return (STATUS_SYNTAX);
898 if (strcasecmp(word, "nxdomain") == 0) {
899 ispositive = ISC_FALSE;
901 } else if (strcasecmp(word, "yxdomain") == 0) {
902 ispositive = ISC_TRUE;
904 } else if (strcasecmp(word, "nxrrset") == 0) {
905 ispositive = ISC_FALSE;
907 } else if (strcasecmp(word, "yxrrset") == 0) {
908 ispositive = ISC_TRUE;
911 fprintf(stderr, "incorrect operation code: %s\n", word);
912 return (STATUS_SYNTAX);
914 return (make_prereq(cmdline, ispositive, isrrset));
918 evaluate_server(char *cmdline) {
922 word = nsu_strsep(&cmdline, " \t\r\n");
924 fprintf(stderr, "could not read server name\n");
925 return (STATUS_SYNTAX);
929 word = nsu_strsep(&cmdline, " \t\r\n");
931 port = DNSDEFAULTPORT;
934 port = strtol(word, &endp, 10);
936 fprintf(stderr, "port '%s' is not numeric\n", word);
937 return (STATUS_SYNTAX);
938 } else if (port < 1 || port > 65535) {
939 fprintf(stderr, "port '%s' is out of range "
940 "(1 to 65535)\n", word);
941 return (STATUS_SYNTAX);
945 if (userserver == NULL) {
946 userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
947 if (userserver == NULL)
948 fatal("out of memory");
951 get_address(server, (in_port_t)port, userserver);
953 return (STATUS_MORE);
957 evaluate_local(char *cmdline) {
963 word = nsu_strsep(&cmdline, " \t\r\n");
965 fprintf(stderr, "could not read server name\n");
966 return (STATUS_SYNTAX);
970 word = nsu_strsep(&cmdline, " \t\r\n");
975 port = strtol(word, &endp, 10);
977 fprintf(stderr, "port '%s' is not numeric\n", word);
978 return (STATUS_SYNTAX);
979 } else if (port < 1 || port > 65535) {
980 fprintf(stderr, "port '%s' is out of range "
981 "(1 to 65535)\n", word);
982 return (STATUS_SYNTAX);
986 if (localaddr == NULL) {
987 localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
988 if (localaddr == NULL)
989 fatal("out of memory");
992 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
993 isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
994 else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
995 isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
997 fprintf(stderr, "invalid address %s", local);
998 return (STATUS_SYNTAX);
1001 return (STATUS_MORE);
1005 evaluate_key(char *cmdline) {
1009 isc_result_t result;
1010 dns_fixedname_t fkeyname;
1011 dns_name_t *keyname;
1013 unsigned char *secret = NULL;
1014 isc_buffer_t secretbuf;
1016 namestr = nsu_strsep(&cmdline, " \t\r\n");
1017 if (*namestr == 0) {
1018 fprintf(stderr, "could not read key name\n");
1019 return (STATUS_SYNTAX);
1022 dns_fixedname_init(&fkeyname);
1023 keyname = dns_fixedname_name(&fkeyname);
1025 isc_buffer_init(&b, namestr, strlen(namestr));
1026 isc_buffer_add(&b, strlen(namestr));
1027 result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
1028 if (result != ISC_R_SUCCESS) {
1029 fprintf(stderr, "could not parse key name\n");
1030 return (STATUS_SYNTAX);
1033 secretstr = nsu_strsep(&cmdline, "\r\n");
1034 if (*secretstr == 0) {
1035 fprintf(stderr, "could not read key secret\n");
1036 return (STATUS_SYNTAX);
1038 secretlen = strlen(secretstr) * 3 / 4;
1039 secret = isc_mem_allocate(mctx, secretlen);
1041 fatal("out of memory");
1043 isc_buffer_init(&secretbuf, secret, secretlen);
1044 result = isc_base64_decodestring(secretstr, &secretbuf);
1045 if (result != ISC_R_SUCCESS) {
1046 fprintf(stderr, "could not create key from %s: %s\n",
1047 secretstr, isc_result_totext(result));
1048 isc_mem_free(mctx, secret);
1049 return (STATUS_SYNTAX);
1051 secretlen = isc_buffer_usedlength(&secretbuf);
1054 dns_tsigkey_detach(&key);
1055 result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name,
1056 secret, secretlen, ISC_TRUE, NULL, 0, 0,
1058 isc_mem_free(mctx, secret);
1059 if (result != ISC_R_SUCCESS) {
1060 fprintf(stderr, "could not create key from %s %s: %s\n",
1061 namestr, secretstr, dns_result_totext(result));
1062 return (STATUS_SYNTAX);
1064 return (STATUS_MORE);
1068 evaluate_zone(char *cmdline) {
1071 isc_result_t result;
1073 word = nsu_strsep(&cmdline, " \t\r\n");
1075 fprintf(stderr, "could not read zone name\n");
1076 return (STATUS_SYNTAX);
1079 dns_fixedname_init(&fuserzone);
1080 userzone = dns_fixedname_name(&fuserzone);
1081 isc_buffer_init(&b, word, strlen(word));
1082 isc_buffer_add(&b, strlen(word));
1083 result = dns_name_fromtext(userzone, &b, dns_rootname, ISC_FALSE,
1085 if (result != ISC_R_SUCCESS) {
1086 userzone = NULL; /* Lest it point to an invalid name */
1087 fprintf(stderr, "could not parse zone name\n");
1088 return (STATUS_SYNTAX);
1091 return (STATUS_MORE);
1095 evaluate_class(char *cmdline) {
1098 isc_result_t result;
1099 dns_rdataclass_t rdclass;
1101 word = nsu_strsep(&cmdline, " \t\r\n");
1103 fprintf(stderr, "could not read class name\n");
1104 return (STATUS_SYNTAX);
1108 r.length = strlen(word);
1109 result = dns_rdataclass_fromtext(&rdclass, &r);
1110 if (result != ISC_R_SUCCESS) {
1111 fprintf(stderr, "could not parse class name: %s\n", word);
1112 return (STATUS_SYNTAX);
1115 case dns_rdataclass_none:
1116 case dns_rdataclass_any:
1117 case dns_rdataclass_reserved0:
1118 fprintf(stderr, "bad default class: %s\n", word);
1119 return (STATUS_SYNTAX);
1121 defaultclass = rdclass;
1124 return (STATUS_MORE);
1128 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1129 isc_result_t result;
1130 dns_name_t *name = NULL;
1133 dns_rdataclass_t rdataclass;
1134 dns_rdatatype_t rdatatype;
1135 dns_rdata_t *rdata = NULL;
1136 dns_rdatalist_t *rdatalist = NULL;
1137 dns_rdataset_t *rdataset = NULL;
1138 isc_textregion_t region;
1140 isc_uint16_t retval;
1142 ddebug("update_addordelete()");
1145 * Read the owner name.
1147 retval = parse_name(&cmdline, updatemsg, &name);
1148 if (retval != STATUS_MORE)
1151 result = dns_message_gettemprdata(updatemsg, &rdata);
1152 check_result(result, "dns_message_gettemprdata");
1160 * If this is an add, read the TTL and verify that it's in range.
1161 * If it's a delete, ignore a TTL if present (for compatibility).
1163 word = nsu_strsep(&cmdline, " \t\r\n");
1166 fprintf(stderr, "could not read owner ttl\n");
1171 rdataclass = dns_rdataclass_any;
1172 rdatatype = dns_rdatatype_any;
1173 rdata->flags = DNS_RDATA_UPDATE;
1177 ttl = strtoul(word, &endp, 10);
1178 if (!isdigit((unsigned char)*word) || *endp != '\0') {
1183 fprintf(stderr, "ttl '%s' is not legal\n", word);
1190 else if (ttl > TTL_MAX) {
1191 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1197 * Read the class or type.
1199 word = nsu_strsep(&cmdline, " \t\r\n");
1203 rdataclass = dns_rdataclass_any;
1204 rdatatype = dns_rdatatype_any;
1205 rdata->flags = DNS_RDATA_UPDATE;
1208 fprintf(stderr, "could not read class or type\n");
1213 region.length = strlen(word);
1214 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1215 if (result == ISC_R_SUCCESS) {
1216 if (!setzoneclass(rdataclass)) {
1217 fprintf(stderr, "class mismatch: %s\n", word);
1221 * Now read the type.
1223 word = nsu_strsep(&cmdline, " \t\r\n");
1226 rdataclass = dns_rdataclass_any;
1227 rdatatype = dns_rdatatype_any;
1228 rdata->flags = DNS_RDATA_UPDATE;
1231 fprintf(stderr, "could not read type\n");
1236 region.length = strlen(word);
1237 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1238 if (result != ISC_R_SUCCESS) {
1239 fprintf(stderr, "'%s' is not a valid type: %s\n",
1240 word, isc_result_totext(result));
1244 rdataclass = getzoneclass();
1245 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1246 if (result != ISC_R_SUCCESS) {
1247 fprintf(stderr, "'%s' is not a valid class or type: "
1248 "%s\n", word, isc_result_totext(result));
1253 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1255 if (retval != STATUS_MORE)
1259 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1260 rdataclass = dns_rdataclass_any;
1262 rdataclass = dns_rdataclass_none;
1264 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1265 fprintf(stderr, "could not read rdata\n");
1272 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1273 check_result(result, "dns_message_gettemprdatalist");
1274 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1275 check_result(result, "dns_message_gettemprdataset");
1276 dns_rdatalist_init(rdatalist);
1277 rdatalist->type = rdatatype;
1278 rdatalist->rdclass = rdataclass;
1279 rdatalist->covers = rdatatype;
1280 rdatalist->ttl = (dns_ttl_t)ttl;
1281 ISC_LIST_INIT(rdatalist->rdata);
1282 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1283 dns_rdataset_init(rdataset);
1284 dns_rdatalist_tordataset(rdatalist, rdataset);
1285 ISC_LIST_INIT(name->list);
1286 ISC_LIST_APPEND(name->list, rdataset, link);
1287 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1288 return (STATUS_MORE);
1292 dns_message_puttempname(updatemsg, &name);
1294 dns_message_puttemprdata(updatemsg, &rdata);
1295 return (STATUS_SYNTAX);
1299 evaluate_update(char *cmdline) {
1301 isc_boolean_t isdelete;
1303 ddebug("evaluate_update()");
1304 word = nsu_strsep(&cmdline, " \t\r\n");
1306 fprintf(stderr, "could not read operation code\n");
1307 return (STATUS_SYNTAX);
1309 if (strcasecmp(word, "delete") == 0)
1310 isdelete = ISC_TRUE;
1311 else if (strcasecmp(word, "add") == 0)
1312 isdelete = ISC_FALSE;
1314 fprintf(stderr, "incorrect operation code: %s\n", word);
1315 return (STATUS_SYNTAX);
1317 return (update_addordelete(cmdline, isdelete));
1321 show_message(dns_message_t *msg) {
1322 isc_result_t result;
1323 isc_buffer_t *buf = NULL;
1326 ddebug("show_message()");
1329 if (bufsz > MAXTEXT) {
1330 fprintf(stderr, "could not allocate large enough "
1331 "buffer to display message\n");
1335 isc_buffer_free(&buf);
1336 result = isc_buffer_allocate(mctx, &buf, bufsz);
1337 check_result(result, "isc_buffer_allocate");
1338 result = dns_message_totext(msg, style, 0, buf);
1340 } while (result == ISC_R_NOSPACE);
1341 if (result != ISC_R_SUCCESS) {
1342 fprintf(stderr, "could not convert message to text format.\n");
1343 isc_buffer_free(&buf);
1346 printf("Outgoing update query:\n%.*s",
1347 (int)isc_buffer_usedlength(buf),
1348 (char*)isc_buffer_base(buf));
1349 isc_buffer_free(&buf);
1354 get_next_command(void) {
1355 char cmdlinebuf[MAXCMD];
1359 ddebug("get_next_command()");
1361 fprintf(stdout, "> ");
1363 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1365 if (cmdline == NULL)
1366 return (STATUS_QUIT);
1367 word = nsu_strsep(&cmdline, " \t\r\n");
1370 return (STATUS_QUIT);
1372 return (STATUS_SEND);
1374 return (STATUS_MORE);
1375 if (strcasecmp(word, "quit") == 0)
1376 return (STATUS_QUIT);
1377 if (strcasecmp(word, "prereq") == 0)
1378 return (evaluate_prereq(cmdline));
1379 if (strcasecmp(word, "update") == 0)
1380 return (evaluate_update(cmdline));
1381 if (strcasecmp(word, "server") == 0)
1382 return (evaluate_server(cmdline));
1383 if (strcasecmp(word, "local") == 0)
1384 return (evaluate_local(cmdline));
1385 if (strcasecmp(word, "zone") == 0)
1386 return (evaluate_zone(cmdline));
1387 if (strcasecmp(word, "class") == 0)
1388 return (evaluate_class(cmdline));
1389 if (strcasecmp(word, "send") == 0)
1390 return (STATUS_SEND);
1391 if (strcasecmp(word, "show") == 0) {
1392 show_message(updatemsg);
1393 return (STATUS_MORE);
1395 if (strcasecmp(word, "key") == 0)
1396 return (evaluate_key(cmdline));
1397 fprintf(stderr, "incorrect section name: %s\n", word);
1398 return (STATUS_SYNTAX);
1401 static isc_boolean_t
1402 user_interaction(void) {
1403 isc_uint16_t result = STATUS_MORE;
1405 ddebug("user_interaction()");
1406 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX))
1407 result = get_next_command();
1408 if (result == STATUS_SEND)
1416 isc_event_t *event = global_event;
1417 ddebug("done_update()");
1418 isc_task_send(global_task, &event);
1422 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
1423 isc_result_t result;
1424 dns_rdata_t rdata = DNS_RDATA_INIT;
1425 dns_rdata_any_tsig_t tsig;
1427 result = dns_rdataset_first(rdataset);
1428 check_result(result, "dns_rdataset_first");
1429 dns_rdataset_current(rdataset, &rdata);
1430 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
1431 check_result(result, "dns_rdata_tostruct");
1432 if (tsig.error != 0) {
1433 if (isc_buffer_remaininglength(b) < 1)
1434 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1435 isc__buffer_putstr(b, "(" /*)*/);
1436 result = dns_tsigrcode_totext(tsig.error, b);
1437 check_result(result, "dns_tsigrcode_totext");
1438 if (isc_buffer_remaininglength(b) < 1)
1439 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
1440 isc__buffer_putstr(b, /*(*/ ")");
1445 update_completed(isc_task_t *task, isc_event_t *event) {
1446 dns_requestevent_t *reqev = NULL;
1447 isc_result_t result;
1448 dns_message_t *rcvmsg = NULL;
1449 dns_request_t *request;
1453 ddebug("update_completed()");
1457 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1458 reqev = (dns_requestevent_t *)event;
1459 request = reqev->request;
1462 dns_request_destroy(&request);
1463 isc_event_free(&event);
1468 if (reqev->result != ISC_R_SUCCESS) {
1469 fprintf(stderr, "; Communication with server failed: %s\n",
1470 isc_result_totext(reqev->result));
1471 seenerror = ISC_TRUE;
1475 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
1476 check_result(result, "dns_message_create");
1477 result = dns_request_getresponse(request, rcvmsg,
1478 DNS_MESSAGEPARSE_PRESERVEORDER);
1482 case DNS_R_CLOCKSKEW:
1483 case DNS_R_EXPECTEDTSIG:
1484 case DNS_R_TSIGERRORSET:
1485 case DNS_R_TSIGVERIFYFAILURE:
1486 case DNS_R_UNEXPECTEDTSIG:
1487 fprintf(stderr, "; TSIG error with server: %s\n",
1488 isc_result_totext(result));
1489 seenerror = ISC_TRUE;
1492 check_result(result, "dns_request_getresponse");
1495 if (rcvmsg->rcode != dns_rcode_noerror) {
1496 seenerror = ISC_TRUE;
1500 dns_rdataset_t *rds;
1502 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1503 result = dns_rcode_totext(rcvmsg->rcode, &b);
1504 check_result(result, "dns_rcode_totext");
1505 rds = dns_message_gettsig(rcvmsg, NULL);
1507 check_tsig_error(rds, &b);
1508 fprintf(stderr, "update failed: %.*s\n",
1509 (int)isc_buffer_usedlength(&b), buf);
1513 isc_buffer_t *buf = NULL;
1518 if (bufsz > MAXTEXT) {
1519 fprintf(stderr, "could not allocate large "
1520 "enough buffer to display message\n");
1524 isc_buffer_free(&buf);
1525 result = isc_buffer_allocate(mctx, &buf, bufsz);
1526 check_result(result, "isc_buffer_allocate");
1527 result = dns_message_totext(rcvmsg, style, 0, buf);
1529 } while (result == ISC_R_NOSPACE);
1530 check_result(result, "dns_message_totext");
1531 fprintf(stderr, "\nReply from update query:\n%.*s\n",
1532 (int)isc_buffer_usedlength(buf),
1533 (char*)isc_buffer_base(buf));
1534 isc_buffer_free(&buf);
1536 dns_message_destroy(&rcvmsg);
1538 dns_request_destroy(&request);
1539 isc_event_free(&event);
1544 send_update(dns_name_t *zonename, isc_sockaddr_t *master,
1545 isc_sockaddr_t *srcaddr)
1547 isc_result_t result;
1548 dns_request_t *request = NULL;
1549 dns_name_t *name = NULL;
1550 dns_rdataset_t *rdataset = NULL;
1551 unsigned int options = 0;
1553 ddebug("send_update()");
1555 result = dns_message_gettempname(updatemsg, &name);
1556 check_result(result, "dns_message_gettempname");
1557 dns_name_init(name, NULL);
1558 dns_name_clone(zonename, name);
1559 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1560 check_result(result, "dns_message_gettemprdataset");
1561 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
1562 ISC_LIST_INIT(name->list);
1563 ISC_LIST_APPEND(name->list, rdataset, link);
1564 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1567 options |= DNS_REQUESTOPT_TCP;
1568 result = dns_request_createvia(requestmgr, updatemsg, srcaddr,
1569 master, options, key,
1570 FIND_TIMEOUT, global_task,
1571 update_completed, NULL, &request);
1572 check_result(result, "dns_request_createvia");
1577 recvsoa(isc_task_t *task, isc_event_t *event) {
1578 dns_requestevent_t *reqev = NULL;
1579 dns_request_t *request = NULL;
1580 isc_result_t result, eresult;
1581 dns_message_t *rcvmsg = NULL;
1582 dns_section_t section;
1583 dns_name_t *name = NULL;
1584 dns_rdataset_t *soaset = NULL;
1585 dns_rdata_soa_t soa;
1586 dns_rdata_t soarr = DNS_RDATA_INIT;
1589 isc_sockaddr_t *serveraddr, tempaddr;
1590 dns_name_t *zonename;
1591 nsu_requestinfo_t *reqinfo;
1592 dns_message_t *soaquery = NULL;
1593 isc_sockaddr_t *addr;
1594 isc_boolean_t seencname = ISC_FALSE;
1598 ddebug("recvsoa()");
1602 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1603 reqev = (dns_requestevent_t *)event;
1604 request = reqev->request;
1605 eresult = reqev->result;
1606 reqinfo = reqev->ev_arg;
1607 soaquery = reqinfo->msg;
1608 addr = reqinfo->addr;
1611 dns_request_destroy(&request);
1612 dns_message_destroy(&soaquery);
1613 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
1614 isc_event_free(&event);
1619 if (eresult != ISC_R_SUCCESS) {
1620 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
1622 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
1623 fprintf(stderr, "; Communication with %s failed: %s\n",
1624 addrbuf, isc_result_totext(eresult));
1625 if (userserver != NULL)
1626 fatal("could not talk to specified name server");
1627 else if (++ns_inuse >= lwconf->nsnext)
1628 fatal("could not talk to any default name server");
1629 ddebug("Destroying request [%p]", request);
1630 dns_request_destroy(&request);
1631 dns_message_renderreset(soaquery);
1632 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
1633 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
1634 isc_event_free(&event);
1635 setzoneclass(dns_rdataclass_none);
1638 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
1640 isc_event_free(&event);
1643 ddebug("About to create rcvmsg");
1644 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
1645 check_result(result, "dns_message_create");
1646 result = dns_request_getresponse(request, rcvmsg,
1647 DNS_MESSAGEPARSE_PRESERVEORDER);
1648 if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
1649 dns_message_destroy(&rcvmsg);
1650 ddebug("Destroying request [%p]", request);
1651 dns_request_destroy(&request);
1652 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
1653 if (reqinfo == NULL)
1654 fatal("out of memory");
1655 reqinfo->msg = soaquery;
1656 reqinfo->addr = addr;
1657 dns_message_renderreset(soaquery);
1658 ddebug("retrying soa request without TSIG");
1659 result = dns_request_createvia(requestmgr, soaquery,
1660 localaddr, addr, 0, NULL,
1661 FIND_TIMEOUT, global_task,
1662 recvsoa, reqinfo, &request);
1663 check_result(result, "dns_request_createvia");
1667 check_result(result, "dns_request_getresponse");
1668 section = DNS_SECTION_ANSWER;
1670 isc_buffer_t *buf = NULL;
1675 isc_buffer_free(&buf);
1676 if (bufsz > MAXTEXT) {
1677 fprintf(stderr, "could not allocate enough "
1678 "space for debugging message\n");
1681 result = isc_buffer_allocate(mctx, &buf, bufsz);
1682 check_result(result, "isc_buffer_allocate");
1683 result = dns_message_totext(rcvmsg, style, 0, buf);
1684 } while (result == ISC_R_NOSPACE);
1685 check_result(result, "dns_message_totext");
1686 fprintf(stderr, "Reply from SOA query:\n%.*s\n",
1687 (int)isc_buffer_usedlength(buf),
1688 (char*)isc_buffer_base(buf));
1689 isc_buffer_free(&buf);
1692 if (rcvmsg->rcode != dns_rcode_noerror &&
1693 rcvmsg->rcode != dns_rcode_nxdomain)
1694 fatal("response to SOA query was unsuccessful");
1698 section = DNS_SECTION_ANSWER;
1700 section = DNS_SECTION_AUTHORITY;
1702 fatal("response to SOA query didn't contain an SOA");
1705 result = dns_message_firstname(rcvmsg, section);
1706 if (result != ISC_R_SUCCESS) {
1710 while (result == ISC_R_SUCCESS) {
1712 dns_message_currentname(rcvmsg, section, &name);
1714 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
1716 if (result == ISC_R_SUCCESS)
1718 if (section == DNS_SECTION_ANSWER) {
1719 dns_rdataset_t *tset = NULL;
1720 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
1721 &tset) == ISC_R_SUCCESS
1723 dns_message_findtype(name, dns_rdatatype_dname, 0,
1724 &tset) == ISC_R_SUCCESS
1727 seencname = ISC_TRUE;
1732 result = dns_message_nextname(rcvmsg, section);
1735 if (soaset == NULL && !seencname) {
1742 unsigned int nlabels;
1744 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
1745 INSIST(result == ISC_R_SUCCESS);
1747 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
1748 nlabels = dns_name_countlabels(name);
1750 fatal("could not find enclosing zone");
1751 dns_name_init(&tname, NULL);
1752 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
1753 dns_name_clone(&tname, name);
1754 dns_request_destroy(&request);
1755 dns_message_renderreset(soaquery);
1756 if (userserver != NULL)
1757 sendrequest(localaddr, userserver, soaquery, &request);
1759 sendrequest(localaddr, &servers[ns_inuse], soaquery,
1765 char namestr[DNS_NAME_FORMATSIZE];
1766 dns_name_format(name, namestr, sizeof(namestr));
1767 fprintf(stderr, "Found zone name: %s\n", namestr);
1770 result = dns_rdataset_first(soaset);
1771 check_result(result, "dns_rdataset_first");
1773 dns_rdata_init(&soarr);
1774 dns_rdataset_current(soaset, &soarr);
1775 result = dns_rdata_tostruct(&soarr, &soa, NULL);
1776 check_result(result, "dns_rdata_tostruct");
1778 dns_name_init(&master, NULL);
1779 dns_name_clone(&soa.origin, &master);
1781 if (userzone != NULL)
1782 zonename = userzone;
1787 char namestr[DNS_NAME_FORMATSIZE];
1788 dns_name_format(&master, namestr, sizeof(namestr));
1789 fprintf(stderr, "The master is: %s\n", namestr);
1792 if (userserver != NULL)
1793 serveraddr = userserver;
1795 char serverstr[DNS_NAME_MAXTEXT+1];
1798 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
1799 result = dns_name_totext(&master, ISC_TRUE, &buf);
1800 check_result(result, "dns_name_totext");
1801 serverstr[isc_buffer_usedlength(&buf)] = 0;
1802 get_address(serverstr, DNSDEFAULTPORT, &tempaddr);
1803 serveraddr = &tempaddr;
1806 send_update(zonename, serveraddr, localaddr);
1808 dns_message_destroy(&soaquery);
1809 dns_request_destroy(&request);
1812 setzoneclass(dns_rdataclass_none);
1813 dns_rdata_freestruct(&soa);
1814 dns_message_destroy(&rcvmsg);
1815 ddebug("Out of recvsoa");
1819 sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
1820 dns_message_t *msg, dns_request_t **request)
1822 isc_result_t result;
1823 nsu_requestinfo_t *reqinfo;
1825 reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
1826 if (reqinfo == NULL)
1827 fatal("out of memory");
1829 reqinfo->addr = destaddr;
1830 result = dns_request_createvia(requestmgr, msg, srcaddr, destaddr, 0,
1831 (userserver != NULL) ? key : NULL,
1832 FIND_TIMEOUT, global_task,
1833 recvsoa, reqinfo, request);
1834 check_result(result, "dns_request_createvia");
1839 start_update(void) {
1840 isc_result_t result;
1841 dns_rdataset_t *rdataset = NULL;
1842 dns_name_t *name = NULL;
1843 dns_request_t *request = NULL;
1844 dns_message_t *soaquery = NULL;
1845 dns_name_t *firstname;
1846 dns_section_t section = DNS_SECTION_UPDATE;
1848 ddebug("start_update()");
1850 result = dns_message_firstname(updatemsg, section);
1851 if (result == ISC_R_NOMORE) {
1852 section = DNS_SECTION_PREREQUISITE;
1853 result = dns_message_firstname(updatemsg, section);
1855 if (result != ISC_R_SUCCESS) {
1860 if (userzone != NULL && userserver != NULL) {
1861 send_update(userzone, userserver, localaddr);
1862 setzoneclass(dns_rdataclass_none);
1866 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
1868 check_result(result, "dns_message_create");
1870 soaquery->flags |= DNS_MESSAGEFLAG_RD;
1872 result = dns_message_gettempname(soaquery, &name);
1873 check_result(result, "dns_message_gettempname");
1875 result = dns_message_gettemprdataset(soaquery, &rdataset);
1876 check_result(result, "dns_message_gettemprdataset");
1878 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
1881 dns_message_currentname(updatemsg, section, &firstname);
1882 dns_name_init(name, NULL);
1883 dns_name_clone(firstname, name);
1885 ISC_LIST_INIT(name->list);
1886 ISC_LIST_APPEND(name->list, rdataset, link);
1887 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
1889 if (userserver != NULL)
1890 sendrequest(localaddr, userserver, soaquery, &request);
1893 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
1899 ddebug("cleanup()");
1901 ddebug("Shutting down task manager");
1902 isc_taskmgr_destroy(&taskmgr);
1904 ddebug("Destroying event");
1905 isc_event_free(&global_event);
1907 ddebug("Shutting down socket manager");
1908 isc_socketmgr_destroy(&socketmgr);
1910 ddebug("Shutting down timer manager");
1911 isc_timermgr_destroy(&timermgr);
1913 ddebug("Destroying hash context");
1916 ddebug("Destroying memory context");
1918 isc_mem_stats(mctx, stderr);
1919 isc_mem_destroy(&mctx);
1923 getinput(isc_task_t *task, isc_event_t *event) {
1933 if (global_event == NULL)
1934 global_event = event;
1937 more = user_interaction();
1947 main(int argc, char **argv) {
1948 isc_result_t result;
1949 style = &dns_master_style_debug;
1953 interactive = ISC_TF(isatty(0));
1957 parse_args(argc, argv);
1961 result = isc_app_onrun(mctx, global_task, getinput, NULL);
1962 check_result(result, "isc_app_onrun");
1964 (void)isc_app_run();