2 * Copyright (C) 2004-2009 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.154.56.6 2009/04/30 07:12:15 marka 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>
40 #include <isc/parseint.h>
41 #include <isc/random.h>
42 #include <isc/region.h>
43 #include <isc/sockaddr.h>
44 #include <isc/socket.h>
45 #include <isc/stdio.h>
46 #include <isc/string.h>
48 #include <isc/timer.h>
49 #include <isc/types.h>
52 #include <dns/callbacks.h>
53 #include <dns/dispatch.h>
54 #include <dns/dnssec.h>
55 #include <dns/events.h>
56 #include <dns/fixedname.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
61 #include <dns/rcode.h>
62 #include <dns/rdata.h>
63 #include <dns/rdataclass.h>
64 #include <dns/rdatalist.h>
65 #include <dns/rdataset.h>
66 #include <dns/rdatastruct.h>
67 #include <dns/rdatatype.h>
68 #include <dns/request.h>
69 #include <dns/result.h>
75 #include <lwres/lwres.h>
76 #include <lwres/net.h>
79 #include <dst/gssapi.h>
81 #include <bind9/getaddresses.h>
85 #ifdef HAVE_GETADDRINFO
86 #ifdef HAVE_GAISTRERROR
87 #define USE_GETADDRINFO
92 #ifndef USE_GETADDRINFO
93 #ifndef ISC_PLATFORM_NONSTDHERRNO
98 #define MAXCMD (4 * 1024)
99 #define MAXWIRE (64 * 1024)
100 #define PACKETSIZE ((64 * 1024) - 1)
101 #define INITTEXT (2 * 1024)
102 #define MAXTEXT (128 * 1024)
103 #define FIND_TIMEOUT 5
104 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
106 #define DNSDEFAULTPORT 53
109 #define RESOLV_CONF "/etc/resolv.conf"
112 static isc_boolean_t debugging
= ISC_FALSE
, ddebugging
= ISC_FALSE
;
113 static isc_boolean_t memdebugging
= ISC_FALSE
;
114 static isc_boolean_t have_ipv4
= ISC_FALSE
;
115 static isc_boolean_t have_ipv6
= ISC_FALSE
;
116 static isc_boolean_t is_dst_up
= ISC_FALSE
;
117 static isc_boolean_t usevc
= ISC_FALSE
;
118 static isc_boolean_t usegsstsig
= ISC_FALSE
;
119 static isc_boolean_t use_win2k_gsstsig
= ISC_FALSE
;
120 static isc_boolean_t tried_other_gsstsig
= ISC_FALSE
;
121 static isc_taskmgr_t
*taskmgr
= NULL
;
122 static isc_task_t
*global_task
= NULL
;
123 static isc_event_t
*global_event
= NULL
;
124 static isc_log_t
*lctx
= NULL
;
125 static isc_mem_t
*mctx
= NULL
;
126 static dns_dispatchmgr_t
*dispatchmgr
= NULL
;
127 static dns_requestmgr_t
*requestmgr
= NULL
;
128 static isc_socketmgr_t
*socketmgr
= NULL
;
129 static isc_timermgr_t
*timermgr
= NULL
;
130 static dns_dispatch_t
*dispatchv4
= NULL
;
131 static dns_dispatch_t
*dispatchv6
= NULL
;
132 static dns_message_t
*updatemsg
= NULL
;
133 static dns_fixedname_t fuserzone
;
134 static dns_name_t
*userzone
= NULL
;
135 static dns_name_t
*zonename
= NULL
;
136 static dns_name_t tmpzonename
;
137 static dns_name_t restart_master
;
138 static dns_tsig_keyring_t
*gssring
= NULL
;
139 static dns_tsigkey_t
*tsigkey
= NULL
;
140 static dst_key_t
*sig0key
;
141 static lwres_context_t
*lwctx
= NULL
;
142 static lwres_conf_t
*lwconf
;
143 static isc_sockaddr_t
*servers
;
144 static int ns_inuse
= 0;
145 static int ns_total
= 0;
146 static isc_sockaddr_t
*userserver
= NULL
;
147 static isc_sockaddr_t
*localaddr
= NULL
;
148 static isc_sockaddr_t
*serveraddr
= NULL
;
149 static isc_sockaddr_t tempaddr
;
150 static char *keystr
= NULL
, *keyfile
= NULL
;
151 static isc_entropy_t
*entropy
= NULL
;
152 static isc_boolean_t shuttingdown
= ISC_FALSE
;
154 static isc_boolean_t interactive
= ISC_TRUE
;
155 static isc_boolean_t seenerror
= ISC_FALSE
;
156 static const dns_master_style_t
*style
;
157 static int requests
= 0;
158 static unsigned int logdebuglevel
= 0;
159 static unsigned int timeout
= 300;
160 static unsigned int udp_timeout
= 3;
161 static unsigned int udp_retries
= 3;
162 static dns_rdataclass_t defaultclass
= dns_rdataclass_in
;
163 static dns_rdataclass_t zoneclass
= dns_rdataclass_none
;
164 static dns_message_t
*answer
= NULL
;
166 typedef struct nsu_requestinfo
{
168 isc_sockaddr_t
*addr
;
172 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
173 dns_message_t
*msg
, dns_request_t
**request
);
175 fatal(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
178 debug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
181 ddebug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
184 static dns_fixedname_t fkname
;
185 static isc_sockaddr_t
*kserver
= NULL
;
186 static char servicename
[DNS_NAME_FORMATSIZE
];
187 static dns_name_t
*keyname
;
188 typedef struct nsu_gssinfo
{
190 isc_sockaddr_t
*addr
;
191 gss_ctx_id_t context
;
195 start_gssrequest(dns_name_t
*master
);
197 send_gssrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
198 dns_message_t
*msg
, dns_request_t
**request
,
199 gss_ctx_id_t context
);
201 recvgss(isc_task_t
*task
, isc_event_t
*event
);
205 error(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
207 #define STATUS_MORE (isc_uint16_t)0
208 #define STATUS_SEND (isc_uint16_t)1
209 #define STATUS_QUIT (isc_uint16_t)2
210 #define STATUS_SYNTAX (isc_uint16_t)3
212 typedef struct entropysource entropysource_t
;
214 struct entropysource
{
215 isc_entropysource_t
*source
;
217 ISC_LINK(entropysource_t
) link
;
220 static ISC_LIST(entropysource_t
) sources
;
223 setup_entropy(isc_mem_t
*mctx
, const char *randomfile
, isc_entropy_t
**ectx
)
226 isc_entropysource_t
*source
= NULL
;
227 entropysource_t
*elt
;
228 int usekeyboard
= ISC_ENTROPY_KEYBOARDMAYBE
;
230 REQUIRE(ectx
!= NULL
);
233 result
= isc_entropy_create(mctx
, ectx
);
234 if (result
!= ISC_R_SUCCESS
)
235 fatal("could not create entropy object");
236 ISC_LIST_INIT(sources
);
239 if (randomfile
!= NULL
&& strcmp(randomfile
, "keyboard") == 0) {
240 usekeyboard
= ISC_ENTROPY_KEYBOARDYES
;
244 result
= isc_entropy_usebestsource(*ectx
, &source
, randomfile
,
247 if (result
!= ISC_R_SUCCESS
)
248 fatal("could not initialize entropy source: %s",
249 isc_result_totext(result
));
251 if (source
!= NULL
) {
252 elt
= isc_mem_get(mctx
, sizeof(*elt
));
254 fatal("out of memory");
255 elt
->source
= source
;
257 ISC_LINK_INIT(elt
, link
);
258 ISC_LIST_APPEND(sources
, elt
, link
);
263 cleanup_entropy(isc_entropy_t
**ectx
) {
264 entropysource_t
*source
;
265 while (!ISC_LIST_EMPTY(sources
)) {
266 source
= ISC_LIST_HEAD(sources
);
267 ISC_LIST_UNLINK(sources
, source
, link
);
268 isc_entropy_destroysource(&source
->source
);
269 isc_mem_put(source
->mctx
, source
, sizeof(*source
));
271 isc_entropy_detach(ectx
);
275 static dns_rdataclass_t
277 if (zoneclass
== dns_rdataclass_none
)
278 zoneclass
= defaultclass
;
283 setzoneclass(dns_rdataclass_t rdclass
) {
284 if (zoneclass
== dns_rdataclass_none
||
285 rdclass
== dns_rdataclass_none
)
287 if (zoneclass
!= rdclass
)
293 fatal(const char *format
, ...) {
296 va_start(args
, format
);
297 vfprintf(stderr
, format
, args
);
299 fprintf(stderr
, "\n");
304 error(const char *format
, ...) {
307 va_start(args
, format
);
308 vfprintf(stderr
, format
, args
);
310 fprintf(stderr
, "\n");
314 debug(const char *format
, ...) {
318 va_start(args
, format
);
319 vfprintf(stderr
, format
, args
);
321 fprintf(stderr
, "\n");
326 ddebug(const char *format
, ...) {
330 va_start(args
, format
);
331 vfprintf(stderr
, format
, args
);
333 fprintf(stderr
, "\n");
338 check_result(isc_result_t result
, const char *msg
) {
339 if (result
!= ISC_R_SUCCESS
)
340 fatal("%s: %s", msg
, isc_result_totext(result
));
344 mem_alloc(void *arg
, size_t size
) {
345 return (isc_mem_get(arg
, size
));
349 mem_free(void *arg
, void *mem
, size_t size
) {
350 isc_mem_put(arg
, mem
, size
);
354 nsu_strsep(char **stringp
, const char *delim
) {
355 char *string
= *stringp
;
363 for (; *string
!= '\0'; string
++) {
365 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
373 for (s
= string
; *s
!= '\0'; s
++) {
375 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
391 ddebug("reset_system()");
392 /* If the update message is still around, destroy it */
393 if (updatemsg
!= NULL
)
394 dns_message_reset(updatemsg
, DNS_MESSAGE_INTENTRENDER
);
396 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
398 check_result(result
, "dns_message_create");
400 updatemsg
->opcode
= dns_opcode_update
;
403 dns_tsigkey_detach(&tsigkey
);
405 dns_tsigkeyring_destroy(&gssring
);
406 tried_other_gsstsig
= ISC_FALSE
;
411 parse_hmac(dns_name_t
**hmac
, const char *hmacstr
, size_t len
) {
412 isc_uint16_t digestbits
= 0;
416 REQUIRE(hmac
!= NULL
&& *hmac
== NULL
);
417 REQUIRE(hmacstr
!= NULL
);
419 if (len
>= sizeof(buf
))
420 fatal("unknown key type '%.*s'", (int)(len
), hmacstr
);
422 strncpy(buf
, hmacstr
, len
);
425 if (strcasecmp(buf
, "hmac-md5") == 0) {
426 *hmac
= DNS_TSIG_HMACMD5_NAME
;
427 } else if (strncasecmp(buf
, "hmac-md5-", 9) == 0) {
428 *hmac
= DNS_TSIG_HMACMD5_NAME
;
429 result
= isc_parse_uint16(&digestbits
, &buf
[9], 10);
430 if (result
!= ISC_R_SUCCESS
|| digestbits
> 128)
431 fatal("digest-bits out of range [0..128]");
432 digestbits
= (digestbits
+7) & ~0x7U
;
433 } else if (strcasecmp(buf
, "hmac-sha1") == 0) {
434 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
435 } else if (strncasecmp(buf
, "hmac-sha1-", 10) == 0) {
436 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
437 result
= isc_parse_uint16(&digestbits
, &buf
[10], 10);
438 if (result
!= ISC_R_SUCCESS
|| digestbits
> 160)
439 fatal("digest-bits out of range [0..160]");
440 digestbits
= (digestbits
+7) & ~0x7U
;
441 } else if (strcasecmp(buf
, "hmac-sha224") == 0) {
442 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
443 } else if (strncasecmp(buf
, "hmac-sha224-", 12) == 0) {
444 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
445 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
446 if (result
!= ISC_R_SUCCESS
|| digestbits
> 224)
447 fatal("digest-bits out of range [0..224]");
448 digestbits
= (digestbits
+7) & ~0x7U
;
449 } else if (strcasecmp(buf
, "hmac-sha256") == 0) {
450 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
451 } else if (strncasecmp(buf
, "hmac-sha256-", 12) == 0) {
452 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
453 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
454 if (result
!= ISC_R_SUCCESS
|| digestbits
> 256)
455 fatal("digest-bits out of range [0..256]");
456 digestbits
= (digestbits
+7) & ~0x7U
;
457 } else if (strcasecmp(buf
, "hmac-sha384") == 0) {
458 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
459 } else if (strncasecmp(buf
, "hmac-sha384-", 12) == 0) {
460 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
461 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
462 if (result
!= ISC_R_SUCCESS
|| digestbits
> 384)
463 fatal("digest-bits out of range [0..384]");
464 digestbits
= (digestbits
+7) & ~0x7U
;
465 } else if (strcasecmp(buf
, "hmac-sha512") == 0) {
466 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
467 } else if (strncasecmp(buf
, "hmac-sha512-", 12) == 0) {
468 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
469 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
470 if (result
!= ISC_R_SUCCESS
|| digestbits
> 512)
471 fatal("digest-bits out of range [0..512]");
472 digestbits
= (digestbits
+7) & ~0x7U
;
474 fatal("unknown key type '%s'", buf
);
480 unsigned char *secret
= NULL
;
482 isc_buffer_t secretbuf
;
484 isc_buffer_t keynamesrc
;
487 dns_fixedname_t fkeyname
;
490 dns_name_t
*hmacname
= NULL
;
491 isc_uint16_t digestbits
= 0;
493 dns_fixedname_init(&fkeyname
);
494 keyname
= dns_fixedname_name(&fkeyname
);
496 debug("Creating key...");
498 s
= strchr(keystr
, ':');
499 if (s
== NULL
|| s
== keystr
|| s
[1] == 0)
500 fatal("key option must specify [hmac:]keyname:secret");
502 n
= strchr(secretstr
, ':');
504 if (n
== secretstr
|| n
[1] == 0)
505 fatal("key option must specify [hmac:]keyname:secret");
508 digestbits
= parse_hmac(&hmacname
, keystr
, s
- keystr
);
510 hmacname
= DNS_TSIG_HMACMD5_NAME
;
515 isc_buffer_init(&keynamesrc
, name
, n
- name
);
516 isc_buffer_add(&keynamesrc
, n
- name
);
518 debug("namefromtext");
519 result
= dns_name_fromtext(keyname
, &keynamesrc
, dns_rootname
,
521 check_result(result
, "dns_name_fromtext");
523 secretlen
= strlen(secretstr
) * 3 / 4;
524 secret
= isc_mem_allocate(mctx
, secretlen
);
526 fatal("out of memory");
528 isc_buffer_init(&secretbuf
, secret
, secretlen
);
529 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
530 if (result
!= ISC_R_SUCCESS
) {
531 fprintf(stderr
, "could not create key from %s: %s\n",
532 keystr
, isc_result_totext(result
));
536 secretlen
= isc_buffer_usedlength(&secretbuf
);
539 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
540 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
, &tsigkey
);
541 if (result
!= ISC_R_SUCCESS
)
542 fprintf(stderr
, "could not create key from %s: %s\n",
543 keystr
, dns_result_totext(result
));
545 dst_key_setbits(tsigkey
->key
, digestbits
);
548 isc_mem_free(mctx
, secret
);
552 setup_keyfile(void) {
553 dst_key_t
*dstkey
= NULL
;
555 dns_name_t
*hmacname
= NULL
;
557 debug("Creating key...");
559 result
= dst_key_fromnamedfile(keyfile
,
560 DST_TYPE_PRIVATE
| DST_TYPE_KEY
, mctx
,
562 if (result
!= ISC_R_SUCCESS
) {
563 fprintf(stderr
, "could not read key from %s: %s\n",
564 keyfile
, isc_result_totext(result
));
567 switch (dst_key_alg(dstkey
)) {
568 case DST_ALG_HMACMD5
:
569 hmacname
= DNS_TSIG_HMACMD5_NAME
;
571 case DST_ALG_HMACSHA1
:
572 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
574 case DST_ALG_HMACSHA224
:
575 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
577 case DST_ALG_HMACSHA256
:
578 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
580 case DST_ALG_HMACSHA384
:
581 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
583 case DST_ALG_HMACSHA512
:
584 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
587 if (hmacname
!= NULL
) {
588 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
),
589 hmacname
, dstkey
, ISC_FALSE
,
590 NULL
, 0, 0, mctx
, NULL
,
592 if (result
!= ISC_R_SUCCESS
) {
593 fprintf(stderr
, "could not create key from %s: %s\n",
594 keyfile
, isc_result_totext(result
));
595 dst_key_free(&dstkey
);
604 isc_task_detach(&global_task
);
606 if (userserver
!= NULL
)
607 isc_mem_put(mctx
, userserver
, sizeof(isc_sockaddr_t
));
609 if (localaddr
!= NULL
)
610 isc_mem_put(mctx
, localaddr
, sizeof(isc_sockaddr_t
));
612 if (tsigkey
!= NULL
) {
613 ddebug("Freeing TSIG key");
614 dns_tsigkey_detach(&tsigkey
);
617 if (sig0key
!= NULL
) {
618 ddebug("Freeing SIG(0) key");
619 dst_key_free(&sig0key
);
622 if (updatemsg
!= NULL
)
623 dns_message_destroy(&updatemsg
);
626 ddebug("Destroy DST lib");
628 is_dst_up
= ISC_FALSE
;
631 cleanup_entropy(&entropy
);
633 lwres_conf_clear(lwctx
);
634 lwres_context_destroy(&lwctx
);
636 isc_mem_put(mctx
, servers
, ns_total
* sizeof(isc_sockaddr_t
));
638 ddebug("Destroying request manager");
639 dns_requestmgr_detach(&requestmgr
);
641 ddebug("Freeing the dispatchers");
643 dns_dispatch_detach(&dispatchv4
);
645 dns_dispatch_detach(&dispatchv6
);
647 ddebug("Shutting down dispatch manager");
648 dns_dispatchmgr_destroy(&dispatchmgr
);
653 maybeshutdown(void) {
654 ddebug("Shutting down request manager");
655 dns_requestmgr_shutdown(requestmgr
);
664 shutdown_program(isc_task_t
*task
, isc_event_t
*event
) {
665 REQUIRE(task
== global_task
);
668 ddebug("shutdown_program()");
669 isc_event_free(&event
);
671 shuttingdown
= ISC_TRUE
;
678 isc_sockaddr_t bind_any
, bind_any6
;
679 lwres_result_t lwresult
;
680 unsigned int attrs
, attrmask
;
682 isc_logconfig_t
*logconfig
= NULL
;
684 ddebug("setup_system()");
686 dns_result_register();
688 result
= isc_net_probeipv4();
689 if (result
== ISC_R_SUCCESS
)
690 have_ipv4
= ISC_TRUE
;
692 result
= isc_net_probeipv6();
693 if (result
== ISC_R_SUCCESS
)
694 have_ipv6
= ISC_TRUE
;
696 if (!have_ipv4
&& !have_ipv6
)
697 fatal("could not find either IPv4 or IPv6");
699 result
= isc_log_create(mctx
, &lctx
, &logconfig
);
700 check_result(result
, "isc_log_create");
702 isc_log_setcontext(lctx
);
704 dns_log_setcontext(lctx
);
706 result
= isc_log_usechannel(logconfig
, "default_debug", NULL
, NULL
);
707 check_result(result
, "isc_log_usechannel");
709 isc_log_setdebuglevel(lctx
, logdebuglevel
);
711 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
, 1);
712 if (lwresult
!= LWRES_R_SUCCESS
)
713 fatal("lwres_context_create failed");
715 (void)lwres_conf_parse(lwctx
, RESOLV_CONF
);
716 lwconf
= lwres_conf_get(lwctx
);
718 ns_total
= lwconf
->nsnext
;
720 /* No name servers in resolv.conf; default to loopback. */
721 struct in_addr localhost
;
723 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
725 fatal("out of memory");
726 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
727 isc_sockaddr_fromin(&servers
[0], &localhost
, DNSDEFAULTPORT
);
729 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
731 fatal("out of memory");
732 for (i
= 0; i
< ns_total
; i
++) {
733 if (lwconf
->nameservers
[i
].family
== LWRES_ADDRTYPE_V4
) {
735 memcpy(&in4
, lwconf
->nameservers
[i
].address
, 4);
736 isc_sockaddr_fromin(&servers
[i
], &in4
, DNSDEFAULTPORT
);
739 memcpy(&in6
, lwconf
->nameservers
[i
].address
, 16);
740 isc_sockaddr_fromin6(&servers
[i
], &in6
,
746 setup_entropy(mctx
, NULL
, &entropy
);
748 result
= isc_hash_create(mctx
, entropy
, DNS_NAME_MAXWIRE
);
749 check_result(result
, "isc_hash_create");
752 result
= dns_dispatchmgr_create(mctx
, entropy
, &dispatchmgr
);
753 check_result(result
, "dns_dispatchmgr_create");
755 result
= isc_socketmgr_create(mctx
, &socketmgr
);
756 check_result(result
, "dns_socketmgr_create");
758 result
= isc_timermgr_create(mctx
, &timermgr
);
759 check_result(result
, "dns_timermgr_create");
761 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
762 check_result(result
, "isc_taskmgr_create");
764 result
= isc_task_create(taskmgr
, 0, &global_task
);
765 check_result(result
, "isc_task_create");
767 result
= isc_task_onshutdown(global_task
, shutdown_program
, NULL
);
768 check_result(result
, "isc_task_onshutdown");
770 result
= dst_lib_init(mctx
, entropy
, 0);
771 check_result(result
, "dst_lib_init");
772 is_dst_up
= ISC_TRUE
;
774 attrmask
= DNS_DISPATCHATTR_UDP
| DNS_DISPATCHATTR_TCP
;
775 attrmask
|= DNS_DISPATCHATTR_IPV4
| DNS_DISPATCHATTR_IPV6
;
778 attrs
= DNS_DISPATCHATTR_UDP
;
779 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
780 attrs
|= DNS_DISPATCHATTR_IPV6
;
781 isc_sockaddr_any6(&bind_any6
);
782 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
783 &bind_any6
, PACKETSIZE
,
785 attrs
, attrmask
, &dispatchv6
);
786 check_result(result
, "dns_dispatch_getudp (v6)");
790 attrs
= DNS_DISPATCHATTR_UDP
;
791 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
792 attrs
|= DNS_DISPATCHATTR_IPV4
;
793 isc_sockaddr_any(&bind_any
);
794 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
795 &bind_any
, PACKETSIZE
,
797 attrs
, attrmask
, &dispatchv4
);
798 check_result(result
, "dns_dispatch_getudp (v4)");
801 result
= dns_requestmgr_create(mctx
, timermgr
,
802 socketmgr
, taskmgr
, dispatchmgr
,
803 dispatchv4
, dispatchv6
, &requestmgr
);
804 check_result(result
, "dns_requestmgr_create");
808 else if (keyfile
!= NULL
)
813 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
818 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
820 if (result
!= ISC_R_SUCCESS
)
821 fatal("couldn't get address for '%s': %s",
822 host
, isc_result_totext(result
));
826 #define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
829 pre_parse_args(int argc
, char **argv
) {
832 while ((ch
= isc_commandline_parse(argc
, argv
, PARSE_ARGS_FMT
)) != -1) {
834 case 'M': /* was -dm */
835 debugging
= ISC_TRUE
;
836 ddebugging
= ISC_TRUE
;
837 memdebugging
= ISC_TRUE
;
838 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
|
843 if (isc_commandline_option
!= '?')
844 fprintf(stderr
, "%s: invalid argument -%c\n",
845 argv
[0], isc_commandline_option
);
846 fprintf(stderr
, "usage: nsupdate [-d] "
847 "[-g | -o | -y keyname:secret | -k keyfile] "
848 "[-v] [filename]\n");
855 isc_commandline_reset
= ISC_TRUE
;
856 isc_commandline_index
= 1;
860 parse_args(int argc
, char **argv
, isc_mem_t
*mctx
, isc_entropy_t
**ectx
) {
866 while ((ch
= isc_commandline_parse(argc
, argv
, PARSE_ARGS_FMT
)) != -1) {
869 debugging
= ISC_TRUE
;
871 case 'D': /* was -dd */
872 debugging
= ISC_TRUE
;
873 ddebugging
= ISC_TRUE
;
878 result
= isc_parse_uint32(&i
, isc_commandline_argument
,
880 if (result
!= ISC_R_SUCCESS
) {
881 fprintf(stderr
, "bad library debug value "
882 "'%s'\n", isc_commandline_argument
);
888 keystr
= isc_commandline_argument
;
894 keyfile
= isc_commandline_argument
;
897 usegsstsig
= ISC_TRUE
;
898 use_win2k_gsstsig
= ISC_FALSE
;
901 usegsstsig
= ISC_TRUE
;
902 use_win2k_gsstsig
= ISC_TRUE
;
905 result
= isc_parse_uint32(&timeout
,
906 isc_commandline_argument
, 10);
907 if (result
!= ISC_R_SUCCESS
) {
908 fprintf(stderr
, "bad timeout '%s'\n", isc_commandline_argument
);
915 result
= isc_parse_uint32(&udp_timeout
,
916 isc_commandline_argument
, 10);
917 if (result
!= ISC_R_SUCCESS
) {
918 fprintf(stderr
, "bad udp timeout '%s'\n", isc_commandline_argument
);
921 if (udp_timeout
== 0)
922 udp_timeout
= UINT_MAX
;
925 result
= isc_parse_uint32(&udp_retries
,
926 isc_commandline_argument
, 10);
927 if (result
!= ISC_R_SUCCESS
) {
928 fprintf(stderr
, "bad udp retries '%s'\n", isc_commandline_argument
);
934 setup_entropy(mctx
, isc_commandline_argument
, ectx
);
938 fprintf(stderr
, "%s: unhandled option: %c\n",
939 argv
[0], isc_commandline_option
);
943 if (keyfile
!= NULL
&& keystr
!= NULL
) {
944 fprintf(stderr
, "%s: cannot specify both -k and -y\n",
950 if (usegsstsig
&& (keyfile
!= NULL
|| keystr
!= NULL
)) {
951 fprintf(stderr
, "%s: cannot specify -g with -k or -y\n",
957 fprintf(stderr
, "%s: cannot specify -g or -o, " \
958 "program not linked with GSS API Library\n",
964 if (argv
[isc_commandline_index
] != NULL
) {
965 if (strcmp(argv
[isc_commandline_index
], "-") == 0) {
968 result
= isc_stdio_open(argv
[isc_commandline_index
],
970 if (result
!= ISC_R_SUCCESS
) {
971 fprintf(stderr
, "could not open '%s': %s\n",
972 argv
[isc_commandline_index
],
973 isc_result_totext(result
));
977 interactive
= ISC_FALSE
;
982 parse_name(char **cmdlinep
, dns_message_t
*msg
, dns_name_t
**namep
) {
985 isc_buffer_t
*namebuf
= NULL
;
988 word
= nsu_strsep(cmdlinep
, " \t\r\n");
990 fprintf(stderr
, "could not read owner name\n");
991 return (STATUS_SYNTAX
);
994 result
= dns_message_gettempname(msg
, namep
);
995 check_result(result
, "dns_message_gettempname");
996 result
= isc_buffer_allocate(mctx
, &namebuf
, DNS_NAME_MAXWIRE
);
997 check_result(result
, "isc_buffer_allocate");
998 dns_name_init(*namep
, NULL
);
999 dns_name_setbuffer(*namep
, namebuf
);
1000 dns_message_takebuffer(msg
, &namebuf
);
1001 isc_buffer_init(&source
, word
, strlen(word
));
1002 isc_buffer_add(&source
, strlen(word
));
1003 result
= dns_name_fromtext(*namep
, &source
, dns_rootname
,
1005 check_result(result
, "dns_name_fromtext");
1006 isc_buffer_invalidate(&source
);
1007 return (STATUS_MORE
);
1011 parse_rdata(char **cmdlinep
, dns_rdataclass_t rdataclass
,
1012 dns_rdatatype_t rdatatype
, dns_message_t
*msg
,
1015 char *cmdline
= *cmdlinep
;
1016 isc_buffer_t source
, *buf
= NULL
, *newbuf
= NULL
;
1018 isc_lex_t
*lex
= NULL
;
1019 dns_rdatacallbacks_t callbacks
;
1020 isc_result_t result
;
1022 while (*cmdline
!= 0 && isspace((unsigned char)*cmdline
))
1025 if (*cmdline
!= 0) {
1026 dns_rdatacallbacks_init(&callbacks
);
1027 result
= isc_lex_create(mctx
, strlen(cmdline
), &lex
);
1028 check_result(result
, "isc_lex_create");
1029 isc_buffer_init(&source
, cmdline
, strlen(cmdline
));
1030 isc_buffer_add(&source
, strlen(cmdline
));
1031 result
= isc_lex_openbuffer(lex
, &source
);
1032 check_result(result
, "isc_lex_openbuffer");
1033 result
= isc_buffer_allocate(mctx
, &buf
, MAXWIRE
);
1034 check_result(result
, "isc_buffer_allocate");
1035 result
= dns_rdata_fromtext(rdata
, rdataclass
, rdatatype
, lex
,
1036 dns_rootname
, 0, mctx
, buf
,
1038 isc_lex_destroy(&lex
);
1039 if (result
== ISC_R_SUCCESS
) {
1040 isc_buffer_usedregion(buf
, &r
);
1041 result
= isc_buffer_allocate(mctx
, &newbuf
, r
.length
);
1042 check_result(result
, "isc_buffer_allocate");
1043 isc_buffer_putmem(newbuf
, r
.base
, r
.length
);
1044 isc_buffer_usedregion(newbuf
, &r
);
1045 dns_rdata_fromregion(rdata
, rdataclass
, rdatatype
, &r
);
1046 isc_buffer_free(&buf
);
1047 dns_message_takebuffer(msg
, &newbuf
);
1049 fprintf(stderr
, "invalid rdata format: %s\n",
1050 isc_result_totext(result
));
1051 isc_buffer_free(&buf
);
1052 return (STATUS_SYNTAX
);
1055 rdata
->flags
= DNS_RDATA_UPDATE
;
1057 *cmdlinep
= cmdline
;
1058 return (STATUS_MORE
);
1062 make_prereq(char *cmdline
, isc_boolean_t ispositive
, isc_boolean_t isrrset
) {
1063 isc_result_t result
;
1065 dns_name_t
*name
= NULL
;
1066 isc_textregion_t region
;
1067 dns_rdataset_t
*rdataset
= NULL
;
1068 dns_rdatalist_t
*rdatalist
= NULL
;
1069 dns_rdataclass_t rdataclass
;
1070 dns_rdatatype_t rdatatype
;
1071 dns_rdata_t
*rdata
= NULL
;
1072 isc_uint16_t retval
;
1074 ddebug("make_prereq()");
1077 * Read the owner name
1079 retval
= parse_name(&cmdline
, updatemsg
, &name
);
1080 if (retval
!= STATUS_MORE
)
1084 * If this is an rrset prereq, read the class or type.
1087 word
= nsu_strsep(&cmdline
, " \t\r\n");
1089 fprintf(stderr
, "could not read class or type\n");
1093 region
.length
= strlen(word
);
1094 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
1095 if (result
== ISC_R_SUCCESS
) {
1096 if (!setzoneclass(rdataclass
)) {
1097 fprintf(stderr
, "class mismatch: %s\n", word
);
1101 * Now read the type.
1103 word
= nsu_strsep(&cmdline
, " \t\r\n");
1105 fprintf(stderr
, "could not read type\n");
1109 region
.length
= strlen(word
);
1110 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1111 if (result
!= ISC_R_SUCCESS
) {
1112 fprintf(stderr
, "invalid type: %s\n", word
);
1116 rdataclass
= getzoneclass();
1117 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1118 if (result
!= ISC_R_SUCCESS
) {
1119 fprintf(stderr
, "invalid type: %s\n", word
);
1124 rdatatype
= dns_rdatatype_any
;
1126 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
1127 check_result(result
, "dns_message_gettemprdata");
1132 if (isrrset
&& ispositive
) {
1133 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
,
1135 if (retval
!= STATUS_MORE
)
1138 rdata
->flags
= DNS_RDATA_UPDATE
;
1140 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
1141 check_result(result
, "dns_message_gettemprdatalist");
1142 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1143 check_result(result
, "dns_message_gettemprdataset");
1144 dns_rdatalist_init(rdatalist
);
1145 rdatalist
->type
= rdatatype
;
1147 if (isrrset
&& rdata
->data
!= NULL
)
1148 rdatalist
->rdclass
= rdataclass
;
1150 rdatalist
->rdclass
= dns_rdataclass_any
;
1152 rdatalist
->rdclass
= dns_rdataclass_none
;
1153 rdatalist
->covers
= 0;
1155 rdata
->rdclass
= rdatalist
->rdclass
;
1156 rdata
->type
= rdatatype
;
1157 ISC_LIST_INIT(rdatalist
->rdata
);
1158 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1159 dns_rdataset_init(rdataset
);
1160 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1161 ISC_LIST_INIT(name
->list
);
1162 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1163 dns_message_addname(updatemsg
, name
, DNS_SECTION_PREREQUISITE
);
1164 return (STATUS_MORE
);
1168 dns_message_puttempname(updatemsg
, &name
);
1169 return (STATUS_SYNTAX
);
1173 evaluate_prereq(char *cmdline
) {
1175 isc_boolean_t ispositive
, isrrset
;
1177 ddebug("evaluate_prereq()");
1178 word
= nsu_strsep(&cmdline
, " \t\r\n");
1180 fprintf(stderr
, "could not read operation code\n");
1181 return (STATUS_SYNTAX
);
1183 if (strcasecmp(word
, "nxdomain") == 0) {
1184 ispositive
= ISC_FALSE
;
1185 isrrset
= ISC_FALSE
;
1186 } else if (strcasecmp(word
, "yxdomain") == 0) {
1187 ispositive
= ISC_TRUE
;
1188 isrrset
= ISC_FALSE
;
1189 } else if (strcasecmp(word
, "nxrrset") == 0) {
1190 ispositive
= ISC_FALSE
;
1192 } else if (strcasecmp(word
, "yxrrset") == 0) {
1193 ispositive
= ISC_TRUE
;
1196 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1197 return (STATUS_SYNTAX
);
1199 return (make_prereq(cmdline
, ispositive
, isrrset
));
1203 evaluate_server(char *cmdline
) {
1204 char *word
, *server
;
1207 word
= nsu_strsep(&cmdline
, " \t\r\n");
1209 fprintf(stderr
, "could not read server name\n");
1210 return (STATUS_SYNTAX
);
1214 word
= nsu_strsep(&cmdline
, " \t\r\n");
1216 port
= DNSDEFAULTPORT
;
1219 port
= strtol(word
, &endp
, 10);
1221 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1222 return (STATUS_SYNTAX
);
1223 } else if (port
< 1 || port
> 65535) {
1224 fprintf(stderr
, "port '%s' is out of range "
1225 "(1 to 65535)\n", word
);
1226 return (STATUS_SYNTAX
);
1230 if (userserver
== NULL
) {
1231 userserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1232 if (userserver
== NULL
)
1233 fatal("out of memory");
1236 get_address(server
, (in_port_t
)port
, userserver
);
1238 return (STATUS_MORE
);
1242 evaluate_local(char *cmdline
) {
1246 struct in6_addr in6
;
1248 word
= nsu_strsep(&cmdline
, " \t\r\n");
1250 fprintf(stderr
, "could not read server name\n");
1251 return (STATUS_SYNTAX
);
1255 word
= nsu_strsep(&cmdline
, " \t\r\n");
1260 port
= strtol(word
, &endp
, 10);
1262 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1263 return (STATUS_SYNTAX
);
1264 } else if (port
< 1 || port
> 65535) {
1265 fprintf(stderr
, "port '%s' is out of range "
1266 "(1 to 65535)\n", word
);
1267 return (STATUS_SYNTAX
);
1271 if (localaddr
== NULL
) {
1272 localaddr
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1273 if (localaddr
== NULL
)
1274 fatal("out of memory");
1277 if (have_ipv6
&& inet_pton(AF_INET6
, local
, &in6
) == 1)
1278 isc_sockaddr_fromin6(localaddr
, &in6
, (in_port_t
)port
);
1279 else if (have_ipv4
&& inet_pton(AF_INET
, local
, &in4
) == 1)
1280 isc_sockaddr_fromin(localaddr
, &in4
, (in_port_t
)port
);
1282 fprintf(stderr
, "invalid address %s", local
);
1283 return (STATUS_SYNTAX
);
1286 return (STATUS_MORE
);
1290 evaluate_key(char *cmdline
) {
1294 isc_result_t result
;
1295 dns_fixedname_t fkeyname
;
1296 dns_name_t
*keyname
;
1298 unsigned char *secret
= NULL
;
1299 isc_buffer_t secretbuf
;
1300 dns_name_t
*hmacname
= NULL
;
1301 isc_uint16_t digestbits
= 0;
1304 namestr
= nsu_strsep(&cmdline
, " \t\r\n");
1305 if (*namestr
== 0) {
1306 fprintf(stderr
, "could not read key name\n");
1307 return (STATUS_SYNTAX
);
1310 dns_fixedname_init(&fkeyname
);
1311 keyname
= dns_fixedname_name(&fkeyname
);
1313 n
= strchr(namestr
, ':');
1315 digestbits
= parse_hmac(&hmacname
, namestr
, n
- namestr
);
1318 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1320 isc_buffer_init(&b
, namestr
, strlen(namestr
));
1321 isc_buffer_add(&b
, strlen(namestr
));
1322 result
= dns_name_fromtext(keyname
, &b
, dns_rootname
, ISC_FALSE
, NULL
);
1323 if (result
!= ISC_R_SUCCESS
) {
1324 fprintf(stderr
, "could not parse key name\n");
1325 return (STATUS_SYNTAX
);
1328 secretstr
= nsu_strsep(&cmdline
, "\r\n");
1329 if (*secretstr
== 0) {
1330 fprintf(stderr
, "could not read key secret\n");
1331 return (STATUS_SYNTAX
);
1333 secretlen
= strlen(secretstr
) * 3 / 4;
1334 secret
= isc_mem_allocate(mctx
, secretlen
);
1336 fatal("out of memory");
1338 isc_buffer_init(&secretbuf
, secret
, secretlen
);
1339 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
1340 if (result
!= ISC_R_SUCCESS
) {
1341 fprintf(stderr
, "could not create key from %s: %s\n",
1342 secretstr
, isc_result_totext(result
));
1343 isc_mem_free(mctx
, secret
);
1344 return (STATUS_SYNTAX
);
1346 secretlen
= isc_buffer_usedlength(&secretbuf
);
1348 if (tsigkey
!= NULL
)
1349 dns_tsigkey_detach(&tsigkey
);
1350 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
1351 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
,
1353 isc_mem_free(mctx
, secret
);
1354 if (result
!= ISC_R_SUCCESS
) {
1355 fprintf(stderr
, "could not create key from %s %s: %s\n",
1356 namestr
, secretstr
, dns_result_totext(result
));
1357 return (STATUS_SYNTAX
);
1359 dst_key_setbits(tsigkey
->key
, digestbits
);
1360 return (STATUS_MORE
);
1364 evaluate_zone(char *cmdline
) {
1367 isc_result_t result
;
1369 word
= nsu_strsep(&cmdline
, " \t\r\n");
1371 fprintf(stderr
, "could not read zone name\n");
1372 return (STATUS_SYNTAX
);
1375 dns_fixedname_init(&fuserzone
);
1376 userzone
= dns_fixedname_name(&fuserzone
);
1377 isc_buffer_init(&b
, word
, strlen(word
));
1378 isc_buffer_add(&b
, strlen(word
));
1379 result
= dns_name_fromtext(userzone
, &b
, dns_rootname
, ISC_FALSE
,
1381 if (result
!= ISC_R_SUCCESS
) {
1382 userzone
= NULL
; /* Lest it point to an invalid name */
1383 fprintf(stderr
, "could not parse zone name\n");
1384 return (STATUS_SYNTAX
);
1387 return (STATUS_MORE
);
1391 evaluate_class(char *cmdline
) {
1394 isc_result_t result
;
1395 dns_rdataclass_t rdclass
;
1397 word
= nsu_strsep(&cmdline
, " \t\r\n");
1399 fprintf(stderr
, "could not read class name\n");
1400 return (STATUS_SYNTAX
);
1404 r
.length
= strlen(word
);
1405 result
= dns_rdataclass_fromtext(&rdclass
, &r
);
1406 if (result
!= ISC_R_SUCCESS
) {
1407 fprintf(stderr
, "could not parse class name: %s\n", word
);
1408 return (STATUS_SYNTAX
);
1411 case dns_rdataclass_none
:
1412 case dns_rdataclass_any
:
1413 case dns_rdataclass_reserved0
:
1414 fprintf(stderr
, "bad default class: %s\n", word
);
1415 return (STATUS_SYNTAX
);
1417 defaultclass
= rdclass
;
1420 return (STATUS_MORE
);
1424 update_addordelete(char *cmdline
, isc_boolean_t isdelete
) {
1425 isc_result_t result
;
1426 dns_name_t
*name
= NULL
;
1429 dns_rdataclass_t rdataclass
;
1430 dns_rdatatype_t rdatatype
;
1431 dns_rdata_t
*rdata
= NULL
;
1432 dns_rdatalist_t
*rdatalist
= NULL
;
1433 dns_rdataset_t
*rdataset
= NULL
;
1434 isc_textregion_t region
;
1435 isc_uint16_t retval
;
1437 ddebug("update_addordelete()");
1440 * Read the owner name.
1442 retval
= parse_name(&cmdline
, updatemsg
, &name
);
1443 if (retval
!= STATUS_MORE
)
1446 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
1447 check_result(result
, "dns_message_gettemprdata");
1455 * If this is an add, read the TTL and verify that it's in range.
1456 * If it's a delete, ignore a TTL if present (for compatibility).
1458 word
= nsu_strsep(&cmdline
, " \t\r\n");
1461 fprintf(stderr
, "could not read owner ttl\n");
1466 rdataclass
= dns_rdataclass_any
;
1467 rdatatype
= dns_rdatatype_any
;
1468 rdata
->flags
= DNS_RDATA_UPDATE
;
1472 result
= isc_parse_uint32(&ttl
, word
, 10);
1473 if (result
!= ISC_R_SUCCESS
) {
1478 fprintf(stderr
, "ttl '%s': %s\n", word
,
1479 isc_result_totext(result
));
1486 else if (ttl
> TTL_MAX
) {
1487 fprintf(stderr
, "ttl '%s' is out of range (0 to %u)\n",
1493 * Read the class or type.
1495 word
= nsu_strsep(&cmdline
, " \t\r\n");
1499 rdataclass
= dns_rdataclass_any
;
1500 rdatatype
= dns_rdatatype_any
;
1501 rdata
->flags
= DNS_RDATA_UPDATE
;
1504 fprintf(stderr
, "could not read class or type\n");
1509 region
.length
= strlen(word
);
1510 rdataclass
= dns_rdataclass_any
;
1511 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
1512 if (result
== ISC_R_SUCCESS
&& rdataclass
!= dns_rdataclass_any
) {
1513 if (!setzoneclass(rdataclass
)) {
1514 fprintf(stderr
, "class mismatch: %s\n", word
);
1518 * Now read the type.
1520 word
= nsu_strsep(&cmdline
, " \t\r\n");
1523 rdataclass
= dns_rdataclass_any
;
1524 rdatatype
= dns_rdatatype_any
;
1525 rdata
->flags
= DNS_RDATA_UPDATE
;
1528 fprintf(stderr
, "could not read type\n");
1533 region
.length
= strlen(word
);
1534 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1535 if (result
!= ISC_R_SUCCESS
) {
1536 fprintf(stderr
, "'%s' is not a valid type: %s\n",
1537 word
, isc_result_totext(result
));
1541 rdataclass
= getzoneclass();
1542 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1543 if (result
!= ISC_R_SUCCESS
) {
1544 fprintf(stderr
, "'%s' is not a valid class or type: "
1545 "%s\n", word
, isc_result_totext(result
));
1550 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
, updatemsg
,
1552 if (retval
!= STATUS_MORE
)
1556 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0)
1557 rdataclass
= dns_rdataclass_any
;
1559 rdataclass
= dns_rdataclass_none
;
1561 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0) {
1562 fprintf(stderr
, "could not read rdata\n");
1569 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
1570 check_result(result
, "dns_message_gettemprdatalist");
1571 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1572 check_result(result
, "dns_message_gettemprdataset");
1573 dns_rdatalist_init(rdatalist
);
1574 rdatalist
->type
= rdatatype
;
1575 rdatalist
->rdclass
= rdataclass
;
1576 rdatalist
->covers
= rdatatype
;
1577 rdatalist
->ttl
= (dns_ttl_t
)ttl
;
1578 ISC_LIST_INIT(rdatalist
->rdata
);
1579 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1580 dns_rdataset_init(rdataset
);
1581 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1582 ISC_LIST_INIT(name
->list
);
1583 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1584 dns_message_addname(updatemsg
, name
, DNS_SECTION_UPDATE
);
1585 return (STATUS_MORE
);
1589 dns_message_puttempname(updatemsg
, &name
);
1590 dns_message_puttemprdata(updatemsg
, &rdata
);
1591 return (STATUS_SYNTAX
);
1595 evaluate_update(char *cmdline
) {
1597 isc_boolean_t isdelete
;
1599 ddebug("evaluate_update()");
1600 word
= nsu_strsep(&cmdline
, " \t\r\n");
1602 fprintf(stderr
, "could not read operation code\n");
1603 return (STATUS_SYNTAX
);
1605 if (strcasecmp(word
, "delete") == 0)
1606 isdelete
= ISC_TRUE
;
1607 else if (strcasecmp(word
, "add") == 0)
1608 isdelete
= ISC_FALSE
;
1610 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1611 return (STATUS_SYNTAX
);
1613 return (update_addordelete(cmdline
, isdelete
));
1617 setzone(dns_name_t
*zonename
) {
1618 isc_result_t result
;
1619 dns_name_t
*name
= NULL
;
1620 dns_rdataset_t
*rdataset
= NULL
;
1622 result
= dns_message_firstname(updatemsg
, DNS_SECTION_ZONE
);
1623 if (result
== ISC_R_SUCCESS
) {
1624 dns_message_currentname(updatemsg
, DNS_SECTION_ZONE
, &name
);
1625 dns_message_removename(updatemsg
, name
, DNS_SECTION_ZONE
);
1626 for (rdataset
= ISC_LIST_HEAD(name
->list
);
1628 rdataset
= ISC_LIST_HEAD(name
->list
)) {
1629 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
1630 dns_rdataset_disassociate(rdataset
);
1631 dns_message_puttemprdataset(updatemsg
, &rdataset
);
1633 dns_message_puttempname(updatemsg
, &name
);
1636 if (zonename
!= NULL
) {
1637 result
= dns_message_gettempname(updatemsg
, &name
);
1638 check_result(result
, "dns_message_gettempname");
1639 dns_name_init(name
, NULL
);
1640 dns_name_clone(zonename
, name
);
1641 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1642 check_result(result
, "dns_message_gettemprdataset");
1643 dns_rdataset_makequestion(rdataset
, getzoneclass(),
1645 ISC_LIST_INIT(name
->list
);
1646 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1647 dns_message_addname(updatemsg
, name
, DNS_SECTION_ZONE
);
1652 show_message(FILE *stream
, dns_message_t
*msg
, const char *description
) {
1653 isc_result_t result
;
1654 isc_buffer_t
*buf
= NULL
;
1657 ddebug("show_message()");
1663 if (bufsz
> MAXTEXT
) {
1664 fprintf(stderr
, "could not allocate large enough "
1665 "buffer to display message\n");
1669 isc_buffer_free(&buf
);
1670 result
= isc_buffer_allocate(mctx
, &buf
, bufsz
);
1671 check_result(result
, "isc_buffer_allocate");
1672 result
= dns_message_totext(msg
, style
, 0, buf
);
1674 } while (result
== ISC_R_NOSPACE
);
1675 if (result
!= ISC_R_SUCCESS
) {
1676 fprintf(stderr
, "could not convert message to text format.\n");
1677 isc_buffer_free(&buf
);
1680 fprintf(stream
, "%s\n%.*s", description
,
1681 (int)isc_buffer_usedlength(buf
), (char*)isc_buffer_base(buf
));
1682 isc_buffer_free(&buf
);
1687 get_next_command(void) {
1688 char cmdlinebuf
[MAXCMD
];
1692 ddebug("get_next_command()");
1694 fprintf(stdout
, "> ");
1698 cmdline
= fgets(cmdlinebuf
, MAXCMD
, input
);
1700 if (cmdline
== NULL
)
1701 return (STATUS_QUIT
);
1702 word
= nsu_strsep(&cmdline
, " \t\r\n");
1705 return (STATUS_QUIT
);
1707 return (STATUS_SEND
);
1709 return (STATUS_MORE
);
1710 if (strcasecmp(word
, "quit") == 0)
1711 return (STATUS_QUIT
);
1712 if (strcasecmp(word
, "prereq") == 0)
1713 return (evaluate_prereq(cmdline
));
1714 if (strcasecmp(word
, "update") == 0)
1715 return (evaluate_update(cmdline
));
1716 if (strcasecmp(word
, "server") == 0)
1717 return (evaluate_server(cmdline
));
1718 if (strcasecmp(word
, "local") == 0)
1719 return (evaluate_local(cmdline
));
1720 if (strcasecmp(word
, "zone") == 0)
1721 return (evaluate_zone(cmdline
));
1722 if (strcasecmp(word
, "class") == 0)
1723 return (evaluate_class(cmdline
));
1724 if (strcasecmp(word
, "send") == 0)
1725 return (STATUS_SEND
);
1726 if (strcasecmp(word
, "show") == 0) {
1727 show_message(stdout
, updatemsg
, "Outgoing update query:");
1728 return (STATUS_MORE
);
1730 if (strcasecmp(word
, "answer") == 0) {
1732 show_message(stdout
, answer
, "Answer:");
1733 return (STATUS_MORE
);
1735 if (strcasecmp(word
, "key") == 0) {
1736 usegsstsig
= ISC_FALSE
;
1737 return (evaluate_key(cmdline
));
1739 if (strcasecmp(word
, "gsstsig") == 0) {
1741 usegsstsig
= ISC_TRUE
;
1742 use_win2k_gsstsig
= ISC_FALSE
;
1744 fprintf(stderr
, "gsstsig not supported\n");
1746 return (STATUS_MORE
);
1748 if (strcasecmp(word
, "oldgsstsig") == 0) {
1750 usegsstsig
= ISC_TRUE
;
1751 use_win2k_gsstsig
= ISC_TRUE
;
1753 fprintf(stderr
, "gsstsig not supported\n");
1755 return (STATUS_MORE
);
1757 if (strcasecmp(word
, "help") == 0) {
1759 "local address [port] (set local resolver)\n"
1760 "server address [port] (set master server for zone)\n"
1761 "send (send the update request)\n"
1762 "show (show the update request)\n"
1763 "answer (show the answer to the last request)\n"
1764 "quit (quit, any pending update is not sent\n"
1765 "help (display this message_\n"
1766 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1767 "gsstsig (use GSS_TSIG to sign the request)\n"
1768 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1769 "zone name (set the zone to be updated)\n"
1770 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1771 "prereq nxdomain name (does this name not exist)\n"
1772 "prereq yxdomain name (does this name exist)\n"
1773 "prereq nxrrset .... (does this RRset exist)\n"
1774 "prereq yxrrset .... (does this RRset not exist)\n"
1775 "update add .... (add the given record to the zone)\n"
1776 "update delete .... (remove the given record(s) from the zone)\n");
1777 return (STATUS_MORE
);
1779 fprintf(stderr
, "incorrect section name: %s\n", word
);
1780 return (STATUS_SYNTAX
);
1783 static isc_boolean_t
1784 user_interaction(void) {
1785 isc_uint16_t result
= STATUS_MORE
;
1787 ddebug("user_interaction()");
1788 while ((result
== STATUS_MORE
) || (result
== STATUS_SYNTAX
)) {
1789 result
= get_next_command();
1790 if (!interactive
&& result
== STATUS_SYNTAX
)
1791 fatal("syntax error");
1793 if (result
== STATUS_SEND
)
1801 isc_event_t
*event
= global_event
;
1802 ddebug("done_update()");
1803 isc_task_send(global_task
, &event
);
1807 check_tsig_error(dns_rdataset_t
*rdataset
, isc_buffer_t
*b
) {
1808 isc_result_t result
;
1809 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1810 dns_rdata_any_tsig_t tsig
;
1812 result
= dns_rdataset_first(rdataset
);
1813 check_result(result
, "dns_rdataset_first");
1814 dns_rdataset_current(rdataset
, &rdata
);
1815 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
1816 check_result(result
, "dns_rdata_tostruct");
1817 if (tsig
.error
!= 0) {
1818 if (isc_buffer_remaininglength(b
) < 1)
1819 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1820 isc__buffer_putstr(b
, "(" /*)*/);
1821 result
= dns_tsigrcode_totext(tsig
.error
, b
);
1822 check_result(result
, "dns_tsigrcode_totext");
1823 if (isc_buffer_remaininglength(b
) < 1)
1824 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1825 isc__buffer_putstr(b
, /*(*/ ")");
1830 update_completed(isc_task_t
*task
, isc_event_t
*event
) {
1831 dns_requestevent_t
*reqev
= NULL
;
1832 isc_result_t result
;
1833 dns_request_t
*request
;
1837 ddebug("update_completed()");
1841 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1842 reqev
= (dns_requestevent_t
*)event
;
1843 request
= reqev
->request
;
1846 dns_request_destroy(&request
);
1847 isc_event_free(&event
);
1852 if (reqev
->result
!= ISC_R_SUCCESS
) {
1853 fprintf(stderr
, "; Communication with server failed: %s\n",
1854 isc_result_totext(reqev
->result
));
1855 seenerror
= ISC_TRUE
;
1859 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &answer
);
1860 check_result(result
, "dns_message_create");
1861 result
= dns_request_getresponse(request
, answer
,
1862 DNS_MESSAGEPARSE_PRESERVEORDER
);
1865 if (answer
->verify_attempted
)
1866 ddebug("tsig verification successful");
1868 case DNS_R_CLOCKSKEW
:
1869 case DNS_R_EXPECTEDTSIG
:
1870 case DNS_R_TSIGERRORSET
:
1871 case DNS_R_TSIGVERIFYFAILURE
:
1872 case DNS_R_UNEXPECTEDTSIG
:
1875 if (usegsstsig
&& answer
->rcode
== dns_rcode_noerror
) {
1877 * For MS DNS that violates RFC 2845, section 4.2
1882 fprintf(stderr
, "; TSIG error with server: %s\n",
1883 isc_result_totext(result
));
1884 seenerror
= ISC_TRUE
;
1887 check_result(result
, "dns_request_getresponse");
1890 if (answer
->rcode
!= dns_rcode_noerror
) {
1891 seenerror
= ISC_TRUE
;
1895 dns_rdataset_t
*rds
;
1897 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
1898 result
= dns_rcode_totext(answer
->rcode
, &b
);
1899 check_result(result
, "dns_rcode_totext");
1900 rds
= dns_message_gettsig(answer
, NULL
);
1902 check_tsig_error(rds
, &b
);
1903 fprintf(stderr
, "update failed: %.*s\n",
1904 (int)isc_buffer_usedlength(&b
), buf
);
1908 show_message(stderr
, answer
, "\nReply from update query:");
1911 dns_request_destroy(&request
);
1913 dns_name_free(&tmpzonename
, mctx
);
1914 dns_name_free(&restart_master
, mctx
);
1916 isc_event_free(&event
);
1921 send_update(dns_name_t
*zonename
, isc_sockaddr_t
*master
,
1922 isc_sockaddr_t
*srcaddr
)
1924 isc_result_t result
;
1925 dns_request_t
*request
= NULL
;
1926 unsigned int options
= 0;
1928 ddebug("send_update()");
1933 options
|= DNS_REQUESTOPT_TCP
;
1934 if (tsigkey
== NULL
&& sig0key
!= NULL
) {
1935 result
= dns_message_setsig0key(updatemsg
, sig0key
);
1936 check_result(result
, "dns_message_setsig0key");
1939 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
1941 isc_sockaddr_format(master
, addrbuf
, sizeof(addrbuf
));
1942 fprintf(stderr
, "Sending update to %s\n", addrbuf
);
1945 result
= dns_request_createvia3(requestmgr
, updatemsg
, srcaddr
,
1946 master
, options
, tsigkey
, timeout
,
1947 udp_timeout
, udp_retries
, global_task
,
1948 update_completed
, NULL
, &request
);
1949 check_result(result
, "dns_request_createvia3");
1952 show_message(stdout
, updatemsg
, "Outgoing update query:");
1958 recvsoa(isc_task_t
*task
, isc_event_t
*event
) {
1959 dns_requestevent_t
*reqev
= NULL
;
1960 dns_request_t
*request
= NULL
;
1961 isc_result_t result
, eresult
;
1962 dns_message_t
*rcvmsg
= NULL
;
1963 dns_section_t section
;
1964 dns_name_t
*name
= NULL
;
1965 dns_rdataset_t
*soaset
= NULL
;
1966 dns_rdata_soa_t soa
;
1967 dns_rdata_t soarr
= DNS_RDATA_INIT
;
1970 nsu_requestinfo_t
*reqinfo
;
1971 dns_message_t
*soaquery
= NULL
;
1972 isc_sockaddr_t
*addr
;
1973 isc_boolean_t seencname
= ISC_FALSE
;
1975 unsigned int nlabels
;
1979 ddebug("recvsoa()");
1983 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1984 reqev
= (dns_requestevent_t
*)event
;
1985 request
= reqev
->request
;
1986 eresult
= reqev
->result
;
1987 reqinfo
= reqev
->ev_arg
;
1988 soaquery
= reqinfo
->msg
;
1989 addr
= reqinfo
->addr
;
1992 dns_request_destroy(&request
);
1993 dns_message_destroy(&soaquery
);
1994 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
1995 isc_event_free(&event
);
2000 if (eresult
!= ISC_R_SUCCESS
) {
2001 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2003 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
2004 fprintf(stderr
, "; Communication with %s failed: %s\n",
2005 addrbuf
, isc_result_totext(eresult
));
2006 if (userserver
!= NULL
)
2007 fatal("could not talk to specified name server");
2008 else if (++ns_inuse
>= lwconf
->nsnext
)
2009 fatal("could not talk to any default name server");
2010 ddebug("Destroying request [%p]", request
);
2011 dns_request_destroy(&request
);
2012 dns_message_renderreset(soaquery
);
2013 dns_message_settsigkey(soaquery
, NULL
);
2014 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2015 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
2016 isc_event_free(&event
);
2017 setzoneclass(dns_rdataclass_none
);
2021 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
2023 isc_event_free(&event
);
2026 ddebug("About to create rcvmsg");
2027 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
2028 check_result(result
, "dns_message_create");
2029 result
= dns_request_getresponse(request
, rcvmsg
,
2030 DNS_MESSAGEPARSE_PRESERVEORDER
);
2031 if (result
== DNS_R_TSIGERRORSET
&& userserver
!= NULL
) {
2032 dns_message_destroy(&rcvmsg
);
2033 ddebug("Destroying request [%p]", request
);
2034 dns_request_destroy(&request
);
2035 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
2036 if (reqinfo
== NULL
)
2037 fatal("out of memory");
2038 reqinfo
->msg
= soaquery
;
2039 reqinfo
->addr
= addr
;
2040 dns_message_renderreset(soaquery
);
2041 ddebug("retrying soa request without TSIG");
2042 result
= dns_request_createvia3(requestmgr
, soaquery
,
2043 localaddr
, addr
, 0, NULL
,
2046 global_task
, recvsoa
, reqinfo
,
2048 check_result(result
, "dns_request_createvia");
2052 check_result(result
, "dns_request_getresponse");
2053 section
= DNS_SECTION_ANSWER
;
2055 show_message(stderr
, rcvmsg
, "Reply from SOA query:");
2057 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
2058 rcvmsg
->rcode
!= dns_rcode_nxdomain
)
2059 fatal("response to SOA query was unsuccessful");
2061 if (userzone
!= NULL
&& rcvmsg
->rcode
== dns_rcode_nxdomain
) {
2062 char namebuf
[DNS_NAME_FORMATSIZE
];
2063 dns_name_format(userzone
, namebuf
, sizeof(namebuf
));
2064 error("specified zone '%s' does not exist (NXDOMAIN)",
2066 dns_message_destroy(&rcvmsg
);
2067 dns_request_destroy(&request
);
2068 dns_message_destroy(&soaquery
);
2069 ddebug("Out of recvsoa");
2076 section
= DNS_SECTION_ANSWER
;
2078 section
= DNS_SECTION_AUTHORITY
;
2082 result
= dns_message_firstname(rcvmsg
, section
);
2083 if (result
!= ISC_R_SUCCESS
) {
2087 while (result
== ISC_R_SUCCESS
) {
2089 dns_message_currentname(rcvmsg
, section
, &name
);
2091 result
= dns_message_findtype(name
, dns_rdatatype_soa
, 0,
2093 if (result
== ISC_R_SUCCESS
)
2095 if (section
== DNS_SECTION_ANSWER
) {
2096 dns_rdataset_t
*tset
= NULL
;
2097 if (dns_message_findtype(name
, dns_rdatatype_cname
, 0,
2098 &tset
) == ISC_R_SUCCESS
||
2099 dns_message_findtype(name
, dns_rdatatype_dname
, 0,
2100 &tset
) == ISC_R_SUCCESS
) {
2101 seencname
= ISC_TRUE
;
2106 result
= dns_message_nextname(rcvmsg
, section
);
2109 if (soaset
== NULL
&& !seencname
) {
2118 char namestr
[DNS_NAME_FORMATSIZE
];
2119 dns_name_format(name
, namestr
, sizeof(namestr
));
2120 fprintf(stderr
, "Found zone name: %s\n", namestr
);
2123 result
= dns_rdataset_first(soaset
);
2124 check_result(result
, "dns_rdataset_first");
2126 dns_rdata_init(&soarr
);
2127 dns_rdataset_current(soaset
, &soarr
);
2128 result
= dns_rdata_tostruct(&soarr
, &soa
, NULL
);
2129 check_result(result
, "dns_rdata_tostruct");
2131 dns_name_init(&master
, NULL
);
2132 dns_name_clone(&soa
.origin
, &master
);
2134 if (userzone
!= NULL
)
2135 zonename
= userzone
;
2140 char namestr
[DNS_NAME_FORMATSIZE
];
2141 dns_name_format(&master
, namestr
, sizeof(namestr
));
2142 fprintf(stderr
, "The master is: %s\n", namestr
);
2145 if (userserver
!= NULL
)
2146 serveraddr
= userserver
;
2148 char serverstr
[DNS_NAME_MAXTEXT
+1];
2151 isc_buffer_init(&buf
, serverstr
, sizeof(serverstr
));
2152 result
= dns_name_totext(&master
, ISC_TRUE
, &buf
);
2153 check_result(result
, "dns_name_totext");
2154 serverstr
[isc_buffer_usedlength(&buf
)] = 0;
2155 get_address(serverstr
, DNSDEFAULTPORT
, &tempaddr
);
2156 serveraddr
= &tempaddr
;
2158 dns_rdata_freestruct(&soa
);
2162 dns_name_init(&tmpzonename
, NULL
);
2163 dns_name_dup(zonename
, mctx
, &tmpzonename
);
2164 dns_name_init(&restart_master
, NULL
);
2165 dns_name_dup(&master
, mctx
, &restart_master
);
2166 start_gssrequest(&master
);
2168 send_update(zonename
, serveraddr
, localaddr
);
2169 setzoneclass(dns_rdataclass_none
);
2172 send_update(zonename
, serveraddr
, localaddr
);
2173 setzoneclass(dns_rdataclass_none
);
2176 dns_message_destroy(&soaquery
);
2177 dns_request_destroy(&request
);
2180 dns_message_destroy(&rcvmsg
);
2181 ddebug("Out of recvsoa");
2185 result
= dns_message_firstname(soaquery
, DNS_SECTION_QUESTION
);
2186 INSIST(result
== ISC_R_SUCCESS
);
2188 dns_message_currentname(soaquery
, DNS_SECTION_QUESTION
, &name
);
2189 nlabels
= dns_name_countlabels(name
);
2191 fatal("could not find enclosing zone");
2192 dns_name_init(&tname
, NULL
);
2193 dns_name_getlabelsequence(name
, 1, nlabels
- 1, &tname
);
2194 dns_name_clone(&tname
, name
);
2195 dns_request_destroy(&request
);
2196 dns_message_renderreset(soaquery
);
2197 dns_message_settsigkey(soaquery
, NULL
);
2198 if (userserver
!= NULL
)
2199 sendrequest(localaddr
, userserver
, soaquery
, &request
);
2201 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2206 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
2207 dns_message_t
*msg
, dns_request_t
**request
)
2209 isc_result_t result
;
2210 nsu_requestinfo_t
*reqinfo
;
2212 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
2213 if (reqinfo
== NULL
)
2214 fatal("out of memory");
2216 reqinfo
->addr
= destaddr
;
2217 result
= dns_request_createvia3(requestmgr
, msg
, srcaddr
, destaddr
, 0,
2218 (userserver
!= NULL
) ? tsigkey
: NULL
,
2219 FIND_TIMEOUT
* 20, FIND_TIMEOUT
, 3,
2220 global_task
, recvsoa
, reqinfo
, request
);
2221 check_result(result
, "dns_request_createvia");
2227 start_gssrequest(dns_name_t
*master
)
2229 gss_ctx_id_t context
;
2231 isc_result_t result
;
2232 isc_uint32_t val
= 0;
2233 dns_message_t
*rmsg
;
2234 dns_request_t
*request
= NULL
;
2235 dns_name_t
*servname
;
2236 dns_fixedname_t fname
;
2237 char namestr
[DNS_NAME_FORMATSIZE
];
2238 char keystr
[DNS_NAME_FORMATSIZE
];
2240 debug("start_gssrequest");
2243 if (gssring
!= NULL
)
2244 dns_tsigkeyring_destroy(&gssring
);
2246 result
= dns_tsigkeyring_create(mctx
, &gssring
);
2248 if (result
!= ISC_R_SUCCESS
)
2249 fatal("dns_tsigkeyring_create failed: %s",
2250 isc_result_totext(result
));
2252 dns_name_format(master
, namestr
, sizeof(namestr
));
2253 if (kserver
== NULL
) {
2254 kserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
2255 if (kserver
== NULL
)
2256 fatal("out of memory");
2258 if (userserver
== NULL
)
2259 get_address(namestr
, DNSDEFAULTPORT
, kserver
);
2261 (void)memcpy(kserver
, userserver
, sizeof(isc_sockaddr_t
));
2263 dns_fixedname_init(&fname
);
2264 servname
= dns_fixedname_name(&fname
);
2266 result
= isc_string_printf(servicename
, sizeof(servicename
),
2268 if (result
!= ISC_R_SUCCESS
)
2269 fatal("isc_string_printf(servicename) failed: %s",
2270 isc_result_totext(result
));
2271 isc_buffer_init(&buf
, servicename
, strlen(servicename
));
2272 isc_buffer_add(&buf
, strlen(servicename
));
2273 result
= dns_name_fromtext(servname
, &buf
, dns_rootname
,
2275 if (result
!= ISC_R_SUCCESS
)
2276 fatal("dns_name_fromtext(servname) failed: %s",
2277 isc_result_totext(result
));
2279 dns_fixedname_init(&fkname
);
2280 keyname
= dns_fixedname_name(&fkname
);
2282 isc_random_get(&val
);
2283 result
= isc_string_printf(keystr
, sizeof(keystr
), "%u.sig-%s",
2285 if (result
!= ISC_R_SUCCESS
)
2286 fatal("isc_string_printf(keystr) failed: %s",
2287 isc_result_totext(result
));
2288 isc_buffer_init(&buf
, keystr
, strlen(keystr
));
2289 isc_buffer_add(&buf
, strlen(keystr
));
2291 result
= dns_name_fromtext(keyname
, &buf
, dns_rootname
,
2293 if (result
!= ISC_R_SUCCESS
)
2294 fatal("dns_name_fromtext(keyname) failed: %s",
2295 isc_result_totext(result
));
2297 /* Windows doesn't recognize name compression in the key name. */
2298 keyname
->attributes
|= DNS_NAMEATTR_NOCOMPRESS
;
2301 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &rmsg
);
2302 if (result
!= ISC_R_SUCCESS
)
2303 fatal("dns_message_create failed: %s",
2304 isc_result_totext(result
));
2306 /* Build first request. */
2308 context
= GSS_C_NO_CONTEXT
;
2309 result
= dns_tkey_buildgssquery(rmsg
, keyname
, servname
, NULL
, 0,
2310 &context
, use_win2k_gsstsig
);
2311 if (result
== ISC_R_FAILURE
)
2312 fatal("Check your Kerberos ticket, it may have expired.");
2313 if (result
!= ISC_R_SUCCESS
)
2314 fatal("dns_tkey_buildgssquery failed: %s",
2315 isc_result_totext(result
));
2317 send_gssrequest(localaddr
, kserver
, rmsg
, &request
, context
);
2321 send_gssrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
2322 dns_message_t
*msg
, dns_request_t
**request
,
2323 gss_ctx_id_t context
)
2325 isc_result_t result
;
2326 nsu_gssinfo_t
*reqinfo
;
2327 unsigned int options
= 0;
2329 debug("send_gssrequest");
2330 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_gssinfo_t
));
2331 if (reqinfo
== NULL
)
2332 fatal("out of memory");
2334 reqinfo
->addr
= destaddr
;
2335 reqinfo
->context
= context
;
2337 options
|= DNS_REQUESTOPT_TCP
;
2338 result
= dns_request_createvia3(requestmgr
, msg
, srcaddr
, destaddr
,
2339 options
, tsigkey
, FIND_TIMEOUT
* 20,
2340 FIND_TIMEOUT
, 3, global_task
, recvgss
,
2342 check_result(result
, "dns_request_createvia3");
2344 show_message(stdout
, msg
, "Outgoing update query:");
2349 recvgss(isc_task_t
*task
, isc_event_t
*event
) {
2350 dns_requestevent_t
*reqev
= NULL
;
2351 dns_request_t
*request
= NULL
;
2352 isc_result_t result
, eresult
;
2353 dns_message_t
*rcvmsg
= NULL
;
2354 nsu_gssinfo_t
*reqinfo
;
2355 dns_message_t
*tsigquery
= NULL
;
2356 isc_sockaddr_t
*addr
;
2357 gss_ctx_id_t context
;
2359 dns_name_t
*servname
;
2360 dns_fixedname_t fname
;
2364 ddebug("recvgss()");
2368 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
2369 reqev
= (dns_requestevent_t
*)event
;
2370 request
= reqev
->request
;
2371 eresult
= reqev
->result
;
2372 reqinfo
= reqev
->ev_arg
;
2373 tsigquery
= reqinfo
->msg
;
2374 context
= reqinfo
->context
;
2375 addr
= reqinfo
->addr
;
2378 dns_request_destroy(&request
);
2379 dns_message_destroy(&tsigquery
);
2380 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2381 isc_event_free(&event
);
2386 if (eresult
!= ISC_R_SUCCESS
) {
2387 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2389 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
2390 fprintf(stderr
, "; Communication with %s failed: %s\n",
2391 addrbuf
, isc_result_totext(eresult
));
2392 if (userserver
!= NULL
)
2393 fatal("could not talk to specified name server");
2394 else if (++ns_inuse
>= lwconf
->nsnext
)
2395 fatal("could not talk to any default name server");
2396 ddebug("Destroying request [%p]", request
);
2397 dns_request_destroy(&request
);
2398 dns_message_renderreset(tsigquery
);
2399 sendrequest(localaddr
, &servers
[ns_inuse
], tsigquery
,
2401 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2402 isc_event_free(&event
);
2405 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2407 isc_event_free(&event
);
2410 ddebug("recvgss creating rcvmsg");
2411 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
2412 check_result(result
, "dns_message_create");
2414 result
= dns_request_getresponse(request
, rcvmsg
,
2415 DNS_MESSAGEPARSE_PRESERVEORDER
);
2416 check_result(result
, "dns_request_getresponse");
2419 show_message(stderr
, rcvmsg
,
2420 "recvmsg reply from GSS-TSIG query");
2422 if (rcvmsg
->rcode
== dns_rcode_formerr
&& !tried_other_gsstsig
) {
2423 ddebug("recvgss trying %s GSS-TSIG",
2424 use_win2k_gsstsig
? "Standard" : "Win2k");
2425 if (use_win2k_gsstsig
)
2426 use_win2k_gsstsig
= ISC_FALSE
;
2428 use_win2k_gsstsig
= ISC_TRUE
;
2429 tried_other_gsstsig
= ISC_TRUE
;
2430 start_gssrequest(&restart_master
);
2434 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
2435 rcvmsg
->rcode
!= dns_rcode_nxdomain
)
2436 fatal("response to GSS-TSIG query was unsuccessful");
2439 dns_fixedname_init(&fname
);
2440 servname
= dns_fixedname_name(&fname
);
2441 isc_buffer_init(&buf
, servicename
, strlen(servicename
));
2442 isc_buffer_add(&buf
, strlen(servicename
));
2443 result
= dns_name_fromtext(servname
, &buf
, dns_rootname
,
2445 check_result(result
, "dns_name_fromtext");
2448 result
= dns_tkey_gssnegotiate(tsigquery
, rcvmsg
, servname
,
2449 &context
, &tsigkey
, gssring
,
2453 case DNS_R_CONTINUE
:
2454 send_gssrequest(localaddr
, kserver
, tsigquery
, &request
,
2460 * XXXSRA Waaay too much fun here. There's no good
2461 * reason why we need a TSIG here (the people who put
2462 * it into the spec admitted at the time that it was
2463 * not a security issue), and Windows clients don't
2464 * seem to work if named complies with the spec and
2465 * includes the gratuitous TSIG. So we're in the
2466 * bizarre situation of having to choose between
2467 * complying with a useless requirement in the spec
2468 * and interoperating. This is nuts. If we can
2469 * confirm this behavior, we should ask the WG to
2470 * consider removing the requirement for the
2471 * gratuitous TSIG here. For the moment, we ignore
2472 * the TSIG -- this too is a spec violation, but it's
2473 * the least insane thing to do.
2477 * Verify the signature.
2479 rcvmsg
->state
= DNS_SECTION_ANY
;
2480 dns_message_setquerytsig(rcvmsg
, NULL
);
2481 result
= dns_message_settsigkey(rcvmsg
, tsigkey
);
2482 check_result(result
, "dns_message_settsigkey");
2483 result
= dns_message_checksig(rcvmsg
, NULL
);
2484 ddebug("tsig verification: %s", dns_result_totext(result
));
2485 check_result(result
, "dns_message_checksig");
2488 send_update(&tmpzonename
, serveraddr
, localaddr
);
2489 setzoneclass(dns_rdataclass_none
);
2493 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result
));
2497 dns_request_destroy(&request
);
2498 dns_message_destroy(&tsigquery
);
2500 dns_message_destroy(&rcvmsg
);
2501 ddebug("Out of recvgss");
2506 start_update(void) {
2507 isc_result_t result
;
2508 dns_rdataset_t
*rdataset
= NULL
;
2509 dns_name_t
*name
= NULL
;
2510 dns_request_t
*request
= NULL
;
2511 dns_message_t
*soaquery
= NULL
;
2512 dns_name_t
*firstname
;
2513 dns_section_t section
= DNS_SECTION_UPDATE
;
2515 ddebug("start_update()");
2518 dns_message_destroy(&answer
);
2520 if (userzone
!= NULL
&& userserver
!= NULL
&& ! usegsstsig
) {
2521 send_update(userzone
, userserver
, localaddr
);
2522 setzoneclass(dns_rdataclass_none
);
2526 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
2528 check_result(result
, "dns_message_create");
2530 if (userserver
== NULL
)
2531 soaquery
->flags
|= DNS_MESSAGEFLAG_RD
;
2533 result
= dns_message_gettempname(soaquery
, &name
);
2534 check_result(result
, "dns_message_gettempname");
2536 result
= dns_message_gettemprdataset(soaquery
, &rdataset
);
2537 check_result(result
, "dns_message_gettemprdataset");
2539 dns_rdataset_makequestion(rdataset
, getzoneclass(), dns_rdatatype_soa
);
2541 if (userzone
!= NULL
) {
2542 dns_name_init(name
, NULL
);
2543 dns_name_clone(userzone
, name
);
2545 result
= dns_message_firstname(updatemsg
, section
);
2546 if (result
== ISC_R_NOMORE
) {
2547 section
= DNS_SECTION_PREREQUISITE
;
2548 result
= dns_message_firstname(updatemsg
, section
);
2550 if (result
!= ISC_R_SUCCESS
) {
2551 dns_message_puttempname(soaquery
, &name
);
2552 dns_rdataset_disassociate(rdataset
);
2553 dns_message_puttemprdataset(soaquery
, &rdataset
);
2554 dns_message_destroy(&soaquery
);
2559 dns_message_currentname(updatemsg
, section
, &firstname
);
2560 dns_name_init(name
, NULL
);
2561 dns_name_clone(firstname
, name
);
2564 ISC_LIST_INIT(name
->list
);
2565 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
2566 dns_message_addname(soaquery
, name
, DNS_SECTION_QUESTION
);
2568 if (userserver
!= NULL
)
2569 sendrequest(localaddr
, userserver
, soaquery
, &request
);
2572 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2578 ddebug("cleanup()");
2581 dns_message_destroy(&answer
);
2584 if (tsigkey
!= NULL
) {
2585 ddebug("detach tsigkey x%p", tsigkey
);
2586 dns_tsigkey_detach(&tsigkey
);
2588 if (gssring
!= NULL
) {
2589 ddebug("Destroying GSS-TSIG keyring");
2590 dns_tsigkeyring_destroy(&gssring
);
2592 if (kserver
!= NULL
) {
2593 isc_mem_put(mctx
, kserver
, sizeof(isc_sockaddr_t
));
2598 ddebug("Shutting down task manager");
2599 isc_taskmgr_destroy(&taskmgr
);
2601 ddebug("Destroying event");
2602 isc_event_free(&global_event
);
2604 ddebug("Shutting down socket manager");
2605 isc_socketmgr_destroy(&socketmgr
);
2607 ddebug("Shutting down timer manager");
2608 isc_timermgr_destroy(&timermgr
);
2610 ddebug("Destroying hash context");
2613 ddebug("Destroying name state");
2616 ddebug("Removing log context");
2617 isc_log_destroy(&lctx
);
2619 ddebug("Destroying memory context");
2621 isc_mem_stats(mctx
, stderr
);
2622 isc_mem_destroy(&mctx
);
2626 getinput(isc_task_t
*task
, isc_event_t
*event
) {
2636 if (global_event
== NULL
)
2637 global_event
= event
;
2640 more
= user_interaction();
2650 main(int argc
, char **argv
) {
2651 isc_result_t result
;
2652 style
= &dns_master_style_debug
;
2656 interactive
= ISC_TF(isatty(0));
2660 pre_parse_args(argc
, argv
);
2662 result
= isc_mem_create(0, 0, &mctx
);
2663 check_result(result
, "isc_mem_create");
2665 parse_args(argc
, argv
, mctx
, &entropy
);
2669 result
= isc_app_onrun(mctx
, global_task
, getinput
, NULL
);
2670 check_result(result
, "isc_app_onrun");
2672 (void)isc_app_run();