2 * Copyright (C) 2004-2007 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.130.18.19 2007/08/28 07:20:01 tbox Exp $ */
31 #include <isc/base64.h>
32 #include <isc/buffer.h>
33 #include <isc/commandline.h>
34 #include <isc/entropy.h>
35 #include <isc/event.h>
39 #include <isc/parseint.h>
40 #include <isc/region.h>
41 #include <isc/sockaddr.h>
42 #include <isc/socket.h>
43 #include <isc/stdio.h>
44 #include <isc/string.h>
46 #include <isc/timer.h>
47 #include <isc/types.h>
50 #include <dns/callbacks.h>
51 #include <dns/dispatch.h>
52 #include <dns/dnssec.h>
53 #include <dns/events.h>
54 #include <dns/fixedname.h>
55 #include <dns/masterdump.h>
56 #include <dns/message.h>
58 #include <dns/rcode.h>
59 #include <dns/rdata.h>
60 #include <dns/rdataclass.h>
61 #include <dns/rdatalist.h>
62 #include <dns/rdataset.h>
63 #include <dns/rdatastruct.h>
64 #include <dns/rdatatype.h>
65 #include <dns/request.h>
66 #include <dns/result.h>
71 #include <lwres/lwres.h>
72 #include <lwres/net.h>
74 #include <bind9/getaddresses.h>
77 #ifdef HAVE_GETADDRINFO
78 #ifdef HAVE_GAISTRERROR
79 #define USE_GETADDRINFO
84 #ifndef USE_GETADDRINFO
85 #ifndef ISC_PLATFORM_NONSTDHERRNO
90 #define MAXCMD (4 * 1024)
91 #define MAXWIRE (64 * 1024)
92 #define PACKETSIZE ((64 * 1024) - 1)
93 #define INITTEXT (2 * 1024)
94 #define MAXTEXT (128 * 1024)
95 #define FIND_TIMEOUT 5
96 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
98 #define DNSDEFAULTPORT 53
101 #define RESOLV_CONF "/etc/resolv.conf"
104 static isc_boolean_t debugging
= ISC_FALSE
, ddebugging
= ISC_FALSE
;
105 static isc_boolean_t memdebugging
= ISC_FALSE
;
106 static isc_boolean_t have_ipv4
= ISC_FALSE
;
107 static isc_boolean_t have_ipv6
= ISC_FALSE
;
108 static isc_boolean_t is_dst_up
= ISC_FALSE
;
109 static isc_boolean_t usevc
= ISC_FALSE
;
110 static isc_taskmgr_t
*taskmgr
= NULL
;
111 static isc_task_t
*global_task
= NULL
;
112 static isc_event_t
*global_event
= NULL
;
113 static isc_mem_t
*mctx
= NULL
;
114 static dns_dispatchmgr_t
*dispatchmgr
= NULL
;
115 static dns_requestmgr_t
*requestmgr
= NULL
;
116 static isc_socketmgr_t
*socketmgr
= NULL
;
117 static isc_timermgr_t
*timermgr
= NULL
;
118 static dns_dispatch_t
*dispatchv4
= NULL
;
119 static dns_dispatch_t
*dispatchv6
= NULL
;
120 static dns_message_t
*updatemsg
= NULL
;
121 static dns_fixedname_t fuserzone
;
122 static dns_name_t
*userzone
= NULL
;
123 static dns_tsigkey_t
*tsigkey
= NULL
;
124 static dst_key_t
*sig0key
;
125 static lwres_context_t
*lwctx
= NULL
;
126 static lwres_conf_t
*lwconf
;
127 static isc_sockaddr_t
*servers
;
128 static int ns_inuse
= 0;
129 static int ns_total
= 0;
130 static isc_sockaddr_t
*userserver
= NULL
;
131 static isc_sockaddr_t
*localaddr
= NULL
;
132 static char *keystr
= NULL
, *keyfile
= NULL
;
133 static isc_entropy_t
*entp
= NULL
;
134 static isc_boolean_t shuttingdown
= ISC_FALSE
;
136 static isc_boolean_t interactive
= ISC_TRUE
;
137 static isc_boolean_t seenerror
= ISC_FALSE
;
138 static const dns_master_style_t
*style
;
139 static int requests
= 0;
140 static unsigned int timeout
= 300;
141 static unsigned int udp_timeout
= 3;
142 static unsigned int udp_retries
= 3;
143 static dns_rdataclass_t defaultclass
= dns_rdataclass_in
;
144 static dns_rdataclass_t zoneclass
= dns_rdataclass_none
;
145 static dns_message_t
*answer
= NULL
;
147 typedef struct nsu_requestinfo
{
149 isc_sockaddr_t
*addr
;
153 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
154 dns_message_t
*msg
, dns_request_t
**request
);
156 fatal(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
159 debug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
162 ddebug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
165 error(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
167 #define STATUS_MORE (isc_uint16_t)0
168 #define STATUS_SEND (isc_uint16_t)1
169 #define STATUS_QUIT (isc_uint16_t)2
170 #define STATUS_SYNTAX (isc_uint16_t)3
172 static dns_rdataclass_t
174 if (zoneclass
== dns_rdataclass_none
)
175 zoneclass
= defaultclass
;
180 setzoneclass(dns_rdataclass_t rdclass
) {
181 if (zoneclass
== dns_rdataclass_none
||
182 rdclass
== dns_rdataclass_none
)
184 if (zoneclass
!= rdclass
)
190 fatal(const char *format
, ...) {
193 va_start(args
, format
);
194 vfprintf(stderr
, format
, args
);
196 fprintf(stderr
, "\n");
201 error(const char *format
, ...) {
204 va_start(args
, format
);
205 vfprintf(stderr
, format
, args
);
207 fprintf(stderr
, "\n");
211 debug(const char *format
, ...) {
215 va_start(args
, format
);
216 vfprintf(stderr
, format
, args
);
218 fprintf(stderr
, "\n");
223 ddebug(const char *format
, ...) {
227 va_start(args
, format
);
228 vfprintf(stderr
, format
, args
);
230 fprintf(stderr
, "\n");
235 check_result(isc_result_t result
, const char *msg
) {
236 if (result
!= ISC_R_SUCCESS
)
237 fatal("%s: %s", msg
, isc_result_totext(result
));
241 mem_alloc(void *arg
, size_t size
) {
242 return (isc_mem_get(arg
, size
));
246 mem_free(void *arg
, void *mem
, size_t size
) {
247 isc_mem_put(arg
, mem
, size
);
251 nsu_strsep(char **stringp
, const char *delim
) {
252 char *string
= *stringp
;
260 for (; *string
!= '\0'; string
++) {
262 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
270 for (s
= string
; *s
!= '\0'; s
++) {
272 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
288 ddebug("reset_system()");
289 /* If the update message is still around, destroy it */
290 if (updatemsg
!= NULL
)
291 dns_message_reset(updatemsg
, DNS_MESSAGE_INTENTRENDER
);
293 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
295 check_result(result
, "dns_message_create");
297 updatemsg
->opcode
= dns_opcode_update
;
301 parse_hmac(dns_name_t
**hmac
, const char *hmacstr
, size_t len
) {
302 isc_uint16_t digestbits
= 0;
306 REQUIRE(hmac
!= NULL
&& *hmac
== NULL
);
307 REQUIRE(hmacstr
!= NULL
);
309 if (len
>= sizeof(buf
))
310 fatal("unknown key type '%.*s'", (int)(len
), hmacstr
);
312 strncpy(buf
, hmacstr
, len
);
315 if (strcasecmp(buf
, "hmac-md5") == 0) {
316 *hmac
= DNS_TSIG_HMACMD5_NAME
;
317 } else if (strncasecmp(buf
, "hmac-md5-", 9) == 0) {
318 *hmac
= DNS_TSIG_HMACMD5_NAME
;
319 result
= isc_parse_uint16(&digestbits
, &buf
[9], 10);
320 if (result
!= ISC_R_SUCCESS
|| digestbits
> 128)
321 fatal("digest-bits out of range [0..128]");
322 digestbits
= (digestbits
+7) & ~0x7U
;
323 } else if (strcasecmp(buf
, "hmac-sha1") == 0) {
324 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
325 } else if (strncasecmp(buf
, "hmac-sha1-", 10) == 0) {
326 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
327 result
= isc_parse_uint16(&digestbits
, &buf
[10], 10);
328 if (result
!= ISC_R_SUCCESS
|| digestbits
> 160)
329 fatal("digest-bits out of range [0..160]");
330 digestbits
= (digestbits
+7) & ~0x7U
;
331 } else if (strcasecmp(buf
, "hmac-sha224") == 0) {
332 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
333 } else if (strncasecmp(buf
, "hmac-sha224-", 12) == 0) {
334 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
335 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
336 if (result
!= ISC_R_SUCCESS
|| digestbits
> 224)
337 fatal("digest-bits out of range [0..224]");
338 digestbits
= (digestbits
+7) & ~0x7U
;
339 } else if (strcasecmp(buf
, "hmac-sha256") == 0) {
340 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
341 } else if (strncasecmp(buf
, "hmac-sha256-", 12) == 0) {
342 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
343 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
344 if (result
!= ISC_R_SUCCESS
|| digestbits
> 256)
345 fatal("digest-bits out of range [0..256]");
346 digestbits
= (digestbits
+7) & ~0x7U
;
347 } else if (strcasecmp(buf
, "hmac-sha384") == 0) {
348 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
349 } else if (strncasecmp(buf
, "hmac-sha384-", 12) == 0) {
350 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
351 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
352 if (result
!= ISC_R_SUCCESS
|| digestbits
> 384)
353 fatal("digest-bits out of range [0..384]");
354 digestbits
= (digestbits
+7) & ~0x7U
;
355 } else if (strcasecmp(buf
, "hmac-sha512") == 0) {
356 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
357 } else if (strncasecmp(buf
, "hmac-sha512-", 12) == 0) {
358 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
359 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
360 if (result
!= ISC_R_SUCCESS
|| digestbits
> 512)
361 fatal("digest-bits out of range [0..512]");
362 digestbits
= (digestbits
+7) & ~0x7U
;
364 fatal("unknown key type '%s'", buf
);
370 unsigned char *secret
= NULL
;
372 isc_buffer_t secretbuf
;
374 isc_buffer_t keynamesrc
;
377 dns_fixedname_t fkeyname
;
380 dns_name_t
*hmacname
= NULL
;
381 isc_uint16_t digestbits
= 0;
383 dns_fixedname_init(&fkeyname
);
384 keyname
= dns_fixedname_name(&fkeyname
);
386 debug("Creating key...");
388 s
= strchr(keystr
, ':');
389 if (s
== NULL
|| s
== keystr
|| s
[1] == 0)
390 fatal("key option must specify [hmac:]keyname:secret");
392 n
= strchr(secretstr
, ':');
394 if (n
== secretstr
|| n
[1] == 0)
395 fatal("key option must specify [hmac:]keyname:secret");
398 digestbits
= parse_hmac(&hmacname
, keystr
, s
- keystr
);
400 hmacname
= DNS_TSIG_HMACMD5_NAME
;
405 isc_buffer_init(&keynamesrc
, name
, n
- name
);
406 isc_buffer_add(&keynamesrc
, n
- name
);
408 debug("namefromtext");
409 result
= dns_name_fromtext(keyname
, &keynamesrc
, dns_rootname
,
411 check_result(result
, "dns_name_fromtext");
413 secretlen
= strlen(secretstr
) * 3 / 4;
414 secret
= isc_mem_allocate(mctx
, secretlen
);
416 fatal("out of memory");
418 isc_buffer_init(&secretbuf
, secret
, secretlen
);
419 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
420 if (result
!= ISC_R_SUCCESS
) {
421 fprintf(stderr
, "could not create key from %s: %s\n",
422 keystr
, isc_result_totext(result
));
426 secretlen
= isc_buffer_usedlength(&secretbuf
);
429 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
430 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
, &tsigkey
);
431 if (result
!= ISC_R_SUCCESS
)
432 fprintf(stderr
, "could not create key from %s: %s\n",
433 keystr
, dns_result_totext(result
));
435 dst_key_setbits(tsigkey
->key
, digestbits
);
438 isc_mem_free(mctx
, secret
);
442 setup_keyfile(void) {
443 dst_key_t
*dstkey
= NULL
;
445 dns_name_t
*hmacname
= NULL
;
447 debug("Creating key...");
449 result
= dst_key_fromnamedfile(keyfile
,
450 DST_TYPE_PRIVATE
| DST_TYPE_KEY
, mctx
,
452 if (result
!= ISC_R_SUCCESS
) {
453 fprintf(stderr
, "could not read key from %s: %s\n",
454 keyfile
, isc_result_totext(result
));
457 switch (dst_key_alg(dstkey
)) {
458 case DST_ALG_HMACMD5
:
459 hmacname
= DNS_TSIG_HMACMD5_NAME
;
461 case DST_ALG_HMACSHA1
:
462 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
464 case DST_ALG_HMACSHA224
:
465 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
467 case DST_ALG_HMACSHA256
:
468 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
470 case DST_ALG_HMACSHA384
:
471 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
473 case DST_ALG_HMACSHA512
:
474 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
477 if (hmacname
!= NULL
) {
478 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
),
479 hmacname
, dstkey
, ISC_FALSE
,
480 NULL
, 0, 0, mctx
, NULL
,
482 if (result
!= ISC_R_SUCCESS
) {
483 fprintf(stderr
, "could not create key from %s: %s\n",
484 keyfile
, isc_result_totext(result
));
485 dst_key_free(&dstkey
);
494 isc_task_detach(&global_task
);
496 if (userserver
!= NULL
)
497 isc_mem_put(mctx
, userserver
, sizeof(isc_sockaddr_t
));
499 if (localaddr
!= NULL
)
500 isc_mem_put(mctx
, localaddr
, sizeof(isc_sockaddr_t
));
502 if (tsigkey
!= NULL
) {
503 ddebug("Freeing TSIG key");
504 dns_tsigkey_detach(&tsigkey
);
507 if (sig0key
!= NULL
) {
508 ddebug("Freeing SIG(0) key");
509 dst_key_free(&sig0key
);
512 if (updatemsg
!= NULL
)
513 dns_message_destroy(&updatemsg
);
516 ddebug("Destroy DST lib");
518 is_dst_up
= ISC_FALSE
;
522 ddebug("Detach from entropy");
523 isc_entropy_detach(&entp
);
526 lwres_conf_clear(lwctx
);
527 lwres_context_destroy(&lwctx
);
529 isc_mem_put(mctx
, servers
, ns_total
* sizeof(isc_sockaddr_t
));
531 ddebug("Destroying request manager");
532 dns_requestmgr_detach(&requestmgr
);
534 ddebug("Freeing the dispatchers");
536 dns_dispatch_detach(&dispatchv4
);
538 dns_dispatch_detach(&dispatchv6
);
540 ddebug("Shutting down dispatch manager");
541 dns_dispatchmgr_destroy(&dispatchmgr
);
546 maybeshutdown(void) {
547 ddebug("Shutting down request manager");
548 dns_requestmgr_shutdown(requestmgr
);
557 shutdown_program(isc_task_t
*task
, isc_event_t
*event
) {
558 REQUIRE(task
== global_task
);
561 ddebug("shutdown_program()");
562 isc_event_free(&event
);
564 shuttingdown
= ISC_TRUE
;
571 isc_sockaddr_t bind_any
, bind_any6
;
572 lwres_result_t lwresult
;
573 unsigned int attrs
, attrmask
;
576 ddebug("setup_system()");
578 dns_result_register();
580 result
= isc_net_probeipv4();
581 if (result
== ISC_R_SUCCESS
)
582 have_ipv4
= ISC_TRUE
;
584 result
= isc_net_probeipv6();
585 if (result
== ISC_R_SUCCESS
)
586 have_ipv6
= ISC_TRUE
;
588 if (!have_ipv4
&& !have_ipv6
)
589 fatal("could not find either IPv4 or IPv6");
591 result
= isc_mem_create(0, 0, &mctx
);
592 check_result(result
, "isc_mem_create");
594 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
, 1);
595 if (lwresult
!= LWRES_R_SUCCESS
)
596 fatal("lwres_context_create failed");
598 (void)lwres_conf_parse(lwctx
, RESOLV_CONF
);
599 lwconf
= lwres_conf_get(lwctx
);
601 ns_total
= lwconf
->nsnext
;
603 /* No name servers in resolv.conf; default to loopback. */
604 struct in_addr localhost
;
606 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
608 fatal("out of memory");
609 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
610 isc_sockaddr_fromin(&servers
[0], &localhost
, DNSDEFAULTPORT
);
612 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
614 fatal("out of memory");
615 for (i
= 0; i
< ns_total
; i
++) {
616 if (lwconf
->nameservers
[i
].family
== LWRES_ADDRTYPE_V4
) {
618 memcpy(&in4
, lwconf
->nameservers
[i
].address
, 4);
619 isc_sockaddr_fromin(&servers
[i
], &in4
, DNSDEFAULTPORT
);
622 memcpy(&in6
, lwconf
->nameservers
[i
].address
, 16);
623 isc_sockaddr_fromin6(&servers
[i
], &in6
,
629 result
= isc_entropy_create(mctx
, &entp
);
630 check_result(result
, "isc_entropy_create");
632 result
= isc_hash_create(mctx
, entp
, DNS_NAME_MAXWIRE
);
633 check_result(result
, "isc_hash_create");
636 result
= dns_dispatchmgr_create(mctx
, entp
, &dispatchmgr
);
637 check_result(result
, "dns_dispatchmgr_create");
639 result
= isc_socketmgr_create(mctx
, &socketmgr
);
640 check_result(result
, "dns_socketmgr_create");
642 result
= isc_timermgr_create(mctx
, &timermgr
);
643 check_result(result
, "dns_timermgr_create");
645 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
646 check_result(result
, "isc_taskmgr_create");
648 result
= isc_task_create(taskmgr
, 0, &global_task
);
649 check_result(result
, "isc_task_create");
651 result
= isc_task_onshutdown(global_task
, shutdown_program
, NULL
);
652 check_result(result
, "isc_task_onshutdown");
654 result
= dst_lib_init(mctx
, entp
, 0);
655 check_result(result
, "dst_lib_init");
656 is_dst_up
= ISC_TRUE
;
658 attrmask
= DNS_DISPATCHATTR_UDP
| DNS_DISPATCHATTR_TCP
;
659 attrmask
|= DNS_DISPATCHATTR_IPV4
| DNS_DISPATCHATTR_IPV6
;
662 attrs
= DNS_DISPATCHATTR_UDP
;
663 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
664 attrs
|= DNS_DISPATCHATTR_IPV6
;
665 isc_sockaddr_any6(&bind_any6
);
666 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
667 &bind_any6
, PACKETSIZE
,
669 attrs
, attrmask
, &dispatchv6
);
670 check_result(result
, "dns_dispatch_getudp (v6)");
674 attrs
= DNS_DISPATCHATTR_UDP
;
675 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
676 attrs
|= DNS_DISPATCHATTR_IPV4
;
677 isc_sockaddr_any(&bind_any
);
678 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
679 &bind_any
, PACKETSIZE
,
681 attrs
, attrmask
, &dispatchv4
);
682 check_result(result
, "dns_dispatch_getudp (v4)");
685 result
= dns_requestmgr_create(mctx
, timermgr
,
686 socketmgr
, taskmgr
, dispatchmgr
,
687 dispatchv4
, dispatchv6
, &requestmgr
);
688 check_result(result
, "dns_requestmgr_create");
692 else if (keyfile
!= NULL
)
697 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
702 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
704 if (result
!= ISC_R_SUCCESS
)
705 fatal("couldn't get address for '%s': %s",
706 host
, isc_result_totext(result
));
711 parse_args(int argc
, char **argv
) {
716 while ((ch
= isc_commandline_parse(argc
, argv
, "dDMy:vk:r:t:u:")) != -1)
720 debugging
= ISC_TRUE
;
722 case 'D': /* was -dd */
723 debugging
= ISC_TRUE
;
724 ddebugging
= ISC_TRUE
;
726 case 'M': /* was -dm */
727 debugging
= ISC_TRUE
;
728 ddebugging
= ISC_TRUE
;
729 memdebugging
= ISC_TRUE
;
730 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
|
734 keystr
= isc_commandline_argument
;
740 keyfile
= isc_commandline_argument
;
743 result
= isc_parse_uint32(&timeout
,
744 isc_commandline_argument
, 10);
745 if (result
!= ISC_R_SUCCESS
) {
746 fprintf(stderr
, "bad timeout '%s'\n", isc_commandline_argument
);
753 result
= isc_parse_uint32(&udp_timeout
,
754 isc_commandline_argument
, 10);
755 if (result
!= ISC_R_SUCCESS
) {
756 fprintf(stderr
, "bad udp timeout '%s'\n", isc_commandline_argument
);
759 if (udp_timeout
== 0)
760 udp_timeout
= UINT_MAX
;
763 result
= isc_parse_uint32(&udp_retries
,
764 isc_commandline_argument
, 10);
765 if (result
!= ISC_R_SUCCESS
) {
766 fprintf(stderr
, "bad udp retries '%s'\n", isc_commandline_argument
);
771 fprintf(stderr
, "%s: invalid argument -%c\n",
773 fprintf(stderr
, "usage: nsupdate [-d] "
774 "[-y keyname:secret | -k keyfile] [-v] "
779 if (keyfile
!= NULL
&& keystr
!= NULL
) {
780 fprintf(stderr
, "%s: cannot specify both -k and -y\n",
785 if (argv
[isc_commandline_index
] != NULL
) {
786 if (strcmp(argv
[isc_commandline_index
], "-") == 0) {
789 result
= isc_stdio_open(argv
[isc_commandline_index
],
791 if (result
!= ISC_R_SUCCESS
) {
792 fprintf(stderr
, "could not open '%s': %s\n",
793 argv
[isc_commandline_index
],
794 isc_result_totext(result
));
798 interactive
= ISC_FALSE
;
803 parse_name(char **cmdlinep
, dns_message_t
*msg
, dns_name_t
**namep
) {
806 isc_buffer_t
*namebuf
= NULL
;
809 word
= nsu_strsep(cmdlinep
, " \t\r\n");
811 fprintf(stderr
, "could not read owner name\n");
812 return (STATUS_SYNTAX
);
815 result
= dns_message_gettempname(msg
, namep
);
816 check_result(result
, "dns_message_gettempname");
817 result
= isc_buffer_allocate(mctx
, &namebuf
, DNS_NAME_MAXWIRE
);
818 check_result(result
, "isc_buffer_allocate");
819 dns_name_init(*namep
, NULL
);
820 dns_name_setbuffer(*namep
, namebuf
);
821 dns_message_takebuffer(msg
, &namebuf
);
822 isc_buffer_init(&source
, word
, strlen(word
));
823 isc_buffer_add(&source
, strlen(word
));
824 result
= dns_name_fromtext(*namep
, &source
, dns_rootname
,
826 check_result(result
, "dns_name_fromtext");
827 isc_buffer_invalidate(&source
);
828 return (STATUS_MORE
);
832 parse_rdata(char **cmdlinep
, dns_rdataclass_t rdataclass
,
833 dns_rdatatype_t rdatatype
, dns_message_t
*msg
,
836 char *cmdline
= *cmdlinep
;
837 isc_buffer_t source
, *buf
= NULL
, *newbuf
= NULL
;
839 isc_lex_t
*lex
= NULL
;
840 dns_rdatacallbacks_t callbacks
;
843 while (*cmdline
!= 0 && isspace((unsigned char)*cmdline
))
847 dns_rdatacallbacks_init(&callbacks
);
848 result
= isc_lex_create(mctx
, strlen(cmdline
), &lex
);
849 check_result(result
, "isc_lex_create");
850 isc_buffer_init(&source
, cmdline
, strlen(cmdline
));
851 isc_buffer_add(&source
, strlen(cmdline
));
852 result
= isc_lex_openbuffer(lex
, &source
);
853 check_result(result
, "isc_lex_openbuffer");
854 result
= isc_buffer_allocate(mctx
, &buf
, MAXWIRE
);
855 check_result(result
, "isc_buffer_allocate");
856 result
= dns_rdata_fromtext(rdata
, rdataclass
, rdatatype
, lex
,
857 dns_rootname
, 0, mctx
, buf
,
859 isc_lex_destroy(&lex
);
860 if (result
== ISC_R_SUCCESS
) {
861 isc_buffer_usedregion(buf
, &r
);
862 result
= isc_buffer_allocate(mctx
, &newbuf
, r
.length
);
863 check_result(result
, "isc_buffer_allocate");
864 isc_buffer_putmem(newbuf
, r
.base
, r
.length
);
865 isc_buffer_usedregion(newbuf
, &r
);
866 dns_rdata_fromregion(rdata
, rdataclass
, rdatatype
, &r
);
867 isc_buffer_free(&buf
);
868 dns_message_takebuffer(msg
, &newbuf
);
870 fprintf(stderr
, "invalid rdata format: %s\n",
871 isc_result_totext(result
));
872 isc_buffer_free(&buf
);
873 return (STATUS_SYNTAX
);
876 rdata
->flags
= DNS_RDATA_UPDATE
;
879 return (STATUS_MORE
);
883 make_prereq(char *cmdline
, isc_boolean_t ispositive
, isc_boolean_t isrrset
) {
886 dns_name_t
*name
= NULL
;
887 isc_textregion_t region
;
888 dns_rdataset_t
*rdataset
= NULL
;
889 dns_rdatalist_t
*rdatalist
= NULL
;
890 dns_rdataclass_t rdataclass
;
891 dns_rdatatype_t rdatatype
;
892 dns_rdata_t
*rdata
= NULL
;
895 ddebug("make_prereq()");
898 * Read the owner name
900 retval
= parse_name(&cmdline
, updatemsg
, &name
);
901 if (retval
!= STATUS_MORE
)
905 * If this is an rrset prereq, read the class or type.
908 word
= nsu_strsep(&cmdline
, " \t\r\n");
910 fprintf(stderr
, "could not read class or type\n");
914 region
.length
= strlen(word
);
915 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
916 if (result
== ISC_R_SUCCESS
) {
917 if (!setzoneclass(rdataclass
)) {
918 fprintf(stderr
, "class mismatch: %s\n", word
);
924 word
= nsu_strsep(&cmdline
, " \t\r\n");
926 fprintf(stderr
, "could not read type\n");
930 region
.length
= strlen(word
);
931 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
932 if (result
!= ISC_R_SUCCESS
) {
933 fprintf(stderr
, "invalid type: %s\n", word
);
937 rdataclass
= getzoneclass();
938 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
939 if (result
!= ISC_R_SUCCESS
) {
940 fprintf(stderr
, "invalid type: %s\n", word
);
945 rdatatype
= dns_rdatatype_any
;
947 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
948 check_result(result
, "dns_message_gettemprdata");
953 if (isrrset
&& ispositive
) {
954 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
,
956 if (retval
!= STATUS_MORE
)
959 rdata
->flags
= DNS_RDATA_UPDATE
;
961 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
962 check_result(result
, "dns_message_gettemprdatalist");
963 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
964 check_result(result
, "dns_message_gettemprdataset");
965 dns_rdatalist_init(rdatalist
);
966 rdatalist
->type
= rdatatype
;
968 if (isrrset
&& rdata
->data
!= NULL
)
969 rdatalist
->rdclass
= rdataclass
;
971 rdatalist
->rdclass
= dns_rdataclass_any
;
973 rdatalist
->rdclass
= dns_rdataclass_none
;
974 rdatalist
->covers
= 0;
976 rdata
->rdclass
= rdatalist
->rdclass
;
977 rdata
->type
= rdatatype
;
978 ISC_LIST_INIT(rdatalist
->rdata
);
979 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
980 dns_rdataset_init(rdataset
);
981 dns_rdatalist_tordataset(rdatalist
, rdataset
);
982 ISC_LIST_INIT(name
->list
);
983 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
984 dns_message_addname(updatemsg
, name
, DNS_SECTION_PREREQUISITE
);
985 return (STATUS_MORE
);
989 dns_message_puttempname(updatemsg
, &name
);
990 return (STATUS_SYNTAX
);
994 evaluate_prereq(char *cmdline
) {
996 isc_boolean_t ispositive
, isrrset
;
998 ddebug("evaluate_prereq()");
999 word
= nsu_strsep(&cmdline
, " \t\r\n");
1001 fprintf(stderr
, "could not read operation code\n");
1002 return (STATUS_SYNTAX
);
1004 if (strcasecmp(word
, "nxdomain") == 0) {
1005 ispositive
= ISC_FALSE
;
1006 isrrset
= ISC_FALSE
;
1007 } else if (strcasecmp(word
, "yxdomain") == 0) {
1008 ispositive
= ISC_TRUE
;
1009 isrrset
= ISC_FALSE
;
1010 } else if (strcasecmp(word
, "nxrrset") == 0) {
1011 ispositive
= ISC_FALSE
;
1013 } else if (strcasecmp(word
, "yxrrset") == 0) {
1014 ispositive
= ISC_TRUE
;
1017 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1018 return (STATUS_SYNTAX
);
1020 return (make_prereq(cmdline
, ispositive
, isrrset
));
1024 evaluate_server(char *cmdline
) {
1025 char *word
, *server
;
1028 word
= nsu_strsep(&cmdline
, " \t\r\n");
1030 fprintf(stderr
, "could not read server name\n");
1031 return (STATUS_SYNTAX
);
1035 word
= nsu_strsep(&cmdline
, " \t\r\n");
1037 port
= DNSDEFAULTPORT
;
1040 port
= strtol(word
, &endp
, 10);
1042 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1043 return (STATUS_SYNTAX
);
1044 } else if (port
< 1 || port
> 65535) {
1045 fprintf(stderr
, "port '%s' is out of range "
1046 "(1 to 65535)\n", word
);
1047 return (STATUS_SYNTAX
);
1051 if (userserver
== NULL
) {
1052 userserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1053 if (userserver
== NULL
)
1054 fatal("out of memory");
1057 get_address(server
, (in_port_t
)port
, userserver
);
1059 return (STATUS_MORE
);
1063 evaluate_local(char *cmdline
) {
1067 struct in6_addr in6
;
1069 word
= nsu_strsep(&cmdline
, " \t\r\n");
1071 fprintf(stderr
, "could not read server name\n");
1072 return (STATUS_SYNTAX
);
1076 word
= nsu_strsep(&cmdline
, " \t\r\n");
1081 port
= strtol(word
, &endp
, 10);
1083 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1084 return (STATUS_SYNTAX
);
1085 } else if (port
< 1 || port
> 65535) {
1086 fprintf(stderr
, "port '%s' is out of range "
1087 "(1 to 65535)\n", word
);
1088 return (STATUS_SYNTAX
);
1092 if (localaddr
== NULL
) {
1093 localaddr
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1094 if (localaddr
== NULL
)
1095 fatal("out of memory");
1098 if (have_ipv6
&& inet_pton(AF_INET6
, local
, &in6
) == 1)
1099 isc_sockaddr_fromin6(localaddr
, &in6
, (in_port_t
)port
);
1100 else if (have_ipv4
&& inet_pton(AF_INET
, local
, &in4
) == 1)
1101 isc_sockaddr_fromin(localaddr
, &in4
, (in_port_t
)port
);
1103 fprintf(stderr
, "invalid address %s", local
);
1104 return (STATUS_SYNTAX
);
1107 return (STATUS_MORE
);
1111 evaluate_key(char *cmdline
) {
1115 isc_result_t result
;
1116 dns_fixedname_t fkeyname
;
1117 dns_name_t
*keyname
;
1119 unsigned char *secret
= NULL
;
1120 isc_buffer_t secretbuf
;
1121 dns_name_t
*hmacname
= NULL
;
1122 isc_uint16_t digestbits
= 0;
1125 namestr
= nsu_strsep(&cmdline
, " \t\r\n");
1126 if (*namestr
== 0) {
1127 fprintf(stderr
, "could not read key name\n");
1128 return (STATUS_SYNTAX
);
1131 dns_fixedname_init(&fkeyname
);
1132 keyname
= dns_fixedname_name(&fkeyname
);
1134 n
= strchr(namestr
, ':');
1136 digestbits
= parse_hmac(&hmacname
, namestr
, n
- namestr
);
1139 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1141 isc_buffer_init(&b
, namestr
, strlen(namestr
));
1142 isc_buffer_add(&b
, strlen(namestr
));
1143 result
= dns_name_fromtext(keyname
, &b
, dns_rootname
, ISC_FALSE
, NULL
);
1144 if (result
!= ISC_R_SUCCESS
) {
1145 fprintf(stderr
, "could not parse key name\n");
1146 return (STATUS_SYNTAX
);
1149 secretstr
= nsu_strsep(&cmdline
, "\r\n");
1150 if (*secretstr
== 0) {
1151 fprintf(stderr
, "could not read key secret\n");
1152 return (STATUS_SYNTAX
);
1154 secretlen
= strlen(secretstr
) * 3 / 4;
1155 secret
= isc_mem_allocate(mctx
, secretlen
);
1157 fatal("out of memory");
1159 isc_buffer_init(&secretbuf
, secret
, secretlen
);
1160 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
1161 if (result
!= ISC_R_SUCCESS
) {
1162 fprintf(stderr
, "could not create key from %s: %s\n",
1163 secretstr
, isc_result_totext(result
));
1164 isc_mem_free(mctx
, secret
);
1165 return (STATUS_SYNTAX
);
1167 secretlen
= isc_buffer_usedlength(&secretbuf
);
1169 if (tsigkey
!= NULL
)
1170 dns_tsigkey_detach(&tsigkey
);
1171 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
1172 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
,
1174 isc_mem_free(mctx
, secret
);
1175 if (result
!= ISC_R_SUCCESS
) {
1176 fprintf(stderr
, "could not create key from %s %s: %s\n",
1177 namestr
, secretstr
, dns_result_totext(result
));
1178 return (STATUS_SYNTAX
);
1180 dst_key_setbits(tsigkey
->key
, digestbits
);
1181 return (STATUS_MORE
);
1185 evaluate_zone(char *cmdline
) {
1188 isc_result_t result
;
1190 word
= nsu_strsep(&cmdline
, " \t\r\n");
1192 fprintf(stderr
, "could not read zone name\n");
1193 return (STATUS_SYNTAX
);
1196 dns_fixedname_init(&fuserzone
);
1197 userzone
= dns_fixedname_name(&fuserzone
);
1198 isc_buffer_init(&b
, word
, strlen(word
));
1199 isc_buffer_add(&b
, strlen(word
));
1200 result
= dns_name_fromtext(userzone
, &b
, dns_rootname
, ISC_FALSE
,
1202 if (result
!= ISC_R_SUCCESS
) {
1203 userzone
= NULL
; /* Lest it point to an invalid name */
1204 fprintf(stderr
, "could not parse zone name\n");
1205 return (STATUS_SYNTAX
);
1208 return (STATUS_MORE
);
1212 evaluate_class(char *cmdline
) {
1215 isc_result_t result
;
1216 dns_rdataclass_t rdclass
;
1218 word
= nsu_strsep(&cmdline
, " \t\r\n");
1220 fprintf(stderr
, "could not read class name\n");
1221 return (STATUS_SYNTAX
);
1225 r
.length
= strlen(word
);
1226 result
= dns_rdataclass_fromtext(&rdclass
, &r
);
1227 if (result
!= ISC_R_SUCCESS
) {
1228 fprintf(stderr
, "could not parse class name: %s\n", word
);
1229 return (STATUS_SYNTAX
);
1232 case dns_rdataclass_none
:
1233 case dns_rdataclass_any
:
1234 case dns_rdataclass_reserved0
:
1235 fprintf(stderr
, "bad default class: %s\n", word
);
1236 return (STATUS_SYNTAX
);
1238 defaultclass
= rdclass
;
1241 return (STATUS_MORE
);
1245 update_addordelete(char *cmdline
, isc_boolean_t isdelete
) {
1246 isc_result_t result
;
1247 dns_name_t
*name
= NULL
;
1250 dns_rdataclass_t rdataclass
;
1251 dns_rdatatype_t rdatatype
;
1252 dns_rdata_t
*rdata
= NULL
;
1253 dns_rdatalist_t
*rdatalist
= NULL
;
1254 dns_rdataset_t
*rdataset
= NULL
;
1255 isc_textregion_t region
;
1256 isc_uint16_t retval
;
1258 ddebug("update_addordelete()");
1261 * Read the owner name.
1263 retval
= parse_name(&cmdline
, updatemsg
, &name
);
1264 if (retval
!= STATUS_MORE
)
1267 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
1268 check_result(result
, "dns_message_gettemprdata");
1276 * If this is an add, read the TTL and verify that it's in range.
1277 * If it's a delete, ignore a TTL if present (for compatibility).
1279 word
= nsu_strsep(&cmdline
, " \t\r\n");
1282 fprintf(stderr
, "could not read owner ttl\n");
1287 rdataclass
= dns_rdataclass_any
;
1288 rdatatype
= dns_rdatatype_any
;
1289 rdata
->flags
= DNS_RDATA_UPDATE
;
1293 result
= isc_parse_uint32(&ttl
, word
, 10);
1294 if (result
!= ISC_R_SUCCESS
) {
1299 fprintf(stderr
, "ttl '%s': %s\n", word
,
1300 isc_result_totext(result
));
1307 else if (ttl
> TTL_MAX
) {
1308 fprintf(stderr
, "ttl '%s' is out of range (0 to %u)\n",
1314 * Read the class or type.
1316 word
= nsu_strsep(&cmdline
, " \t\r\n");
1320 rdataclass
= dns_rdataclass_any
;
1321 rdatatype
= dns_rdatatype_any
;
1322 rdata
->flags
= DNS_RDATA_UPDATE
;
1325 fprintf(stderr
, "could not read class or type\n");
1330 region
.length
= strlen(word
);
1331 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
1332 if (result
== ISC_R_SUCCESS
) {
1333 if (!setzoneclass(rdataclass
)) {
1334 fprintf(stderr
, "class mismatch: %s\n", word
);
1338 * Now read the type.
1340 word
= nsu_strsep(&cmdline
, " \t\r\n");
1343 rdataclass
= dns_rdataclass_any
;
1344 rdatatype
= dns_rdatatype_any
;
1345 rdata
->flags
= DNS_RDATA_UPDATE
;
1348 fprintf(stderr
, "could not read type\n");
1353 region
.length
= strlen(word
);
1354 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1355 if (result
!= ISC_R_SUCCESS
) {
1356 fprintf(stderr
, "'%s' is not a valid type: %s\n",
1357 word
, isc_result_totext(result
));
1361 rdataclass
= getzoneclass();
1362 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1363 if (result
!= ISC_R_SUCCESS
) {
1364 fprintf(stderr
, "'%s' is not a valid class or type: "
1365 "%s\n", word
, isc_result_totext(result
));
1370 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
, updatemsg
,
1372 if (retval
!= STATUS_MORE
)
1376 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0)
1377 rdataclass
= dns_rdataclass_any
;
1379 rdataclass
= dns_rdataclass_none
;
1381 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0) {
1382 fprintf(stderr
, "could not read rdata\n");
1389 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
1390 check_result(result
, "dns_message_gettemprdatalist");
1391 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1392 check_result(result
, "dns_message_gettemprdataset");
1393 dns_rdatalist_init(rdatalist
);
1394 rdatalist
->type
= rdatatype
;
1395 rdatalist
->rdclass
= rdataclass
;
1396 rdatalist
->covers
= rdatatype
;
1397 rdatalist
->ttl
= (dns_ttl_t
)ttl
;
1398 ISC_LIST_INIT(rdatalist
->rdata
);
1399 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1400 dns_rdataset_init(rdataset
);
1401 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1402 ISC_LIST_INIT(name
->list
);
1403 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1404 dns_message_addname(updatemsg
, name
, DNS_SECTION_UPDATE
);
1405 return (STATUS_MORE
);
1409 dns_message_puttempname(updatemsg
, &name
);
1411 dns_message_puttemprdata(updatemsg
, &rdata
);
1412 return (STATUS_SYNTAX
);
1416 evaluate_update(char *cmdline
) {
1418 isc_boolean_t isdelete
;
1420 ddebug("evaluate_update()");
1421 word
= nsu_strsep(&cmdline
, " \t\r\n");
1423 fprintf(stderr
, "could not read operation code\n");
1424 return (STATUS_SYNTAX
);
1426 if (strcasecmp(word
, "delete") == 0)
1427 isdelete
= ISC_TRUE
;
1428 else if (strcasecmp(word
, "add") == 0)
1429 isdelete
= ISC_FALSE
;
1431 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1432 return (STATUS_SYNTAX
);
1434 return (update_addordelete(cmdline
, isdelete
));
1438 setzone(dns_name_t
*zonename
) {
1439 isc_result_t result
;
1440 dns_name_t
*name
= NULL
;
1441 dns_rdataset_t
*rdataset
= NULL
;
1443 result
= dns_message_firstname(updatemsg
, DNS_SECTION_ZONE
);
1444 if (result
== ISC_R_SUCCESS
) {
1445 dns_message_currentname(updatemsg
, DNS_SECTION_ZONE
, &name
);
1446 dns_message_removename(updatemsg
, name
, DNS_SECTION_ZONE
);
1447 for (rdataset
= ISC_LIST_HEAD(name
->list
);
1449 rdataset
= ISC_LIST_HEAD(name
->list
)) {
1450 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
1451 dns_rdataset_disassociate(rdataset
);
1452 dns_message_puttemprdataset(updatemsg
, &rdataset
);
1454 dns_message_puttempname(updatemsg
, &name
);
1457 if (zonename
!= NULL
) {
1458 result
= dns_message_gettempname(updatemsg
, &name
);
1459 check_result(result
, "dns_message_gettempname");
1460 dns_name_init(name
, NULL
);
1461 dns_name_clone(zonename
, name
);
1462 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1463 check_result(result
, "dns_message_gettemprdataset");
1464 dns_rdataset_makequestion(rdataset
, getzoneclass(),
1466 ISC_LIST_INIT(name
->list
);
1467 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1468 dns_message_addname(updatemsg
, name
, DNS_SECTION_ZONE
);
1473 show_message(dns_message_t
*msg
) {
1474 isc_result_t result
;
1475 isc_buffer_t
*buf
= NULL
;
1478 ddebug("show_message()");
1484 if (bufsz
> MAXTEXT
) {
1485 fprintf(stderr
, "could not allocate large enough "
1486 "buffer to display message\n");
1490 isc_buffer_free(&buf
);
1491 result
= isc_buffer_allocate(mctx
, &buf
, bufsz
);
1492 check_result(result
, "isc_buffer_allocate");
1493 result
= dns_message_totext(msg
, style
, 0, buf
);
1495 } while (result
== ISC_R_NOSPACE
);
1496 if (result
!= ISC_R_SUCCESS
) {
1497 fprintf(stderr
, "could not convert message to text format.\n");
1498 isc_buffer_free(&buf
);
1501 printf("Outgoing update query:\n%.*s",
1502 (int)isc_buffer_usedlength(buf
),
1503 (char*)isc_buffer_base(buf
));
1504 isc_buffer_free(&buf
);
1509 get_next_command(void) {
1510 char cmdlinebuf
[MAXCMD
];
1514 ddebug("get_next_command()");
1516 fprintf(stdout
, "> ");
1520 cmdline
= fgets(cmdlinebuf
, MAXCMD
, input
);
1522 if (cmdline
== NULL
)
1523 return (STATUS_QUIT
);
1524 word
= nsu_strsep(&cmdline
, " \t\r\n");
1527 return (STATUS_QUIT
);
1529 return (STATUS_SEND
);
1531 return (STATUS_MORE
);
1532 if (strcasecmp(word
, "quit") == 0)
1533 return (STATUS_QUIT
);
1534 if (strcasecmp(word
, "prereq") == 0)
1535 return (evaluate_prereq(cmdline
));
1536 if (strcasecmp(word
, "update") == 0)
1537 return (evaluate_update(cmdline
));
1538 if (strcasecmp(word
, "server") == 0)
1539 return (evaluate_server(cmdline
));
1540 if (strcasecmp(word
, "local") == 0)
1541 return (evaluate_local(cmdline
));
1542 if (strcasecmp(word
, "zone") == 0)
1543 return (evaluate_zone(cmdline
));
1544 if (strcasecmp(word
, "class") == 0)
1545 return (evaluate_class(cmdline
));
1546 if (strcasecmp(word
, "send") == 0)
1547 return (STATUS_SEND
);
1548 if (strcasecmp(word
, "show") == 0) {
1549 show_message(updatemsg
);
1550 return (STATUS_MORE
);
1552 if (strcasecmp(word
, "answer") == 0) {
1554 show_message(answer
);
1555 return (STATUS_MORE
);
1557 if (strcasecmp(word
, "key") == 0)
1558 return (evaluate_key(cmdline
));
1559 fprintf(stderr
, "incorrect section name: %s\n", word
);
1560 return (STATUS_SYNTAX
);
1563 static isc_boolean_t
1564 user_interaction(void) {
1565 isc_uint16_t result
= STATUS_MORE
;
1567 ddebug("user_interaction()");
1568 while ((result
== STATUS_MORE
) || (result
== STATUS_SYNTAX
)) {
1569 result
= get_next_command();
1570 if (!interactive
&& result
== STATUS_SYNTAX
)
1571 fatal("syntax error");
1573 if (result
== STATUS_SEND
)
1581 isc_event_t
*event
= global_event
;
1582 ddebug("done_update()");
1583 isc_task_send(global_task
, &event
);
1587 check_tsig_error(dns_rdataset_t
*rdataset
, isc_buffer_t
*b
) {
1588 isc_result_t result
;
1589 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1590 dns_rdata_any_tsig_t tsig
;
1592 result
= dns_rdataset_first(rdataset
);
1593 check_result(result
, "dns_rdataset_first");
1594 dns_rdataset_current(rdataset
, &rdata
);
1595 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
1596 check_result(result
, "dns_rdata_tostruct");
1597 if (tsig
.error
!= 0) {
1598 if (isc_buffer_remaininglength(b
) < 1)
1599 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1600 isc__buffer_putstr(b
, "(" /*)*/);
1601 result
= dns_tsigrcode_totext(tsig
.error
, b
);
1602 check_result(result
, "dns_tsigrcode_totext");
1603 if (isc_buffer_remaininglength(b
) < 1)
1604 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1605 isc__buffer_putstr(b
, /*(*/ ")");
1610 update_completed(isc_task_t
*task
, isc_event_t
*event
) {
1611 dns_requestevent_t
*reqev
= NULL
;
1612 isc_result_t result
;
1613 dns_request_t
*request
;
1617 ddebug("update_completed()");
1621 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1622 reqev
= (dns_requestevent_t
*)event
;
1623 request
= reqev
->request
;
1626 dns_request_destroy(&request
);
1627 isc_event_free(&event
);
1632 if (reqev
->result
!= ISC_R_SUCCESS
) {
1633 fprintf(stderr
, "; Communication with server failed: %s\n",
1634 isc_result_totext(reqev
->result
));
1635 seenerror
= ISC_TRUE
;
1639 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &answer
);
1640 check_result(result
, "dns_message_create");
1641 result
= dns_request_getresponse(request
, answer
,
1642 DNS_MESSAGEPARSE_PRESERVEORDER
);
1646 case DNS_R_CLOCKSKEW
:
1647 case DNS_R_EXPECTEDTSIG
:
1648 case DNS_R_TSIGERRORSET
:
1649 case DNS_R_TSIGVERIFYFAILURE
:
1650 case DNS_R_UNEXPECTEDTSIG
:
1651 fprintf(stderr
, "; TSIG error with server: %s\n",
1652 isc_result_totext(result
));
1653 seenerror
= ISC_TRUE
;
1656 check_result(result
, "dns_request_getresponse");
1659 if (answer
->rcode
!= dns_rcode_noerror
) {
1660 seenerror
= ISC_TRUE
;
1664 dns_rdataset_t
*rds
;
1666 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1667 result
= dns_rcode_totext(answer
->rcode
, &b
);
1668 check_result(result
, "dns_rcode_totext");
1669 rds
= dns_message_gettsig(answer
, NULL
);
1671 check_tsig_error(rds
, &b
);
1672 fprintf(stderr
, "update failed: %.*s\n",
1673 (int)isc_buffer_usedlength(&b
), buf
);
1677 isc_buffer_t
*buf
= NULL
;
1682 if (bufsz
> MAXTEXT
) {
1683 fprintf(stderr
, "could not allocate large "
1684 "enough buffer to display message\n");
1688 isc_buffer_free(&buf
);
1689 result
= isc_buffer_allocate(mctx
, &buf
, bufsz
);
1690 check_result(result
, "isc_buffer_allocate");
1691 result
= dns_message_totext(answer
, style
, 0, buf
);
1693 } while (result
== ISC_R_NOSPACE
);
1694 check_result(result
, "dns_message_totext");
1695 fprintf(stderr
, "\nReply from update query:\n%.*s\n",
1696 (int)isc_buffer_usedlength(buf
),
1697 (char*)isc_buffer_base(buf
));
1698 isc_buffer_free(&buf
);
1701 dns_request_destroy(&request
);
1702 isc_event_free(&event
);
1707 send_update(dns_name_t
*zonename
, isc_sockaddr_t
*master
,
1708 isc_sockaddr_t
*srcaddr
)
1710 isc_result_t result
;
1711 dns_request_t
*request
= NULL
;
1712 unsigned int options
= 0;
1714 ddebug("send_update()");
1719 options
|= DNS_REQUESTOPT_TCP
;
1720 if (tsigkey
== NULL
&& sig0key
!= NULL
) {
1721 result
= dns_message_setsig0key(updatemsg
, sig0key
);
1722 check_result(result
, "dns_message_setsig0key");
1725 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
1727 isc_sockaddr_format(master
, addrbuf
, sizeof(addrbuf
));
1728 fprintf(stderr
, "Sending update to %s\n", addrbuf
);
1730 result
= dns_request_createvia3(requestmgr
, updatemsg
, srcaddr
,
1731 master
, options
, tsigkey
, timeout
,
1732 udp_timeout
, udp_retries
, global_task
,
1733 update_completed
, NULL
, &request
);
1734 check_result(result
, "dns_request_createvia3");
1737 show_message(updatemsg
);
1743 recvsoa(isc_task_t
*task
, isc_event_t
*event
) {
1744 dns_requestevent_t
*reqev
= NULL
;
1745 dns_request_t
*request
= NULL
;
1746 isc_result_t result
, eresult
;
1747 dns_message_t
*rcvmsg
= NULL
;
1748 dns_section_t section
;
1749 dns_name_t
*name
= NULL
;
1750 dns_rdataset_t
*soaset
= NULL
;
1751 dns_rdata_soa_t soa
;
1752 dns_rdata_t soarr
= DNS_RDATA_INIT
;
1755 isc_sockaddr_t
*serveraddr
, tempaddr
;
1756 dns_name_t
*zonename
;
1757 nsu_requestinfo_t
*reqinfo
;
1758 dns_message_t
*soaquery
= NULL
;
1759 isc_sockaddr_t
*addr
;
1760 isc_boolean_t seencname
= ISC_FALSE
;
1762 unsigned int nlabels
;
1766 ddebug("recvsoa()");
1770 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1771 reqev
= (dns_requestevent_t
*)event
;
1772 request
= reqev
->request
;
1773 eresult
= reqev
->result
;
1774 reqinfo
= reqev
->ev_arg
;
1775 soaquery
= reqinfo
->msg
;
1776 addr
= reqinfo
->addr
;
1779 dns_request_destroy(&request
);
1780 dns_message_destroy(&soaquery
);
1781 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
1782 isc_event_free(&event
);
1787 if (eresult
!= ISC_R_SUCCESS
) {
1788 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
1790 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
1791 fprintf(stderr
, "; Communication with %s failed: %s\n",
1792 addrbuf
, isc_result_totext(eresult
));
1793 if (userserver
!= NULL
)
1794 fatal("could not talk to specified name server");
1795 else if (++ns_inuse
>= lwconf
->nsnext
)
1796 fatal("could not talk to any default name server");
1797 ddebug("Destroying request [%p]", request
);
1798 dns_request_destroy(&request
);
1799 dns_message_renderreset(soaquery
);
1800 dns_message_settsigkey(soaquery
, NULL
);
1801 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
1802 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
1803 isc_event_free(&event
);
1804 setzoneclass(dns_rdataclass_none
);
1808 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
1810 isc_event_free(&event
);
1813 ddebug("About to create rcvmsg");
1814 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
1815 check_result(result
, "dns_message_create");
1816 result
= dns_request_getresponse(request
, rcvmsg
,
1817 DNS_MESSAGEPARSE_PRESERVEORDER
);
1818 if (result
== DNS_R_TSIGERRORSET
&& userserver
!= NULL
) {
1819 dns_message_destroy(&rcvmsg
);
1820 ddebug("Destroying request [%p]", request
);
1821 dns_request_destroy(&request
);
1822 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
1823 if (reqinfo
== NULL
)
1824 fatal("out of memory");
1825 reqinfo
->msg
= soaquery
;
1826 reqinfo
->addr
= addr
;
1827 dns_message_renderreset(soaquery
);
1828 ddebug("retrying soa request without TSIG");
1829 result
= dns_request_createvia3(requestmgr
, soaquery
,
1830 localaddr
, addr
, 0, NULL
,
1833 global_task
, recvsoa
, reqinfo
,
1835 check_result(result
, "dns_request_createvia");
1839 check_result(result
, "dns_request_getresponse");
1840 section
= DNS_SECTION_ANSWER
;
1842 isc_buffer_t
*buf
= NULL
;
1847 isc_buffer_free(&buf
);
1848 if (bufsz
> MAXTEXT
) {
1849 fprintf(stderr
, "could not allocate enough "
1850 "space for debugging message\n");
1853 result
= isc_buffer_allocate(mctx
, &buf
, bufsz
);
1854 check_result(result
, "isc_buffer_allocate");
1855 result
= dns_message_totext(rcvmsg
, style
, 0, buf
);
1856 } while (result
== ISC_R_NOSPACE
);
1857 check_result(result
, "dns_message_totext");
1858 fprintf(stderr
, "Reply from SOA query:\n%.*s\n",
1859 (int)isc_buffer_usedlength(buf
),
1860 (char*)isc_buffer_base(buf
));
1861 isc_buffer_free(&buf
);
1864 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
1865 rcvmsg
->rcode
!= dns_rcode_nxdomain
)
1866 fatal("response to SOA query was unsuccessful");
1868 if (userzone
!= NULL
&& rcvmsg
->rcode
== dns_rcode_nxdomain
) {
1869 char namebuf
[DNS_NAME_FORMATSIZE
];
1870 dns_name_format(userzone
, namebuf
, sizeof(namebuf
));
1871 error("specified zone '%s' does not exist (NXDOMAIN)",
1873 dns_message_destroy(&rcvmsg
);
1874 dns_request_destroy(&request
);
1875 dns_message_destroy(&soaquery
);
1876 ddebug("Out of recvsoa");
1883 section
= DNS_SECTION_ANSWER
;
1885 section
= DNS_SECTION_AUTHORITY
;
1889 result
= dns_message_firstname(rcvmsg
, section
);
1890 if (result
!= ISC_R_SUCCESS
) {
1894 while (result
== ISC_R_SUCCESS
) {
1896 dns_message_currentname(rcvmsg
, section
, &name
);
1898 result
= dns_message_findtype(name
, dns_rdatatype_soa
, 0,
1900 if (result
== ISC_R_SUCCESS
)
1902 if (section
== DNS_SECTION_ANSWER
) {
1903 dns_rdataset_t
*tset
= NULL
;
1904 if (dns_message_findtype(name
, dns_rdatatype_cname
, 0,
1905 &tset
) == ISC_R_SUCCESS
1907 dns_message_findtype(name
, dns_rdatatype_dname
, 0,
1908 &tset
) == ISC_R_SUCCESS
1911 seencname
= ISC_TRUE
;
1916 result
= dns_message_nextname(rcvmsg
, section
);
1919 if (soaset
== NULL
&& !seencname
) {
1928 char namestr
[DNS_NAME_FORMATSIZE
];
1929 dns_name_format(name
, namestr
, sizeof(namestr
));
1930 fprintf(stderr
, "Found zone name: %s\n", namestr
);
1933 result
= dns_rdataset_first(soaset
);
1934 check_result(result
, "dns_rdataset_first");
1936 dns_rdata_init(&soarr
);
1937 dns_rdataset_current(soaset
, &soarr
);
1938 result
= dns_rdata_tostruct(&soarr
, &soa
, NULL
);
1939 check_result(result
, "dns_rdata_tostruct");
1941 dns_name_init(&master
, NULL
);
1942 dns_name_clone(&soa
.origin
, &master
);
1944 if (userzone
!= NULL
)
1945 zonename
= userzone
;
1950 char namestr
[DNS_NAME_FORMATSIZE
];
1951 dns_name_format(&master
, namestr
, sizeof(namestr
));
1952 fprintf(stderr
, "The master is: %s\n", namestr
);
1955 if (userserver
!= NULL
)
1956 serveraddr
= userserver
;
1958 char serverstr
[DNS_NAME_MAXTEXT
+1];
1961 isc_buffer_init(&buf
, serverstr
, sizeof(serverstr
));
1962 result
= dns_name_totext(&master
, ISC_TRUE
, &buf
);
1963 check_result(result
, "dns_name_totext");
1964 serverstr
[isc_buffer_usedlength(&buf
)] = 0;
1965 get_address(serverstr
, DNSDEFAULTPORT
, &tempaddr
);
1966 serveraddr
= &tempaddr
;
1968 dns_rdata_freestruct(&soa
);
1970 send_update(zonename
, serveraddr
, localaddr
);
1971 setzoneclass(dns_rdataclass_none
);
1973 dns_message_destroy(&soaquery
);
1974 dns_request_destroy(&request
);
1977 dns_message_destroy(&rcvmsg
);
1978 ddebug("Out of recvsoa");
1982 result
= dns_message_firstname(soaquery
, DNS_SECTION_QUESTION
);
1983 INSIST(result
== ISC_R_SUCCESS
);
1985 dns_message_currentname(soaquery
, DNS_SECTION_QUESTION
, &name
);
1986 nlabels
= dns_name_countlabels(name
);
1988 fatal("could not find enclosing zone");
1989 dns_name_init(&tname
, NULL
);
1990 dns_name_getlabelsequence(name
, 1, nlabels
- 1, &tname
);
1991 dns_name_clone(&tname
, name
);
1992 dns_request_destroy(&request
);
1993 dns_message_renderreset(soaquery
);
1994 dns_message_settsigkey(soaquery
, NULL
);
1995 if (userserver
!= NULL
)
1996 sendrequest(localaddr
, userserver
, soaquery
, &request
);
1998 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
,
2004 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
2005 dns_message_t
*msg
, dns_request_t
**request
)
2007 isc_result_t result
;
2008 nsu_requestinfo_t
*reqinfo
;
2010 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
2011 if (reqinfo
== NULL
)
2012 fatal("out of memory");
2014 reqinfo
->addr
= destaddr
;
2015 result
= dns_request_createvia3(requestmgr
, msg
, srcaddr
, destaddr
, 0,
2016 (userserver
!= NULL
) ? tsigkey
: NULL
,
2017 FIND_TIMEOUT
* 20, FIND_TIMEOUT
, 3,
2018 global_task
, recvsoa
, reqinfo
, request
);
2019 check_result(result
, "dns_request_createvia");
2024 start_update(void) {
2025 isc_result_t result
;
2026 dns_rdataset_t
*rdataset
= NULL
;
2027 dns_name_t
*name
= NULL
;
2028 dns_request_t
*request
= NULL
;
2029 dns_message_t
*soaquery
= NULL
;
2030 dns_name_t
*firstname
;
2031 dns_section_t section
= DNS_SECTION_UPDATE
;
2033 ddebug("start_update()");
2036 dns_message_destroy(&answer
);
2038 if (userzone
!= NULL
&& userserver
!= NULL
) {
2039 send_update(userzone
, userserver
, localaddr
);
2040 setzoneclass(dns_rdataclass_none
);
2044 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
2046 check_result(result
, "dns_message_create");
2048 if (userserver
== NULL
)
2049 soaquery
->flags
|= DNS_MESSAGEFLAG_RD
;
2051 result
= dns_message_gettempname(soaquery
, &name
);
2052 check_result(result
, "dns_message_gettempname");
2054 result
= dns_message_gettemprdataset(soaquery
, &rdataset
);
2055 check_result(result
, "dns_message_gettemprdataset");
2057 dns_rdataset_makequestion(rdataset
, getzoneclass(), dns_rdatatype_soa
);
2059 if (userzone
!= NULL
) {
2060 dns_name_init(name
, NULL
);
2061 dns_name_clone(userzone
, name
);
2063 result
= dns_message_firstname(updatemsg
, section
);
2064 if (result
== ISC_R_NOMORE
) {
2065 section
= DNS_SECTION_PREREQUISITE
;
2066 result
= dns_message_firstname(updatemsg
, section
);
2068 if (result
!= ISC_R_SUCCESS
) {
2069 dns_message_puttempname(soaquery
, &name
);
2070 dns_rdataset_disassociate(rdataset
);
2071 dns_message_puttemprdataset(soaquery
, &rdataset
);
2072 dns_message_destroy(&soaquery
);
2077 dns_message_currentname(updatemsg
, section
, &firstname
);
2078 dns_name_init(name
, NULL
);
2079 dns_name_clone(firstname
, name
);
2082 ISC_LIST_INIT(name
->list
);
2083 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
2084 dns_message_addname(soaquery
, name
, DNS_SECTION_QUESTION
);
2086 if (userserver
!= NULL
)
2087 sendrequest(localaddr
, userserver
, soaquery
, &request
);
2090 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2096 ddebug("cleanup()");
2099 dns_message_destroy(&answer
);
2100 ddebug("Shutting down task manager");
2101 isc_taskmgr_destroy(&taskmgr
);
2103 ddebug("Destroying event");
2104 isc_event_free(&global_event
);
2106 ddebug("Shutting down socket manager");
2107 isc_socketmgr_destroy(&socketmgr
);
2109 ddebug("Shutting down timer manager");
2110 isc_timermgr_destroy(&timermgr
);
2112 ddebug("Destroying hash context");
2115 ddebug("Destroying name state");
2118 ddebug("Destroying memory context");
2120 isc_mem_stats(mctx
, stderr
);
2121 isc_mem_destroy(&mctx
);
2125 getinput(isc_task_t
*task
, isc_event_t
*event
) {
2135 if (global_event
== NULL
)
2136 global_event
= event
;
2139 more
= user_interaction();
2149 main(int argc
, char **argv
) {
2150 isc_result_t result
;
2151 style
= &dns_master_style_debug
;
2155 interactive
= ISC_TF(isatty(0));
2159 parse_args(argc
, argv
);
2163 result
= isc_app_onrun(mctx
, global_task
, getinput
, NULL
);
2164 check_result(result
, "isc_app_onrun");
2166 (void)isc_app_run();