4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: nsupdate.c,v 1.173 2009/09/29 15:06:06 fdupont Exp */
33 #include <isc/base64.h>
34 #include <isc/buffer.h>
35 #include <isc/commandline.h>
36 #include <isc/entropy.h>
37 #include <isc/event.h>
43 #include <isc/parseint.h>
44 #include <isc/print.h>
45 #include <isc/random.h>
46 #include <isc/region.h>
47 #include <isc/sockaddr.h>
48 #include <isc/socket.h>
49 #include <isc/stdio.h>
50 #include <isc/string.h>
52 #include <isc/timer.h>
53 #include <isc/types.h>
56 #include <isccfg/namedconf.h>
58 #include <dns/callbacks.h>
59 #include <dns/dispatch.h>
60 #include <dns/dnssec.h>
61 #include <dns/events.h>
62 #include <dns/fixedname.h>
64 #include <dns/masterdump.h>
65 #include <dns/message.h>
67 #include <dns/rcode.h>
68 #include <dns/rdata.h>
69 #include <dns/rdataclass.h>
70 #include <dns/rdatalist.h>
71 #include <dns/rdataset.h>
72 #include <dns/rdatastruct.h>
73 #include <dns/rdatatype.h>
74 #include <dns/request.h>
75 #include <dns/result.h>
81 #include <lwres/lwres.h>
82 #include <lwres/net.h>
85 #include <dst/gssapi.h>
87 #include <bind9/getaddresses.h>
91 #ifdef HAVE_GETADDRINFO
92 #ifdef HAVE_GAISTRERROR
93 #define USE_GETADDRINFO
98 #ifndef USE_GETADDRINFO
99 #ifndef ISC_PLATFORM_NONSTDHERRNO
104 #define MAXCMD (4 * 1024)
105 #define MAXWIRE (64 * 1024)
106 #define PACKETSIZE ((64 * 1024) - 1)
107 #define INITTEXT (2 * 1024)
108 #define MAXTEXT (128 * 1024)
109 #define FIND_TIMEOUT 5
110 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
112 #define DNSDEFAULTPORT 53
114 static isc_uint16_t dnsport
= DNSDEFAULTPORT
;
117 #define RESOLV_CONF "/etc/resolv.conf"
120 static isc_boolean_t debugging
= ISC_FALSE
, ddebugging
= ISC_FALSE
;
121 static isc_boolean_t memdebugging
= ISC_FALSE
;
122 static isc_boolean_t have_ipv4
= ISC_FALSE
;
123 static isc_boolean_t have_ipv6
= ISC_FALSE
;
124 static isc_boolean_t is_dst_up
= ISC_FALSE
;
125 static isc_boolean_t usevc
= ISC_FALSE
;
126 static isc_boolean_t usegsstsig
= ISC_FALSE
;
127 static isc_boolean_t use_win2k_gsstsig
= ISC_FALSE
;
128 static isc_boolean_t tried_other_gsstsig
= ISC_FALSE
;
129 static isc_boolean_t local_only
= ISC_FALSE
;
130 static isc_taskmgr_t
*taskmgr
= NULL
;
131 static isc_task_t
*global_task
= NULL
;
132 static isc_event_t
*global_event
= NULL
;
133 static isc_log_t
*lctx
= NULL
;
134 static isc_mem_t
*mctx
= NULL
;
135 static dns_dispatchmgr_t
*dispatchmgr
= NULL
;
136 static dns_requestmgr_t
*requestmgr
= NULL
;
137 static isc_socketmgr_t
*socketmgr
= NULL
;
138 static isc_timermgr_t
*timermgr
= NULL
;
139 static dns_dispatch_t
*dispatchv4
= NULL
;
140 static dns_dispatch_t
*dispatchv6
= NULL
;
141 static dns_message_t
*updatemsg
= NULL
;
142 static dns_fixedname_t fuserzone
;
143 static dns_name_t
*userzone
= NULL
;
144 static dns_name_t
*zonename
= NULL
;
145 static dns_name_t tmpzonename
;
146 static dns_name_t restart_master
;
147 static dns_tsig_keyring_t
*gssring
= NULL
;
148 static dns_tsigkey_t
*tsigkey
= NULL
;
149 static dst_key_t
*sig0key
;
150 static lwres_context_t
*lwctx
= NULL
;
151 static lwres_conf_t
*lwconf
;
152 static isc_sockaddr_t
*servers
;
153 static int ns_inuse
= 0;
154 static int ns_total
= 0;
155 static isc_sockaddr_t
*userserver
= NULL
;
156 static isc_sockaddr_t
*localaddr
= NULL
;
157 static isc_sockaddr_t
*serveraddr
= NULL
;
158 static isc_sockaddr_t tempaddr
;
159 static const char *keyfile
= NULL
;
160 static char *keystr
= NULL
;
161 static isc_entropy_t
*entropy
= NULL
;
162 static isc_boolean_t shuttingdown
= ISC_FALSE
;
164 static isc_boolean_t interactive
= ISC_TRUE
;
165 static isc_boolean_t seenerror
= ISC_FALSE
;
166 static const dns_master_style_t
*style
;
167 static int requests
= 0;
168 static unsigned int logdebuglevel
= 0;
169 static unsigned int timeout
= 300;
170 static unsigned int udp_timeout
= 3;
171 static unsigned int udp_retries
= 3;
172 static dns_rdataclass_t defaultclass
= dns_rdataclass_in
;
173 static dns_rdataclass_t zoneclass
= dns_rdataclass_none
;
174 static dns_message_t
*answer
= NULL
;
175 static isc_uint32_t default_ttl
= 0;
176 static isc_boolean_t default_ttl_set
= ISC_FALSE
;
178 typedef struct nsu_requestinfo
{
180 isc_sockaddr_t
*addr
;
184 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
185 dns_message_t
*msg
, dns_request_t
**request
);
187 ISC_PLATFORM_NORETURN_PRE
static void
188 fatal(const char *format
, ...)
189 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST
;
192 debug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
195 ddebug(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
198 static dns_fixedname_t fkname
;
199 static isc_sockaddr_t
*kserver
= NULL
;
200 static char servicename
[DNS_NAME_FORMATSIZE
];
201 static dns_name_t
*keyname
;
202 typedef struct nsu_gssinfo
{
204 isc_sockaddr_t
*addr
;
205 gss_ctx_id_t context
;
209 start_gssrequest(dns_name_t
*master
);
211 send_gssrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
212 dns_message_t
*msg
, dns_request_t
**request
,
213 gss_ctx_id_t context
);
215 recvgss(isc_task_t
*task
, isc_event_t
*event
);
219 error(const char *format
, ...) ISC_FORMAT_PRINTF(1, 2);
221 #define STATUS_MORE (isc_uint16_t)0
222 #define STATUS_SEND (isc_uint16_t)1
223 #define STATUS_QUIT (isc_uint16_t)2
224 #define STATUS_SYNTAX (isc_uint16_t)3
226 typedef struct entropysource entropysource_t
;
228 struct entropysource
{
229 isc_entropysource_t
*source
;
231 ISC_LINK(entropysource_t
) link
;
234 static ISC_LIST(entropysource_t
) sources
;
237 setup_entropy(isc_mem_t
*mctx
, const char *randomfile
, isc_entropy_t
**ectx
)
240 isc_entropysource_t
*source
= NULL
;
241 entropysource_t
*elt
;
242 int usekeyboard
= ISC_ENTROPY_KEYBOARDMAYBE
;
244 REQUIRE(ectx
!= NULL
);
247 result
= isc_entropy_create(mctx
, ectx
);
248 if (result
!= ISC_R_SUCCESS
)
249 fatal("could not create entropy object");
250 ISC_LIST_INIT(sources
);
253 if (randomfile
!= NULL
&& strcmp(randomfile
, "keyboard") == 0) {
254 usekeyboard
= ISC_ENTROPY_KEYBOARDYES
;
258 result
= isc_entropy_usebestsource(*ectx
, &source
, randomfile
,
261 if (result
!= ISC_R_SUCCESS
)
262 fatal("could not initialize entropy source: %s",
263 isc_result_totext(result
));
265 if (source
!= NULL
) {
266 elt
= isc_mem_get(mctx
, sizeof(*elt
));
268 fatal("out of memory");
269 elt
->source
= source
;
271 ISC_LINK_INIT(elt
, link
);
272 ISC_LIST_APPEND(sources
, elt
, link
);
277 cleanup_entropy(isc_entropy_t
**ectx
) {
278 entropysource_t
*source
;
279 while (!ISC_LIST_EMPTY(sources
)) {
280 source
= ISC_LIST_HEAD(sources
);
281 ISC_LIST_UNLINK(sources
, source
, link
);
282 isc_entropy_destroysource(&source
->source
);
283 isc_mem_put(source
->mctx
, source
, sizeof(*source
));
285 isc_entropy_detach(ectx
);
289 static dns_rdataclass_t
291 if (zoneclass
== dns_rdataclass_none
)
292 zoneclass
= defaultclass
;
297 setzoneclass(dns_rdataclass_t rdclass
) {
298 if (zoneclass
== dns_rdataclass_none
||
299 rdclass
== dns_rdataclass_none
)
301 if (zoneclass
!= rdclass
)
307 fatal(const char *format
, ...) {
310 va_start(args
, format
);
311 vfprintf(stderr
, format
, args
);
313 fprintf(stderr
, "\n");
318 error(const char *format
, ...) {
321 va_start(args
, format
);
322 vfprintf(stderr
, format
, args
);
324 fprintf(stderr
, "\n");
328 debug(const char *format
, ...) {
332 va_start(args
, format
);
333 vfprintf(stderr
, format
, args
);
335 fprintf(stderr
, "\n");
340 ddebug(const char *format
, ...) {
344 va_start(args
, format
);
345 vfprintf(stderr
, format
, args
);
347 fprintf(stderr
, "\n");
352 check_result(isc_result_t result
, const char *msg
) {
353 if (result
!= ISC_R_SUCCESS
)
354 fatal("%s: %s", msg
, isc_result_totext(result
));
358 mem_alloc(void *arg
, size_t size
) {
359 return (isc_mem_get(arg
, size
));
363 mem_free(void *arg
, void *mem
, size_t size
) {
364 isc_mem_put(arg
, mem
, size
);
368 nsu_strsep(char **stringp
, const char *delim
) {
369 char *string
= *stringp
;
377 for (; *string
!= '\0'; string
++) {
379 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
387 for (s
= string
; *s
!= '\0'; s
++) {
389 for (d
= delim
; (dc
= *d
) != '\0'; d
++) {
405 ddebug("reset_system()");
406 /* If the update message is still around, destroy it */
407 if (updatemsg
!= NULL
)
408 dns_message_reset(updatemsg
, DNS_MESSAGE_INTENTRENDER
);
410 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
412 check_result(result
, "dns_message_create");
414 updatemsg
->opcode
= dns_opcode_update
;
417 dns_tsigkey_detach(&tsigkey
);
419 dns_tsigkeyring_destroy(&gssring
);
420 tried_other_gsstsig
= ISC_FALSE
;
425 parse_hmac(dns_name_t
**hmac
, const char *hmacstr
, size_t len
) {
426 isc_uint16_t digestbits
= 0;
430 REQUIRE(hmac
!= NULL
&& *hmac
== NULL
);
431 REQUIRE(hmacstr
!= NULL
);
433 if (len
>= sizeof(buf
))
434 fatal("unknown key type '%.*s'", (int)(len
), hmacstr
);
436 strncpy(buf
, hmacstr
, len
);
439 if (strcasecmp(buf
, "hmac-md5") == 0) {
440 *hmac
= DNS_TSIG_HMACMD5_NAME
;
441 } else if (strncasecmp(buf
, "hmac-md5-", 9) == 0) {
442 *hmac
= DNS_TSIG_HMACMD5_NAME
;
443 result
= isc_parse_uint16(&digestbits
, &buf
[9], 10);
444 if (result
!= ISC_R_SUCCESS
|| digestbits
> 128)
445 fatal("digest-bits out of range [0..128]");
446 digestbits
= (digestbits
+7) & ~0x7U
;
447 } else if (strcasecmp(buf
, "hmac-sha1") == 0) {
448 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
449 } else if (strncasecmp(buf
, "hmac-sha1-", 10) == 0) {
450 *hmac
= DNS_TSIG_HMACSHA1_NAME
;
451 result
= isc_parse_uint16(&digestbits
, &buf
[10], 10);
452 if (result
!= ISC_R_SUCCESS
|| digestbits
> 160)
453 fatal("digest-bits out of range [0..160]");
454 digestbits
= (digestbits
+7) & ~0x7U
;
455 } else if (strcasecmp(buf
, "hmac-sha224") == 0) {
456 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
457 } else if (strncasecmp(buf
, "hmac-sha224-", 12) == 0) {
458 *hmac
= DNS_TSIG_HMACSHA224_NAME
;
459 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
460 if (result
!= ISC_R_SUCCESS
|| digestbits
> 224)
461 fatal("digest-bits out of range [0..224]");
462 digestbits
= (digestbits
+7) & ~0x7U
;
463 } else if (strcasecmp(buf
, "hmac-sha256") == 0) {
464 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
465 } else if (strncasecmp(buf
, "hmac-sha256-", 12) == 0) {
466 *hmac
= DNS_TSIG_HMACSHA256_NAME
;
467 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
468 if (result
!= ISC_R_SUCCESS
|| digestbits
> 256)
469 fatal("digest-bits out of range [0..256]");
470 digestbits
= (digestbits
+7) & ~0x7U
;
471 } else if (strcasecmp(buf
, "hmac-sha384") == 0) {
472 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
473 } else if (strncasecmp(buf
, "hmac-sha384-", 12) == 0) {
474 *hmac
= DNS_TSIG_HMACSHA384_NAME
;
475 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
476 if (result
!= ISC_R_SUCCESS
|| digestbits
> 384)
477 fatal("digest-bits out of range [0..384]");
478 digestbits
= (digestbits
+7) & ~0x7U
;
479 } else if (strcasecmp(buf
, "hmac-sha512") == 0) {
480 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
481 } else if (strncasecmp(buf
, "hmac-sha512-", 12) == 0) {
482 *hmac
= DNS_TSIG_HMACSHA512_NAME
;
483 result
= isc_parse_uint16(&digestbits
, &buf
[12], 10);
484 if (result
!= ISC_R_SUCCESS
|| digestbits
> 512)
485 fatal("digest-bits out of range [0..512]");
486 digestbits
= (digestbits
+7) & ~0x7U
;
488 fatal("unknown key type '%s'", buf
);
494 unsigned char *secret
= NULL
;
496 isc_buffer_t secretbuf
;
498 isc_buffer_t keynamesrc
;
501 dns_fixedname_t fkeyname
;
504 dns_name_t
*hmacname
= NULL
;
505 isc_uint16_t digestbits
= 0;
507 dns_fixedname_init(&fkeyname
);
508 keyname
= dns_fixedname_name(&fkeyname
);
510 debug("Creating key...");
512 s
= strchr(keystr
, ':');
513 if (s
== NULL
|| s
== keystr
|| s
[1] == 0)
514 fatal("key option must specify [hmac:]keyname:secret");
516 n
= strchr(secretstr
, ':');
518 if (n
== secretstr
|| n
[1] == 0)
519 fatal("key option must specify [hmac:]keyname:secret");
522 digestbits
= parse_hmac(&hmacname
, keystr
, s
- keystr
);
524 hmacname
= DNS_TSIG_HMACMD5_NAME
;
529 isc_buffer_init(&keynamesrc
, name
, n
- name
);
530 isc_buffer_add(&keynamesrc
, n
- name
);
532 debug("namefromtext");
533 result
= dns_name_fromtext(keyname
, &keynamesrc
, dns_rootname
, 0, NULL
);
534 check_result(result
, "dns_name_fromtext");
536 secretlen
= strlen(secretstr
) * 3 / 4;
537 secret
= isc_mem_allocate(mctx
, secretlen
);
539 fatal("out of memory");
541 isc_buffer_init(&secretbuf
, secret
, secretlen
);
542 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
543 if (result
!= ISC_R_SUCCESS
) {
544 fprintf(stderr
, "could not create key from %s: %s\n",
545 keystr
, isc_result_totext(result
));
549 secretlen
= isc_buffer_usedlength(&secretbuf
);
552 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
553 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
, &tsigkey
);
554 if (result
!= ISC_R_SUCCESS
)
555 fprintf(stderr
, "could not create key from %s: %s\n",
556 keystr
, dns_result_totext(result
));
558 dst_key_setbits(tsigkey
->key
, digestbits
);
561 isc_mem_free(mctx
, secret
);
565 * Get a key from a named.conf format keyfile
568 read_sessionkey(isc_mem_t
*mctx
, isc_log_t
*lctx
) {
569 cfg_parser_t
*pctx
= NULL
;
570 cfg_obj_t
*sessionkey
= NULL
;
571 const cfg_obj_t
*key
= NULL
;
572 const cfg_obj_t
*secretobj
= NULL
;
573 const cfg_obj_t
*algorithmobj
= NULL
;
575 const char *secretstr
;
576 const char *algorithm
;
580 if (! isc_file_exists(keyfile
))
581 return (ISC_R_FILENOTFOUND
);
583 result
= cfg_parser_create(mctx
, lctx
, &pctx
);
584 if (result
!= ISC_R_SUCCESS
)
587 result
= cfg_parse_file(pctx
, keyfile
, &cfg_type_sessionkey
,
589 if (result
!= ISC_R_SUCCESS
)
592 result
= cfg_map_get(sessionkey
, "key", &key
);
593 if (result
!= ISC_R_SUCCESS
)
596 (void) cfg_map_get(key
, "secret", &secretobj
);
597 (void) cfg_map_get(key
, "algorithm", &algorithmobj
);
598 if (secretobj
== NULL
|| algorithmobj
== NULL
)
599 fatal("key must have algorithm and secret");
601 keyname
= cfg_obj_asstring(cfg_map_getname(key
));
602 secretstr
= cfg_obj_asstring(secretobj
);
603 algorithm
= cfg_obj_asstring(algorithmobj
);
605 len
= strlen(algorithm
) + strlen(keyname
) + strlen(secretstr
) + 3;
606 keystr
= isc_mem_allocate(mctx
, len
);
607 snprintf(keystr
, len
, "%s:%s:%s", algorithm
, keyname
, secretstr
);
612 if (sessionkey
!= NULL
)
613 cfg_obj_destroy(pctx
, &sessionkey
);
614 cfg_parser_destroy(&pctx
);
618 isc_mem_free(mctx
, keystr
);
624 setup_keyfile(isc_mem_t
*mctx
, isc_log_t
*lctx
) {
625 dst_key_t
*dstkey
= NULL
;
627 dns_name_t
*hmacname
= NULL
;
629 debug("Creating key...");
631 /* Try reading the key from a K* pair */
632 result
= dst_key_fromnamedfile(keyfile
, NULL
,
633 DST_TYPE_PRIVATE
| DST_TYPE_KEY
, mctx
,
636 /* If that didn't work, try reading it as a session.key keyfile */
637 if (result
!= ISC_R_SUCCESS
) {
638 result
= read_sessionkey(mctx
, lctx
);
639 if (result
== ISC_R_SUCCESS
)
643 if (result
!= ISC_R_SUCCESS
) {
644 fprintf(stderr
, "could not read key from %s: %s\n",
645 keyfile
, isc_result_totext(result
));
649 switch (dst_key_alg(dstkey
)) {
650 case DST_ALG_HMACMD5
:
651 hmacname
= DNS_TSIG_HMACMD5_NAME
;
653 case DST_ALG_HMACSHA1
:
654 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
656 case DST_ALG_HMACSHA224
:
657 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
659 case DST_ALG_HMACSHA256
:
660 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
662 case DST_ALG_HMACSHA384
:
663 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
665 case DST_ALG_HMACSHA512
:
666 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
669 if (hmacname
!= NULL
) {
670 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
),
671 hmacname
, dstkey
, ISC_FALSE
,
672 NULL
, 0, 0, mctx
, NULL
,
674 if (result
!= ISC_R_SUCCESS
) {
675 fprintf(stderr
, "could not create key from %s: %s\n",
676 keyfile
, isc_result_totext(result
));
677 dst_key_free(&dstkey
);
686 isc_task_detach(&global_task
);
688 if (userserver
!= NULL
)
689 isc_mem_put(mctx
, userserver
, sizeof(isc_sockaddr_t
));
691 if (localaddr
!= NULL
)
692 isc_mem_put(mctx
, localaddr
, sizeof(isc_sockaddr_t
));
694 if (tsigkey
!= NULL
) {
695 ddebug("Freeing TSIG key");
696 dns_tsigkey_detach(&tsigkey
);
699 if (sig0key
!= NULL
) {
700 ddebug("Freeing SIG(0) key");
701 dst_key_free(&sig0key
);
704 if (updatemsg
!= NULL
)
705 dns_message_destroy(&updatemsg
);
708 ddebug("Destroy DST lib");
710 is_dst_up
= ISC_FALSE
;
713 cleanup_entropy(&entropy
);
715 lwres_conf_clear(lwctx
);
716 lwres_context_destroy(&lwctx
);
718 isc_mem_put(mctx
, servers
, ns_total
* sizeof(isc_sockaddr_t
));
720 ddebug("Destroying request manager");
721 dns_requestmgr_detach(&requestmgr
);
723 ddebug("Freeing the dispatchers");
725 dns_dispatch_detach(&dispatchv4
);
727 dns_dispatch_detach(&dispatchv6
);
729 ddebug("Shutting down dispatch manager");
730 dns_dispatchmgr_destroy(&dispatchmgr
);
735 maybeshutdown(void) {
736 ddebug("Shutting down request manager");
737 dns_requestmgr_shutdown(requestmgr
);
746 shutdown_program(isc_task_t
*task
, isc_event_t
*event
) {
747 REQUIRE(task
== global_task
);
750 ddebug("shutdown_program()");
751 isc_event_free(&event
);
753 shuttingdown
= ISC_TRUE
;
760 isc_sockaddr_t bind_any
, bind_any6
;
761 lwres_result_t lwresult
;
762 unsigned int attrs
, attrmask
;
764 isc_logconfig_t
*logconfig
= NULL
;
766 ddebug("setup_system()");
768 dns_result_register();
770 result
= isc_net_probeipv4();
771 if (result
== ISC_R_SUCCESS
)
772 have_ipv4
= ISC_TRUE
;
774 result
= isc_net_probeipv6();
775 if (result
== ISC_R_SUCCESS
)
776 have_ipv6
= ISC_TRUE
;
778 if (!have_ipv4
&& !have_ipv6
)
779 fatal("could not find either IPv4 or IPv6");
781 result
= isc_log_create(mctx
, &lctx
, &logconfig
);
782 check_result(result
, "isc_log_create");
784 isc_log_setcontext(lctx
);
786 dns_log_setcontext(lctx
);
788 result
= isc_log_usechannel(logconfig
, "default_debug", NULL
, NULL
);
789 check_result(result
, "isc_log_usechannel");
791 isc_log_setdebuglevel(lctx
, logdebuglevel
);
793 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
, 1);
794 if (lwresult
!= LWRES_R_SUCCESS
)
795 fatal("lwres_context_create failed");
797 (void)lwres_conf_parse(lwctx
, RESOLV_CONF
);
798 lwconf
= lwres_conf_get(lwctx
);
800 ns_total
= lwconf
->nsnext
;
802 /* No name servers in resolv.conf; default to loopback. */
803 struct in_addr localhost
;
805 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
807 fatal("out of memory");
808 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
809 isc_sockaddr_fromin(&servers
[0], &localhost
, dnsport
);
811 servers
= isc_mem_get(mctx
, ns_total
* sizeof(isc_sockaddr_t
));
813 fatal("out of memory");
814 for (i
= 0; i
< ns_total
; i
++) {
815 if (lwconf
->nameservers
[i
].family
== LWRES_ADDRTYPE_V4
) {
817 memcpy(&in4
, lwconf
->nameservers
[i
].address
, 4);
818 isc_sockaddr_fromin(&servers
[i
], &in4
, dnsport
);
821 memcpy(&in6
, lwconf
->nameservers
[i
].address
, 16);
822 isc_sockaddr_fromin6(&servers
[i
], &in6
,
828 setup_entropy(mctx
, NULL
, &entropy
);
830 result
= isc_hash_create(mctx
, entropy
, DNS_NAME_MAXWIRE
);
831 check_result(result
, "isc_hash_create");
834 result
= dns_dispatchmgr_create(mctx
, entropy
, &dispatchmgr
);
835 check_result(result
, "dns_dispatchmgr_create");
837 result
= isc_socketmgr_create(mctx
, &socketmgr
);
838 check_result(result
, "dns_socketmgr_create");
840 result
= isc_timermgr_create(mctx
, &timermgr
);
841 check_result(result
, "dns_timermgr_create");
843 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
844 check_result(result
, "isc_taskmgr_create");
846 result
= isc_task_create(taskmgr
, 0, &global_task
);
847 check_result(result
, "isc_task_create");
849 result
= isc_task_onshutdown(global_task
, shutdown_program
, NULL
);
850 check_result(result
, "isc_task_onshutdown");
852 result
= dst_lib_init(mctx
, entropy
, 0);
853 check_result(result
, "dst_lib_init");
854 is_dst_up
= ISC_TRUE
;
856 attrmask
= DNS_DISPATCHATTR_UDP
| DNS_DISPATCHATTR_TCP
;
857 attrmask
|= DNS_DISPATCHATTR_IPV4
| DNS_DISPATCHATTR_IPV6
;
860 attrs
= DNS_DISPATCHATTR_UDP
;
861 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
862 attrs
|= DNS_DISPATCHATTR_IPV6
;
863 isc_sockaddr_any6(&bind_any6
);
864 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
865 &bind_any6
, PACKETSIZE
,
867 attrs
, attrmask
, &dispatchv6
);
868 check_result(result
, "dns_dispatch_getudp (v6)");
872 attrs
= DNS_DISPATCHATTR_UDP
;
873 attrs
|= DNS_DISPATCHATTR_MAKEQUERY
;
874 attrs
|= DNS_DISPATCHATTR_IPV4
;
875 isc_sockaddr_any(&bind_any
);
876 result
= dns_dispatch_getudp(dispatchmgr
, socketmgr
, taskmgr
,
877 &bind_any
, PACKETSIZE
,
879 attrs
, attrmask
, &dispatchv4
);
880 check_result(result
, "dns_dispatch_getudp (v4)");
883 result
= dns_requestmgr_create(mctx
, timermgr
,
884 socketmgr
, taskmgr
, dispatchmgr
,
885 dispatchv4
, dispatchv6
, &requestmgr
);
886 check_result(result
, "dns_requestmgr_create");
891 read_sessionkey(mctx
, lctx
);
892 else if (keyfile
!= NULL
)
893 setup_keyfile(mctx
, lctx
);
897 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
902 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
904 if (result
!= ISC_R_SUCCESS
)
905 fatal("couldn't get address for '%s': %s",
906 host
, isc_result_totext(result
));
910 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:"
913 pre_parse_args(int argc
, char **argv
) {
916 while ((ch
= isc_commandline_parse(argc
, argv
, PARSE_ARGS_FMT
)) != -1) {
918 case 'M': /* was -dm */
919 debugging
= ISC_TRUE
;
920 ddebugging
= ISC_TRUE
;
921 memdebugging
= ISC_TRUE
;
922 isc_mem_debugging
= ISC_MEM_DEBUGTRACE
|
928 if (isc_commandline_option
!= '?')
929 fprintf(stderr
, "%s: invalid argument -%c\n",
930 argv
[0], isc_commandline_option
);
931 fprintf(stderr
, "usage: nsupdate [-dD] [-L level] [-l]"
932 "[-g | -o | -y keyname:secret | -k keyfile] "
933 "[-v] [filename]\n");
940 isc_commandline_reset
= ISC_TRUE
;
941 isc_commandline_index
= 1;
945 parse_args(int argc
, char **argv
, isc_mem_t
*mctx
, isc_entropy_t
**ectx
) {
951 while ((ch
= isc_commandline_parse(argc
, argv
, PARSE_ARGS_FMT
)) != -1) {
954 debugging
= ISC_TRUE
;
956 case 'D': /* was -dd */
957 debugging
= ISC_TRUE
;
958 ddebugging
= ISC_TRUE
;
963 local_only
= ISC_TRUE
;
966 result
= isc_parse_uint32(&i
, isc_commandline_argument
,
968 if (result
!= ISC_R_SUCCESS
) {
969 fprintf(stderr
, "bad library debug value "
970 "'%s'\n", isc_commandline_argument
);
976 keystr
= isc_commandline_argument
;
982 keyfile
= isc_commandline_argument
;
985 usegsstsig
= ISC_TRUE
;
986 use_win2k_gsstsig
= ISC_FALSE
;
989 usegsstsig
= ISC_TRUE
;
990 use_win2k_gsstsig
= ISC_TRUE
;
993 result
= isc_parse_uint16(&dnsport
,
994 isc_commandline_argument
, 10);
995 if (result
!= ISC_R_SUCCESS
) {
996 fprintf(stderr
, "bad port number "
997 "'%s'\n", isc_commandline_argument
);
1002 result
= isc_parse_uint32(&timeout
,
1003 isc_commandline_argument
, 10);
1004 if (result
!= ISC_R_SUCCESS
) {
1005 fprintf(stderr
, "bad timeout '%s'\n", isc_commandline_argument
);
1012 result
= isc_parse_uint32(&udp_timeout
,
1013 isc_commandline_argument
, 10);
1014 if (result
!= ISC_R_SUCCESS
) {
1015 fprintf(stderr
, "bad udp timeout '%s'\n", isc_commandline_argument
);
1018 if (udp_timeout
== 0)
1019 udp_timeout
= UINT_MAX
;
1022 result
= isc_parse_uint32(&udp_retries
,
1023 isc_commandline_argument
, 10);
1024 if (result
!= ISC_R_SUCCESS
) {
1025 fprintf(stderr
, "bad udp retries '%s'\n", isc_commandline_argument
);
1031 setup_entropy(mctx
, isc_commandline_argument
, ectx
);
1035 fprintf(stderr
, "%s: unhandled option: %c\n",
1036 argv
[0], isc_commandline_option
);
1040 if (keyfile
!= NULL
&& keystr
!= NULL
) {
1041 fprintf(stderr
, "%s: cannot specify both -k and -y\n",
1047 struct in_addr localhost
;
1049 if (keyfile
== NULL
)
1050 keyfile
= SESSION_KEYFILE
;
1052 if (userserver
== NULL
) {
1053 userserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1054 if (userserver
== NULL
)
1055 fatal("out of memory");
1058 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
1059 isc_sockaddr_fromin(userserver
, &localhost
, dnsport
);
1063 if (usegsstsig
&& (keyfile
!= NULL
|| keystr
!= NULL
)) {
1064 fprintf(stderr
, "%s: cannot specify -g with -k or -y\n",
1070 fprintf(stderr
, "%s: cannot specify -g or -o, " \
1071 "program not linked with GSS API Library\n",
1077 if (argv
[isc_commandline_index
] != NULL
) {
1078 if (strcmp(argv
[isc_commandline_index
], "-") == 0) {
1081 result
= isc_stdio_open(argv
[isc_commandline_index
],
1083 if (result
!= ISC_R_SUCCESS
) {
1084 fprintf(stderr
, "could not open '%s': %s\n",
1085 argv
[isc_commandline_index
],
1086 isc_result_totext(result
));
1090 interactive
= ISC_FALSE
;
1095 parse_name(char **cmdlinep
, dns_message_t
*msg
, dns_name_t
**namep
) {
1096 isc_result_t result
;
1098 isc_buffer_t
*namebuf
= NULL
;
1099 isc_buffer_t source
;
1101 word
= nsu_strsep(cmdlinep
, " \t\r\n");
1103 fprintf(stderr
, "could not read owner name\n");
1104 return (STATUS_SYNTAX
);
1107 result
= dns_message_gettempname(msg
, namep
);
1108 check_result(result
, "dns_message_gettempname");
1109 result
= isc_buffer_allocate(mctx
, &namebuf
, DNS_NAME_MAXWIRE
);
1110 check_result(result
, "isc_buffer_allocate");
1111 dns_name_init(*namep
, NULL
);
1112 dns_name_setbuffer(*namep
, namebuf
);
1113 dns_message_takebuffer(msg
, &namebuf
);
1114 isc_buffer_init(&source
, word
, strlen(word
));
1115 isc_buffer_add(&source
, strlen(word
));
1116 result
= dns_name_fromtext(*namep
, &source
, dns_rootname
, 0, NULL
);
1117 check_result(result
, "dns_name_fromtext");
1118 isc_buffer_invalidate(&source
);
1119 return (STATUS_MORE
);
1123 parse_rdata(char **cmdlinep
, dns_rdataclass_t rdataclass
,
1124 dns_rdatatype_t rdatatype
, dns_message_t
*msg
,
1127 char *cmdline
= *cmdlinep
;
1128 isc_buffer_t source
, *buf
= NULL
, *newbuf
= NULL
;
1130 isc_lex_t
*lex
= NULL
;
1131 dns_rdatacallbacks_t callbacks
;
1132 isc_result_t result
;
1134 while (*cmdline
!= 0 && isspace((unsigned char)*cmdline
))
1137 if (*cmdline
!= 0) {
1138 dns_rdatacallbacks_init(&callbacks
);
1139 result
= isc_lex_create(mctx
, strlen(cmdline
), &lex
);
1140 check_result(result
, "isc_lex_create");
1141 isc_buffer_init(&source
, cmdline
, strlen(cmdline
));
1142 isc_buffer_add(&source
, strlen(cmdline
));
1143 result
= isc_lex_openbuffer(lex
, &source
);
1144 check_result(result
, "isc_lex_openbuffer");
1145 result
= isc_buffer_allocate(mctx
, &buf
, MAXWIRE
);
1146 check_result(result
, "isc_buffer_allocate");
1147 result
= dns_rdata_fromtext(NULL
, rdataclass
, rdatatype
, lex
,
1148 dns_rootname
, 0, mctx
, buf
,
1150 isc_lex_destroy(&lex
);
1151 if (result
== ISC_R_SUCCESS
) {
1152 isc_buffer_usedregion(buf
, &r
);
1153 result
= isc_buffer_allocate(mctx
, &newbuf
, r
.length
);
1154 check_result(result
, "isc_buffer_allocate");
1155 isc_buffer_putmem(newbuf
, r
.base
, r
.length
);
1156 isc_buffer_usedregion(newbuf
, &r
);
1157 dns_rdata_fromregion(rdata
, rdataclass
, rdatatype
, &r
);
1158 isc_buffer_free(&buf
);
1159 dns_message_takebuffer(msg
, &newbuf
);
1161 fprintf(stderr
, "invalid rdata format: %s\n",
1162 isc_result_totext(result
));
1163 isc_buffer_free(&buf
);
1164 return (STATUS_SYNTAX
);
1167 rdata
->flags
= DNS_RDATA_UPDATE
;
1169 *cmdlinep
= cmdline
;
1170 return (STATUS_MORE
);
1174 make_prereq(char *cmdline
, isc_boolean_t ispositive
, isc_boolean_t isrrset
) {
1175 isc_result_t result
;
1177 dns_name_t
*name
= NULL
;
1178 isc_textregion_t region
;
1179 dns_rdataset_t
*rdataset
= NULL
;
1180 dns_rdatalist_t
*rdatalist
= NULL
;
1181 dns_rdataclass_t rdataclass
;
1182 dns_rdatatype_t rdatatype
;
1183 dns_rdata_t
*rdata
= NULL
;
1184 isc_uint16_t retval
;
1186 ddebug("make_prereq()");
1189 * Read the owner name
1191 retval
= parse_name(&cmdline
, updatemsg
, &name
);
1192 if (retval
!= STATUS_MORE
)
1196 * If this is an rrset prereq, read the class or type.
1199 word
= nsu_strsep(&cmdline
, " \t\r\n");
1201 fprintf(stderr
, "could not read class or type\n");
1205 region
.length
= strlen(word
);
1206 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
1207 if (result
== ISC_R_SUCCESS
) {
1208 if (!setzoneclass(rdataclass
)) {
1209 fprintf(stderr
, "class mismatch: %s\n", word
);
1213 * Now read the type.
1215 word
= nsu_strsep(&cmdline
, " \t\r\n");
1217 fprintf(stderr
, "could not read type\n");
1221 region
.length
= strlen(word
);
1222 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1223 if (result
!= ISC_R_SUCCESS
) {
1224 fprintf(stderr
, "invalid type: %s\n", word
);
1228 rdataclass
= getzoneclass();
1229 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1230 if (result
!= ISC_R_SUCCESS
) {
1231 fprintf(stderr
, "invalid type: %s\n", word
);
1236 rdatatype
= dns_rdatatype_any
;
1238 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
1239 check_result(result
, "dns_message_gettemprdata");
1241 dns_rdata_init(rdata
);
1243 if (isrrset
&& ispositive
) {
1244 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
,
1246 if (retval
!= STATUS_MORE
)
1249 rdata
->flags
= DNS_RDATA_UPDATE
;
1251 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
1252 check_result(result
, "dns_message_gettemprdatalist");
1253 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1254 check_result(result
, "dns_message_gettemprdataset");
1255 dns_rdatalist_init(rdatalist
);
1256 rdatalist
->type
= rdatatype
;
1258 if (isrrset
&& rdata
->data
!= NULL
)
1259 rdatalist
->rdclass
= rdataclass
;
1261 rdatalist
->rdclass
= dns_rdataclass_any
;
1263 rdatalist
->rdclass
= dns_rdataclass_none
;
1264 rdatalist
->covers
= 0;
1266 rdata
->rdclass
= rdatalist
->rdclass
;
1267 rdata
->type
= rdatatype
;
1268 ISC_LIST_INIT(rdatalist
->rdata
);
1269 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1270 dns_rdataset_init(rdataset
);
1271 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1272 ISC_LIST_INIT(name
->list
);
1273 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1274 dns_message_addname(updatemsg
, name
, DNS_SECTION_PREREQUISITE
);
1275 return (STATUS_MORE
);
1279 dns_message_puttempname(updatemsg
, &name
);
1280 return (STATUS_SYNTAX
);
1284 evaluate_prereq(char *cmdline
) {
1286 isc_boolean_t ispositive
, isrrset
;
1288 ddebug("evaluate_prereq()");
1289 word
= nsu_strsep(&cmdline
, " \t\r\n");
1291 fprintf(stderr
, "could not read operation code\n");
1292 return (STATUS_SYNTAX
);
1294 if (strcasecmp(word
, "nxdomain") == 0) {
1295 ispositive
= ISC_FALSE
;
1296 isrrset
= ISC_FALSE
;
1297 } else if (strcasecmp(word
, "yxdomain") == 0) {
1298 ispositive
= ISC_TRUE
;
1299 isrrset
= ISC_FALSE
;
1300 } else if (strcasecmp(word
, "nxrrset") == 0) {
1301 ispositive
= ISC_FALSE
;
1303 } else if (strcasecmp(word
, "yxrrset") == 0) {
1304 ispositive
= ISC_TRUE
;
1307 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1308 return (STATUS_SYNTAX
);
1310 return (make_prereq(cmdline
, ispositive
, isrrset
));
1314 evaluate_server(char *cmdline
) {
1315 char *word
, *server
;
1319 fprintf(stderr
, "cannot reset server in localhost-only mode\n");
1320 return (STATUS_SYNTAX
);
1323 word
= nsu_strsep(&cmdline
, " \t\r\n");
1325 fprintf(stderr
, "could not read server name\n");
1326 return (STATUS_SYNTAX
);
1330 word
= nsu_strsep(&cmdline
, " \t\r\n");
1335 port
= strtol(word
, &endp
, 10);
1337 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1338 return (STATUS_SYNTAX
);
1339 } else if (port
< 1 || port
> 65535) {
1340 fprintf(stderr
, "port '%s' is out of range "
1341 "(1 to 65535)\n", word
);
1342 return (STATUS_SYNTAX
);
1346 if (userserver
== NULL
) {
1347 userserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1348 if (userserver
== NULL
)
1349 fatal("out of memory");
1352 get_address(server
, (in_port_t
)port
, userserver
);
1354 return (STATUS_MORE
);
1358 evaluate_local(char *cmdline
) {
1362 struct in6_addr in6
;
1364 word
= nsu_strsep(&cmdline
, " \t\r\n");
1366 fprintf(stderr
, "could not read server name\n");
1367 return (STATUS_SYNTAX
);
1371 word
= nsu_strsep(&cmdline
, " \t\r\n");
1376 port
= strtol(word
, &endp
, 10);
1378 fprintf(stderr
, "port '%s' is not numeric\n", word
);
1379 return (STATUS_SYNTAX
);
1380 } else if (port
< 1 || port
> 65535) {
1381 fprintf(stderr
, "port '%s' is out of range "
1382 "(1 to 65535)\n", word
);
1383 return (STATUS_SYNTAX
);
1387 if (localaddr
== NULL
) {
1388 localaddr
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
1389 if (localaddr
== NULL
)
1390 fatal("out of memory");
1393 if (have_ipv6
&& inet_pton(AF_INET6
, local
, &in6
) == 1)
1394 isc_sockaddr_fromin6(localaddr
, &in6
, (in_port_t
)port
);
1395 else if (have_ipv4
&& inet_pton(AF_INET
, local
, &in4
) == 1)
1396 isc_sockaddr_fromin(localaddr
, &in4
, (in_port_t
)port
);
1398 fprintf(stderr
, "invalid address %s", local
);
1399 return (STATUS_SYNTAX
);
1402 return (STATUS_MORE
);
1406 evaluate_key(char *cmdline
) {
1410 isc_result_t result
;
1411 dns_fixedname_t fkeyname
;
1412 dns_name_t
*keyname
;
1414 unsigned char *secret
= NULL
;
1415 isc_buffer_t secretbuf
;
1416 dns_name_t
*hmacname
= NULL
;
1417 isc_uint16_t digestbits
= 0;
1420 namestr
= nsu_strsep(&cmdline
, " \t\r\n");
1421 if (*namestr
== 0) {
1422 fprintf(stderr
, "could not read key name\n");
1423 return (STATUS_SYNTAX
);
1426 dns_fixedname_init(&fkeyname
);
1427 keyname
= dns_fixedname_name(&fkeyname
);
1429 n
= strchr(namestr
, ':');
1431 digestbits
= parse_hmac(&hmacname
, namestr
, n
- namestr
);
1434 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1436 isc_buffer_init(&b
, namestr
, strlen(namestr
));
1437 isc_buffer_add(&b
, strlen(namestr
));
1438 result
= dns_name_fromtext(keyname
, &b
, dns_rootname
, 0, NULL
);
1439 if (result
!= ISC_R_SUCCESS
) {
1440 fprintf(stderr
, "could not parse key name\n");
1441 return (STATUS_SYNTAX
);
1444 secretstr
= nsu_strsep(&cmdline
, "\r\n");
1445 if (*secretstr
== 0) {
1446 fprintf(stderr
, "could not read key secret\n");
1447 return (STATUS_SYNTAX
);
1449 secretlen
= strlen(secretstr
) * 3 / 4;
1450 secret
= isc_mem_allocate(mctx
, secretlen
);
1452 fatal("out of memory");
1454 isc_buffer_init(&secretbuf
, secret
, secretlen
);
1455 result
= isc_base64_decodestring(secretstr
, &secretbuf
);
1456 if (result
!= ISC_R_SUCCESS
) {
1457 fprintf(stderr
, "could not create key from %s: %s\n",
1458 secretstr
, isc_result_totext(result
));
1459 isc_mem_free(mctx
, secret
);
1460 return (STATUS_SYNTAX
);
1462 secretlen
= isc_buffer_usedlength(&secretbuf
);
1464 if (tsigkey
!= NULL
)
1465 dns_tsigkey_detach(&tsigkey
);
1466 result
= dns_tsigkey_create(keyname
, hmacname
, secret
, secretlen
,
1467 ISC_TRUE
, NULL
, 0, 0, mctx
, NULL
,
1469 isc_mem_free(mctx
, secret
);
1470 if (result
!= ISC_R_SUCCESS
) {
1471 fprintf(stderr
, "could not create key from %s %s: %s\n",
1472 namestr
, secretstr
, dns_result_totext(result
));
1473 return (STATUS_SYNTAX
);
1475 dst_key_setbits(tsigkey
->key
, digestbits
);
1476 return (STATUS_MORE
);
1480 evaluate_zone(char *cmdline
) {
1483 isc_result_t result
;
1485 word
= nsu_strsep(&cmdline
, " \t\r\n");
1487 fprintf(stderr
, "could not read zone name\n");
1488 return (STATUS_SYNTAX
);
1491 dns_fixedname_init(&fuserzone
);
1492 userzone
= dns_fixedname_name(&fuserzone
);
1493 isc_buffer_init(&b
, word
, strlen(word
));
1494 isc_buffer_add(&b
, strlen(word
));
1495 result
= dns_name_fromtext(userzone
, &b
, dns_rootname
, 0, NULL
);
1496 if (result
!= ISC_R_SUCCESS
) {
1497 userzone
= NULL
; /* Lest it point to an invalid name */
1498 fprintf(stderr
, "could not parse zone name\n");
1499 return (STATUS_SYNTAX
);
1502 return (STATUS_MORE
);
1506 evaluate_ttl(char *cmdline
) {
1508 isc_result_t result
;
1511 word
= nsu_strsep(&cmdline
, " \t\r\n");
1513 fprintf(stderr
, "could not ttl\n");
1514 return (STATUS_SYNTAX
);
1517 if (!strcasecmp(word
, "none")) {
1519 default_ttl_set
= ISC_FALSE
;
1520 return (STATUS_MORE
);
1523 result
= isc_parse_uint32(&ttl
, word
, 10);
1524 if (result
!= ISC_R_SUCCESS
)
1525 return (STATUS_SYNTAX
);
1527 if (ttl
> TTL_MAX
) {
1528 fprintf(stderr
, "ttl '%s' is out of range (0 to %u)\n",
1530 return (STATUS_SYNTAX
);
1533 default_ttl_set
= ISC_TRUE
;
1535 return (STATUS_MORE
);
1539 evaluate_class(char *cmdline
) {
1542 isc_result_t result
;
1543 dns_rdataclass_t rdclass
;
1545 word
= nsu_strsep(&cmdline
, " \t\r\n");
1547 fprintf(stderr
, "could not read class name\n");
1548 return (STATUS_SYNTAX
);
1552 r
.length
= strlen(word
);
1553 result
= dns_rdataclass_fromtext(&rdclass
, &r
);
1554 if (result
!= ISC_R_SUCCESS
) {
1555 fprintf(stderr
, "could not parse class name: %s\n", word
);
1556 return (STATUS_SYNTAX
);
1559 case dns_rdataclass_none
:
1560 case dns_rdataclass_any
:
1561 case dns_rdataclass_reserved0
:
1562 fprintf(stderr
, "bad default class: %s\n", word
);
1563 return (STATUS_SYNTAX
);
1565 defaultclass
= rdclass
;
1568 return (STATUS_MORE
);
1572 update_addordelete(char *cmdline
, isc_boolean_t isdelete
) {
1573 isc_result_t result
;
1574 dns_name_t
*name
= NULL
;
1577 dns_rdataclass_t rdataclass
;
1578 dns_rdatatype_t rdatatype
;
1579 dns_rdata_t
*rdata
= NULL
;
1580 dns_rdatalist_t
*rdatalist
= NULL
;
1581 dns_rdataset_t
*rdataset
= NULL
;
1582 isc_textregion_t region
;
1583 isc_uint16_t retval
;
1585 ddebug("update_addordelete()");
1588 * Read the owner name.
1590 retval
= parse_name(&cmdline
, updatemsg
, &name
);
1591 if (retval
!= STATUS_MORE
)
1594 result
= dns_message_gettemprdata(updatemsg
, &rdata
);
1595 check_result(result
, "dns_message_gettemprdata");
1597 dns_rdata_init(rdata
);
1600 * If this is an add, read the TTL and verify that it's in range.
1601 * If it's a delete, ignore a TTL if present (for compatibility).
1603 word
= nsu_strsep(&cmdline
, " \t\r\n");
1606 fprintf(stderr
, "could not read owner ttl\n");
1611 rdataclass
= dns_rdataclass_any
;
1612 rdatatype
= dns_rdatatype_any
;
1613 rdata
->flags
= DNS_RDATA_UPDATE
;
1617 result
= isc_parse_uint32(&ttl
, word
, 10);
1618 if (result
!= ISC_R_SUCCESS
) {
1622 } else if (default_ttl_set
) {
1626 fprintf(stderr
, "ttl '%s': %s\n", word
,
1627 isc_result_totext(result
));
1634 else if (ttl
> TTL_MAX
) {
1635 fprintf(stderr
, "ttl '%s' is out of range (0 to %u)\n",
1641 * Read the class or type.
1643 word
= nsu_strsep(&cmdline
, " \t\r\n");
1647 rdataclass
= dns_rdataclass_any
;
1648 rdatatype
= dns_rdatatype_any
;
1649 rdata
->flags
= DNS_RDATA_UPDATE
;
1652 fprintf(stderr
, "could not read class or type\n");
1657 region
.length
= strlen(word
);
1658 rdataclass
= dns_rdataclass_any
;
1659 result
= dns_rdataclass_fromtext(&rdataclass
, ®ion
);
1660 if (result
== ISC_R_SUCCESS
&& rdataclass
!= dns_rdataclass_any
) {
1661 if (!setzoneclass(rdataclass
)) {
1662 fprintf(stderr
, "class mismatch: %s\n", word
);
1666 * Now read the type.
1668 word
= nsu_strsep(&cmdline
, " \t\r\n");
1671 rdataclass
= dns_rdataclass_any
;
1672 rdatatype
= dns_rdatatype_any
;
1673 rdata
->flags
= DNS_RDATA_UPDATE
;
1676 fprintf(stderr
, "could not read type\n");
1681 region
.length
= strlen(word
);
1682 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1683 if (result
!= ISC_R_SUCCESS
) {
1684 fprintf(stderr
, "'%s' is not a valid type: %s\n",
1685 word
, isc_result_totext(result
));
1689 rdataclass
= getzoneclass();
1690 result
= dns_rdatatype_fromtext(&rdatatype
, ®ion
);
1691 if (result
!= ISC_R_SUCCESS
) {
1692 fprintf(stderr
, "'%s' is not a valid class or type: "
1693 "%s\n", word
, isc_result_totext(result
));
1698 retval
= parse_rdata(&cmdline
, rdataclass
, rdatatype
, updatemsg
,
1700 if (retval
!= STATUS_MORE
)
1704 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0)
1705 rdataclass
= dns_rdataclass_any
;
1707 rdataclass
= dns_rdataclass_none
;
1709 if ((rdata
->flags
& DNS_RDATA_UPDATE
) != 0) {
1710 fprintf(stderr
, "could not read rdata\n");
1717 result
= dns_message_gettemprdatalist(updatemsg
, &rdatalist
);
1718 check_result(result
, "dns_message_gettemprdatalist");
1719 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1720 check_result(result
, "dns_message_gettemprdataset");
1721 dns_rdatalist_init(rdatalist
);
1722 rdatalist
->type
= rdatatype
;
1723 rdatalist
->rdclass
= rdataclass
;
1724 rdatalist
->covers
= rdatatype
;
1725 rdatalist
->ttl
= (dns_ttl_t
)ttl
;
1726 ISC_LIST_INIT(rdatalist
->rdata
);
1727 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1728 dns_rdataset_init(rdataset
);
1729 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1730 ISC_LIST_INIT(name
->list
);
1731 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1732 dns_message_addname(updatemsg
, name
, DNS_SECTION_UPDATE
);
1733 return (STATUS_MORE
);
1737 dns_message_puttempname(updatemsg
, &name
);
1738 dns_message_puttemprdata(updatemsg
, &rdata
);
1739 return (STATUS_SYNTAX
);
1743 evaluate_update(char *cmdline
) {
1745 isc_boolean_t isdelete
;
1747 ddebug("evaluate_update()");
1748 word
= nsu_strsep(&cmdline
, " \t\r\n");
1750 fprintf(stderr
, "could not read operation code\n");
1751 return (STATUS_SYNTAX
);
1753 if (strcasecmp(word
, "delete") == 0)
1754 isdelete
= ISC_TRUE
;
1755 else if (strcasecmp(word
, "add") == 0)
1756 isdelete
= ISC_FALSE
;
1758 fprintf(stderr
, "incorrect operation code: %s\n", word
);
1759 return (STATUS_SYNTAX
);
1761 return (update_addordelete(cmdline
, isdelete
));
1765 setzone(dns_name_t
*zonename
) {
1766 isc_result_t result
;
1767 dns_name_t
*name
= NULL
;
1768 dns_rdataset_t
*rdataset
= NULL
;
1770 result
= dns_message_firstname(updatemsg
, DNS_SECTION_ZONE
);
1771 if (result
== ISC_R_SUCCESS
) {
1772 dns_message_currentname(updatemsg
, DNS_SECTION_ZONE
, &name
);
1773 dns_message_removename(updatemsg
, name
, DNS_SECTION_ZONE
);
1774 for (rdataset
= ISC_LIST_HEAD(name
->list
);
1776 rdataset
= ISC_LIST_HEAD(name
->list
)) {
1777 ISC_LIST_UNLINK(name
->list
, rdataset
, link
);
1778 dns_rdataset_disassociate(rdataset
);
1779 dns_message_puttemprdataset(updatemsg
, &rdataset
);
1781 dns_message_puttempname(updatemsg
, &name
);
1784 if (zonename
!= NULL
) {
1785 result
= dns_message_gettempname(updatemsg
, &name
);
1786 check_result(result
, "dns_message_gettempname");
1787 dns_name_init(name
, NULL
);
1788 dns_name_clone(zonename
, name
);
1789 result
= dns_message_gettemprdataset(updatemsg
, &rdataset
);
1790 check_result(result
, "dns_message_gettemprdataset");
1791 dns_rdataset_makequestion(rdataset
, getzoneclass(),
1793 ISC_LIST_INIT(name
->list
);
1794 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1795 dns_message_addname(updatemsg
, name
, DNS_SECTION_ZONE
);
1800 show_message(FILE *stream
, dns_message_t
*msg
, const char *description
) {
1801 isc_result_t result
;
1802 isc_buffer_t
*buf
= NULL
;
1805 ddebug("show_message()");
1811 if (bufsz
> MAXTEXT
) {
1812 fprintf(stderr
, "could not allocate large enough "
1813 "buffer to display message\n");
1817 isc_buffer_free(&buf
);
1818 result
= isc_buffer_allocate(mctx
, &buf
, bufsz
);
1819 check_result(result
, "isc_buffer_allocate");
1820 result
= dns_message_totext(msg
, style
, 0, buf
);
1822 } while (result
== ISC_R_NOSPACE
);
1823 if (result
!= ISC_R_SUCCESS
) {
1824 fprintf(stderr
, "could not convert message to text format.\n");
1825 isc_buffer_free(&buf
);
1828 fprintf(stream
, "%s\n%.*s", description
,
1829 (int)isc_buffer_usedlength(buf
), (char*)isc_buffer_base(buf
));
1830 isc_buffer_free(&buf
);
1835 get_next_command(void) {
1836 char cmdlinebuf
[MAXCMD
];
1840 ddebug("get_next_command()");
1842 fprintf(stdout
, "> ");
1846 cmdline
= fgets(cmdlinebuf
, MAXCMD
, input
);
1848 if (cmdline
== NULL
)
1849 return (STATUS_QUIT
);
1850 word
= nsu_strsep(&cmdline
, " \t\r\n");
1853 return (STATUS_QUIT
);
1855 return (STATUS_SEND
);
1857 return (STATUS_MORE
);
1858 if (strcasecmp(word
, "quit") == 0)
1859 return (STATUS_QUIT
);
1860 if (strcasecmp(word
, "prereq") == 0)
1861 return (evaluate_prereq(cmdline
));
1862 if (strcasecmp(word
, "update") == 0)
1863 return (evaluate_update(cmdline
));
1864 if (strcasecmp(word
, "server") == 0)
1865 return (evaluate_server(cmdline
));
1866 if (strcasecmp(word
, "local") == 0)
1867 return (evaluate_local(cmdline
));
1868 if (strcasecmp(word
, "zone") == 0)
1869 return (evaluate_zone(cmdline
));
1870 if (strcasecmp(word
, "class") == 0)
1871 return (evaluate_class(cmdline
));
1872 if (strcasecmp(word
, "send") == 0)
1873 return (STATUS_SEND
);
1874 if (strcasecmp(word
, "debug") == 0) {
1876 ddebugging
= ISC_TRUE
;
1878 debugging
= ISC_TRUE
;
1879 return (STATUS_MORE
);
1881 if (strcasecmp(word
, "ttl") == 0)
1882 return (evaluate_ttl(cmdline
));
1883 if (strcasecmp(word
, "show") == 0) {
1884 show_message(stdout
, updatemsg
, "Outgoing update query:");
1885 return (STATUS_MORE
);
1887 if (strcasecmp(word
, "answer") == 0) {
1889 show_message(stdout
, answer
, "Answer:");
1890 return (STATUS_MORE
);
1892 if (strcasecmp(word
, "key") == 0) {
1893 usegsstsig
= ISC_FALSE
;
1894 return (evaluate_key(cmdline
));
1896 if (strcasecmp(word
, "gsstsig") == 0) {
1898 usegsstsig
= ISC_TRUE
;
1899 use_win2k_gsstsig
= ISC_FALSE
;
1901 fprintf(stderr
, "gsstsig not supported\n");
1903 return (STATUS_MORE
);
1905 if (strcasecmp(word
, "oldgsstsig") == 0) {
1907 usegsstsig
= ISC_TRUE
;
1908 use_win2k_gsstsig
= ISC_TRUE
;
1910 fprintf(stderr
, "gsstsig not supported\n");
1912 return (STATUS_MORE
);
1914 if (strcasecmp(word
, "help") == 0) {
1916 "local address [port] (set local resolver)\n"
1917 "server address [port] (set master server for zone)\n"
1918 "send (send the update request)\n"
1919 "show (show the update request)\n"
1920 "answer (show the answer to the last request)\n"
1921 "quit (quit, any pending update is not sent\n"
1922 "help (display this message_\n"
1923 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
1924 "gsstsig (use GSS_TSIG to sign the request)\n"
1925 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
1926 "zone name (set the zone to be updated)\n"
1927 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
1928 "prereq nxdomain name (does this name not exist)\n"
1929 "prereq yxdomain name (does this name exist)\n"
1930 "prereq nxrrset .... (does this RRset exist)\n"
1931 "prereq yxrrset .... (does this RRset not exist)\n"
1932 "update add .... (add the given record to the zone)\n"
1933 "update delete .... (remove the given record(s) from the zone)\n");
1934 return (STATUS_MORE
);
1936 fprintf(stderr
, "incorrect section name: %s\n", word
);
1937 return (STATUS_SYNTAX
);
1940 static isc_boolean_t
1941 user_interaction(void) {
1942 isc_uint16_t result
= STATUS_MORE
;
1944 ddebug("user_interaction()");
1945 while ((result
== STATUS_MORE
) || (result
== STATUS_SYNTAX
)) {
1946 result
= get_next_command();
1947 if (!interactive
&& result
== STATUS_SYNTAX
)
1948 fatal("syntax error");
1950 if (result
== STATUS_SEND
)
1958 isc_event_t
*event
= global_event
;
1959 ddebug("done_update()");
1960 isc_task_send(global_task
, &event
);
1964 check_tsig_error(dns_rdataset_t
*rdataset
, isc_buffer_t
*b
) {
1965 isc_result_t result
;
1966 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1967 dns_rdata_any_tsig_t tsig
;
1969 result
= dns_rdataset_first(rdataset
);
1970 check_result(result
, "dns_rdataset_first");
1971 dns_rdataset_current(rdataset
, &rdata
);
1972 result
= dns_rdata_tostruct(&rdata
, &tsig
, NULL
);
1973 check_result(result
, "dns_rdata_tostruct");
1974 if (tsig
.error
!= 0) {
1975 if (isc_buffer_remaininglength(b
) < 1)
1976 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1977 isc__buffer_putstr(b
, "(" /*)*/);
1978 result
= dns_tsigrcode_totext(tsig
.error
, b
);
1979 check_result(result
, "dns_tsigrcode_totext");
1980 if (isc_buffer_remaininglength(b
) < 1)
1981 check_result(ISC_R_NOSPACE
, "isc_buffer_remaininglength");
1982 isc__buffer_putstr(b
, /*(*/ ")");
1987 update_completed(isc_task_t
*task
, isc_event_t
*event
) {
1988 dns_requestevent_t
*reqev
= NULL
;
1989 isc_result_t result
;
1990 dns_request_t
*request
;
1994 ddebug("update_completed()");
1998 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
1999 reqev
= (dns_requestevent_t
*)event
;
2000 request
= reqev
->request
;
2003 dns_request_destroy(&request
);
2004 isc_event_free(&event
);
2009 if (reqev
->result
!= ISC_R_SUCCESS
) {
2010 fprintf(stderr
, "; Communication with server failed: %s\n",
2011 isc_result_totext(reqev
->result
));
2012 seenerror
= ISC_TRUE
;
2016 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &answer
);
2017 check_result(result
, "dns_message_create");
2018 result
= dns_request_getresponse(request
, answer
,
2019 DNS_MESSAGEPARSE_PRESERVEORDER
);
2022 if (answer
->verify_attempted
)
2023 ddebug("tsig verification successful");
2025 case DNS_R_CLOCKSKEW
:
2026 case DNS_R_EXPECTEDTSIG
:
2027 case DNS_R_TSIGERRORSET
:
2028 case DNS_R_TSIGVERIFYFAILURE
:
2029 case DNS_R_UNEXPECTEDTSIG
:
2032 if (usegsstsig
&& answer
->rcode
== dns_rcode_noerror
) {
2034 * For MS DNS that violates RFC 2845, section 4.2
2039 fprintf(stderr
, "; TSIG error with server: %s\n",
2040 isc_result_totext(result
));
2041 seenerror
= ISC_TRUE
;
2044 check_result(result
, "dns_request_getresponse");
2047 if (answer
->rcode
!= dns_rcode_noerror
) {
2048 seenerror
= ISC_TRUE
;
2052 dns_rdataset_t
*rds
;
2054 isc_buffer_init(&b
, buf
, sizeof(buf
) - 1);
2055 result
= dns_rcode_totext(answer
->rcode
, &b
);
2056 check_result(result
, "dns_rcode_totext");
2057 rds
= dns_message_gettsig(answer
, NULL
);
2059 check_tsig_error(rds
, &b
);
2060 fprintf(stderr
, "update failed: %.*s\n",
2061 (int)isc_buffer_usedlength(&b
), buf
);
2065 show_message(stderr
, answer
, "\nReply from update query:");
2068 dns_request_destroy(&request
);
2070 dns_name_free(&tmpzonename
, mctx
);
2071 dns_name_free(&restart_master
, mctx
);
2073 isc_event_free(&event
);
2078 send_update(dns_name_t
*zonename
, isc_sockaddr_t
*master
,
2079 isc_sockaddr_t
*srcaddr
)
2081 isc_result_t result
;
2082 dns_request_t
*request
= NULL
;
2083 unsigned int options
= 0;
2085 ddebug("send_update()");
2090 options
|= DNS_REQUESTOPT_TCP
;
2091 if (tsigkey
== NULL
&& sig0key
!= NULL
) {
2092 result
= dns_message_setsig0key(updatemsg
, sig0key
);
2093 check_result(result
, "dns_message_setsig0key");
2096 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2098 isc_sockaddr_format(master
, addrbuf
, sizeof(addrbuf
));
2099 fprintf(stderr
, "Sending update to %s\n", addrbuf
);
2102 result
= dns_request_createvia3(requestmgr
, updatemsg
, srcaddr
,
2103 master
, options
, tsigkey
, timeout
,
2104 udp_timeout
, udp_retries
, global_task
,
2105 update_completed
, NULL
, &request
);
2106 check_result(result
, "dns_request_createvia3");
2109 show_message(stdout
, updatemsg
, "Outgoing update query:");
2115 recvsoa(isc_task_t
*task
, isc_event_t
*event
) {
2116 dns_requestevent_t
*reqev
= NULL
;
2117 dns_request_t
*request
= NULL
;
2118 isc_result_t result
, eresult
;
2119 dns_message_t
*rcvmsg
= NULL
;
2120 dns_section_t section
;
2121 dns_name_t
*name
= NULL
;
2122 dns_rdataset_t
*soaset
= NULL
;
2123 dns_rdata_soa_t soa
;
2124 dns_rdata_t soarr
= DNS_RDATA_INIT
;
2127 nsu_requestinfo_t
*reqinfo
;
2128 dns_message_t
*soaquery
= NULL
;
2129 isc_sockaddr_t
*addr
;
2130 isc_boolean_t seencname
= ISC_FALSE
;
2132 unsigned int nlabels
;
2136 ddebug("recvsoa()");
2140 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
2141 reqev
= (dns_requestevent_t
*)event
;
2142 request
= reqev
->request
;
2143 eresult
= reqev
->result
;
2144 reqinfo
= reqev
->ev_arg
;
2145 soaquery
= reqinfo
->msg
;
2146 addr
= reqinfo
->addr
;
2149 dns_request_destroy(&request
);
2150 dns_message_destroy(&soaquery
);
2151 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
2152 isc_event_free(&event
);
2157 if (eresult
!= ISC_R_SUCCESS
) {
2158 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2160 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
2161 fprintf(stderr
, "; Communication with %s failed: %s\n",
2162 addrbuf
, isc_result_totext(eresult
));
2163 if (userserver
!= NULL
)
2164 fatal("could not talk to specified name server");
2165 else if (++ns_inuse
>= lwconf
->nsnext
)
2166 fatal("could not talk to any default name server");
2167 ddebug("Destroying request [%p]", request
);
2168 dns_request_destroy(&request
);
2169 dns_message_renderreset(soaquery
);
2170 dns_message_settsigkey(soaquery
, NULL
);
2171 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2172 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
2173 isc_event_free(&event
);
2174 setzoneclass(dns_rdataclass_none
);
2178 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_requestinfo_t
));
2180 isc_event_free(&event
);
2183 ddebug("About to create rcvmsg");
2184 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
2185 check_result(result
, "dns_message_create");
2186 result
= dns_request_getresponse(request
, rcvmsg
,
2187 DNS_MESSAGEPARSE_PRESERVEORDER
);
2188 if (result
== DNS_R_TSIGERRORSET
&& userserver
!= NULL
) {
2189 dns_message_destroy(&rcvmsg
);
2190 ddebug("Destroying request [%p]", request
);
2191 dns_request_destroy(&request
);
2192 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
2193 if (reqinfo
== NULL
)
2194 fatal("out of memory");
2195 reqinfo
->msg
= soaquery
;
2196 reqinfo
->addr
= addr
;
2197 dns_message_renderreset(soaquery
);
2198 ddebug("retrying soa request without TSIG");
2199 result
= dns_request_createvia3(requestmgr
, soaquery
,
2200 localaddr
, addr
, 0, NULL
,
2203 global_task
, recvsoa
, reqinfo
,
2205 check_result(result
, "dns_request_createvia");
2209 check_result(result
, "dns_request_getresponse");
2210 section
= DNS_SECTION_ANSWER
;
2212 show_message(stderr
, rcvmsg
, "Reply from SOA query:");
2214 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
2215 rcvmsg
->rcode
!= dns_rcode_nxdomain
)
2216 fatal("response to SOA query was unsuccessful");
2218 if (userzone
!= NULL
&& rcvmsg
->rcode
== dns_rcode_nxdomain
) {
2219 char namebuf
[DNS_NAME_FORMATSIZE
];
2220 dns_name_format(userzone
, namebuf
, sizeof(namebuf
));
2221 error("specified zone '%s' does not exist (NXDOMAIN)",
2223 dns_message_destroy(&rcvmsg
);
2224 dns_request_destroy(&request
);
2225 dns_message_destroy(&soaquery
);
2226 ddebug("Out of recvsoa");
2233 section
= DNS_SECTION_ANSWER
;
2235 section
= DNS_SECTION_AUTHORITY
;
2239 result
= dns_message_firstname(rcvmsg
, section
);
2240 if (result
!= ISC_R_SUCCESS
) {
2244 while (result
== ISC_R_SUCCESS
) {
2246 dns_message_currentname(rcvmsg
, section
, &name
);
2248 result
= dns_message_findtype(name
, dns_rdatatype_soa
, 0,
2250 if (result
== ISC_R_SUCCESS
)
2252 if (section
== DNS_SECTION_ANSWER
) {
2253 dns_rdataset_t
*tset
= NULL
;
2254 if (dns_message_findtype(name
, dns_rdatatype_cname
, 0,
2255 &tset
) == ISC_R_SUCCESS
||
2256 dns_message_findtype(name
, dns_rdatatype_dname
, 0,
2257 &tset
) == ISC_R_SUCCESS
) {
2258 seencname
= ISC_TRUE
;
2263 result
= dns_message_nextname(rcvmsg
, section
);
2266 if (soaset
== NULL
&& !seencname
) {
2275 char namestr
[DNS_NAME_FORMATSIZE
];
2276 dns_name_format(name
, namestr
, sizeof(namestr
));
2277 fprintf(stderr
, "Found zone name: %s\n", namestr
);
2280 result
= dns_rdataset_first(soaset
);
2281 check_result(result
, "dns_rdataset_first");
2283 dns_rdata_init(&soarr
);
2284 dns_rdataset_current(soaset
, &soarr
);
2285 result
= dns_rdata_tostruct(&soarr
, &soa
, NULL
);
2286 check_result(result
, "dns_rdata_tostruct");
2288 dns_name_init(&master
, NULL
);
2289 dns_name_clone(&soa
.origin
, &master
);
2291 if (userzone
!= NULL
)
2292 zonename
= userzone
;
2297 char namestr
[DNS_NAME_FORMATSIZE
];
2298 dns_name_format(&master
, namestr
, sizeof(namestr
));
2299 fprintf(stderr
, "The master is: %s\n", namestr
);
2302 if (userserver
!= NULL
)
2303 serveraddr
= userserver
;
2305 char serverstr
[DNS_NAME_MAXTEXT
+1];
2308 isc_buffer_init(&buf
, serverstr
, sizeof(serverstr
));
2309 result
= dns_name_totext(&master
, ISC_TRUE
, &buf
);
2310 check_result(result
, "dns_name_totext");
2311 serverstr
[isc_buffer_usedlength(&buf
)] = 0;
2312 get_address(serverstr
, dnsport
, &tempaddr
);
2313 serveraddr
= &tempaddr
;
2315 dns_rdata_freestruct(&soa
);
2319 dns_name_init(&tmpzonename
, NULL
);
2320 dns_name_dup(zonename
, mctx
, &tmpzonename
);
2321 dns_name_init(&restart_master
, NULL
);
2322 dns_name_dup(&master
, mctx
, &restart_master
);
2323 start_gssrequest(&master
);
2325 send_update(zonename
, serveraddr
, localaddr
);
2326 setzoneclass(dns_rdataclass_none
);
2329 send_update(zonename
, serveraddr
, localaddr
);
2330 setzoneclass(dns_rdataclass_none
);
2333 dns_message_destroy(&soaquery
);
2334 dns_request_destroy(&request
);
2337 dns_message_destroy(&rcvmsg
);
2338 ddebug("Out of recvsoa");
2342 result
= dns_message_firstname(soaquery
, DNS_SECTION_QUESTION
);
2343 INSIST(result
== ISC_R_SUCCESS
);
2345 dns_message_currentname(soaquery
, DNS_SECTION_QUESTION
, &name
);
2346 nlabels
= dns_name_countlabels(name
);
2348 fatal("could not find enclosing zone");
2349 dns_name_init(&tname
, NULL
);
2350 dns_name_getlabelsequence(name
, 1, nlabels
- 1, &tname
);
2351 dns_name_clone(&tname
, name
);
2352 dns_request_destroy(&request
);
2353 dns_message_renderreset(soaquery
);
2354 dns_message_settsigkey(soaquery
, NULL
);
2355 if (userserver
!= NULL
)
2356 sendrequest(localaddr
, userserver
, soaquery
, &request
);
2358 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2363 sendrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
2364 dns_message_t
*msg
, dns_request_t
**request
)
2366 isc_result_t result
;
2367 nsu_requestinfo_t
*reqinfo
;
2369 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_requestinfo_t
));
2370 if (reqinfo
== NULL
)
2371 fatal("out of memory");
2373 reqinfo
->addr
= destaddr
;
2374 result
= dns_request_createvia3(requestmgr
, msg
, srcaddr
, destaddr
, 0,
2375 (userserver
!= NULL
) ? tsigkey
: NULL
,
2376 FIND_TIMEOUT
* 20, FIND_TIMEOUT
, 3,
2377 global_task
, recvsoa
, reqinfo
, request
);
2378 check_result(result
, "dns_request_createvia");
2384 start_gssrequest(dns_name_t
*master
)
2386 gss_ctx_id_t context
;
2388 isc_result_t result
;
2389 isc_uint32_t val
= 0;
2390 dns_message_t
*rmsg
;
2391 dns_request_t
*request
= NULL
;
2392 dns_name_t
*servname
;
2393 dns_fixedname_t fname
;
2394 char namestr
[DNS_NAME_FORMATSIZE
];
2395 char keystr
[DNS_NAME_FORMATSIZE
];
2397 debug("start_gssrequest");
2400 if (gssring
!= NULL
)
2401 dns_tsigkeyring_destroy(&gssring
);
2403 result
= dns_tsigkeyring_create(mctx
, &gssring
);
2405 if (result
!= ISC_R_SUCCESS
)
2406 fatal("dns_tsigkeyring_create failed: %s",
2407 isc_result_totext(result
));
2409 dns_name_format(master
, namestr
, sizeof(namestr
));
2410 if (kserver
== NULL
) {
2411 kserver
= isc_mem_get(mctx
, sizeof(isc_sockaddr_t
));
2412 if (kserver
== NULL
)
2413 fatal("out of memory");
2415 if (userserver
== NULL
)
2416 get_address(namestr
, dnsport
, kserver
);
2418 (void)memcpy(kserver
, userserver
, sizeof(isc_sockaddr_t
));
2420 dns_fixedname_init(&fname
);
2421 servname
= dns_fixedname_name(&fname
);
2423 result
= isc_string_printf(servicename
, sizeof(servicename
),
2425 if (result
!= ISC_R_SUCCESS
)
2426 fatal("isc_string_printf(servicename) failed: %s",
2427 isc_result_totext(result
));
2428 isc_buffer_init(&buf
, servicename
, strlen(servicename
));
2429 isc_buffer_add(&buf
, strlen(servicename
));
2430 result
= dns_name_fromtext(servname
, &buf
, dns_rootname
, 0, NULL
);
2431 if (result
!= ISC_R_SUCCESS
)
2432 fatal("dns_name_fromtext(servname) failed: %s",
2433 isc_result_totext(result
));
2435 dns_fixedname_init(&fkname
);
2436 keyname
= dns_fixedname_name(&fkname
);
2438 isc_random_get(&val
);
2439 result
= isc_string_printf(keystr
, sizeof(keystr
), "%u.sig-%s",
2441 if (result
!= ISC_R_SUCCESS
)
2442 fatal("isc_string_printf(keystr) failed: %s",
2443 isc_result_totext(result
));
2444 isc_buffer_init(&buf
, keystr
, strlen(keystr
));
2445 isc_buffer_add(&buf
, strlen(keystr
));
2447 result
= dns_name_fromtext(keyname
, &buf
, dns_rootname
, 0, NULL
);
2448 if (result
!= ISC_R_SUCCESS
)
2449 fatal("dns_name_fromtext(keyname) failed: %s",
2450 isc_result_totext(result
));
2452 /* Windows doesn't recognize name compression in the key name. */
2453 keyname
->attributes
|= DNS_NAMEATTR_NOCOMPRESS
;
2456 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
, &rmsg
);
2457 if (result
!= ISC_R_SUCCESS
)
2458 fatal("dns_message_create failed: %s",
2459 isc_result_totext(result
));
2461 /* Build first request. */
2463 context
= GSS_C_NO_CONTEXT
;
2464 result
= dns_tkey_buildgssquery(rmsg
, keyname
, servname
, NULL
, 0,
2465 &context
, use_win2k_gsstsig
);
2466 if (result
== ISC_R_FAILURE
)
2467 fatal("Check your Kerberos ticket, it may have expired.");
2468 if (result
!= ISC_R_SUCCESS
)
2469 fatal("dns_tkey_buildgssquery failed: %s",
2470 isc_result_totext(result
));
2472 send_gssrequest(localaddr
, kserver
, rmsg
, &request
, context
);
2476 send_gssrequest(isc_sockaddr_t
*srcaddr
, isc_sockaddr_t
*destaddr
,
2477 dns_message_t
*msg
, dns_request_t
**request
,
2478 gss_ctx_id_t context
)
2480 isc_result_t result
;
2481 nsu_gssinfo_t
*reqinfo
;
2482 unsigned int options
= 0;
2484 debug("send_gssrequest");
2485 reqinfo
= isc_mem_get(mctx
, sizeof(nsu_gssinfo_t
));
2486 if (reqinfo
== NULL
)
2487 fatal("out of memory");
2489 reqinfo
->addr
= destaddr
;
2490 reqinfo
->context
= context
;
2492 options
|= DNS_REQUESTOPT_TCP
;
2493 result
= dns_request_createvia3(requestmgr
, msg
, srcaddr
, destaddr
,
2494 options
, tsigkey
, FIND_TIMEOUT
* 20,
2495 FIND_TIMEOUT
, 3, global_task
, recvgss
,
2497 check_result(result
, "dns_request_createvia3");
2499 show_message(stdout
, msg
, "Outgoing update query:");
2504 recvgss(isc_task_t
*task
, isc_event_t
*event
) {
2505 dns_requestevent_t
*reqev
= NULL
;
2506 dns_request_t
*request
= NULL
;
2507 isc_result_t result
, eresult
;
2508 dns_message_t
*rcvmsg
= NULL
;
2509 nsu_gssinfo_t
*reqinfo
;
2510 dns_message_t
*tsigquery
= NULL
;
2511 isc_sockaddr_t
*addr
;
2512 gss_ctx_id_t context
;
2514 dns_name_t
*servname
;
2515 dns_fixedname_t fname
;
2519 ddebug("recvgss()");
2523 REQUIRE(event
->ev_type
== DNS_EVENT_REQUESTDONE
);
2524 reqev
= (dns_requestevent_t
*)event
;
2525 request
= reqev
->request
;
2526 eresult
= reqev
->result
;
2527 reqinfo
= reqev
->ev_arg
;
2528 tsigquery
= reqinfo
->msg
;
2529 context
= reqinfo
->context
;
2530 addr
= reqinfo
->addr
;
2533 dns_request_destroy(&request
);
2534 dns_message_destroy(&tsigquery
);
2535 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2536 isc_event_free(&event
);
2541 if (eresult
!= ISC_R_SUCCESS
) {
2542 char addrbuf
[ISC_SOCKADDR_FORMATSIZE
];
2544 isc_sockaddr_format(addr
, addrbuf
, sizeof(addrbuf
));
2545 fprintf(stderr
, "; Communication with %s failed: %s\n",
2546 addrbuf
, isc_result_totext(eresult
));
2547 if (userserver
!= NULL
)
2548 fatal("could not talk to specified name server");
2549 else if (++ns_inuse
>= lwconf
->nsnext
)
2550 fatal("could not talk to any default name server");
2551 ddebug("Destroying request [%p]", request
);
2552 dns_request_destroy(&request
);
2553 dns_message_renderreset(tsigquery
);
2554 sendrequest(localaddr
, &servers
[ns_inuse
], tsigquery
,
2556 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2557 isc_event_free(&event
);
2560 isc_mem_put(mctx
, reqinfo
, sizeof(nsu_gssinfo_t
));
2562 isc_event_free(&event
);
2565 ddebug("recvgss creating rcvmsg");
2566 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &rcvmsg
);
2567 check_result(result
, "dns_message_create");
2569 result
= dns_request_getresponse(request
, rcvmsg
,
2570 DNS_MESSAGEPARSE_PRESERVEORDER
);
2571 check_result(result
, "dns_request_getresponse");
2574 show_message(stderr
, rcvmsg
,
2575 "recvmsg reply from GSS-TSIG query");
2577 if (rcvmsg
->rcode
== dns_rcode_formerr
&& !tried_other_gsstsig
) {
2578 ddebug("recvgss trying %s GSS-TSIG",
2579 use_win2k_gsstsig
? "Standard" : "Win2k");
2580 if (use_win2k_gsstsig
)
2581 use_win2k_gsstsig
= ISC_FALSE
;
2583 use_win2k_gsstsig
= ISC_TRUE
;
2584 tried_other_gsstsig
= ISC_TRUE
;
2585 start_gssrequest(&restart_master
);
2589 if (rcvmsg
->rcode
!= dns_rcode_noerror
&&
2590 rcvmsg
->rcode
!= dns_rcode_nxdomain
)
2591 fatal("response to GSS-TSIG query was unsuccessful");
2594 dns_fixedname_init(&fname
);
2595 servname
= dns_fixedname_name(&fname
);
2596 isc_buffer_init(&buf
, servicename
, strlen(servicename
));
2597 isc_buffer_add(&buf
, strlen(servicename
));
2598 result
= dns_name_fromtext(servname
, &buf
, dns_rootname
, 0, NULL
);
2599 check_result(result
, "dns_name_fromtext");
2602 result
= dns_tkey_gssnegotiate(tsigquery
, rcvmsg
, servname
,
2603 &context
, &tsigkey
, gssring
,
2607 case DNS_R_CONTINUE
:
2608 send_gssrequest(localaddr
, kserver
, tsigquery
, &request
,
2614 * XXXSRA Waaay too much fun here. There's no good
2615 * reason why we need a TSIG here (the people who put
2616 * it into the spec admitted at the time that it was
2617 * not a security issue), and Windows clients don't
2618 * seem to work if named complies with the spec and
2619 * includes the gratuitous TSIG. So we're in the
2620 * bizarre situation of having to choose between
2621 * complying with a useless requirement in the spec
2622 * and interoperating. This is nuts. If we can
2623 * confirm this behavior, we should ask the WG to
2624 * consider removing the requirement for the
2625 * gratuitous TSIG here. For the moment, we ignore
2626 * the TSIG -- this too is a spec violation, but it's
2627 * the least insane thing to do.
2631 * Verify the signature.
2633 rcvmsg
->state
= DNS_SECTION_ANY
;
2634 dns_message_setquerytsig(rcvmsg
, NULL
);
2635 result
= dns_message_settsigkey(rcvmsg
, tsigkey
);
2636 check_result(result
, "dns_message_settsigkey");
2637 result
= dns_message_checksig(rcvmsg
, NULL
);
2638 ddebug("tsig verification: %s", dns_result_totext(result
));
2639 check_result(result
, "dns_message_checksig");
2642 send_update(&tmpzonename
, serveraddr
, localaddr
);
2643 setzoneclass(dns_rdataclass_none
);
2647 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result
));
2651 dns_request_destroy(&request
);
2652 dns_message_destroy(&tsigquery
);
2654 dns_message_destroy(&rcvmsg
);
2655 ddebug("Out of recvgss");
2660 start_update(void) {
2661 isc_result_t result
;
2662 dns_rdataset_t
*rdataset
= NULL
;
2663 dns_name_t
*name
= NULL
;
2664 dns_request_t
*request
= NULL
;
2665 dns_message_t
*soaquery
= NULL
;
2666 dns_name_t
*firstname
;
2667 dns_section_t section
= DNS_SECTION_UPDATE
;
2669 ddebug("start_update()");
2672 dns_message_destroy(&answer
);
2674 if (userzone
!= NULL
&& userserver
!= NULL
&& ! usegsstsig
) {
2675 send_update(userzone
, userserver
, localaddr
);
2676 setzoneclass(dns_rdataclass_none
);
2680 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
2682 check_result(result
, "dns_message_create");
2684 if (userserver
== NULL
)
2685 soaquery
->flags
|= DNS_MESSAGEFLAG_RD
;
2687 result
= dns_message_gettempname(soaquery
, &name
);
2688 check_result(result
, "dns_message_gettempname");
2690 result
= dns_message_gettemprdataset(soaquery
, &rdataset
);
2691 check_result(result
, "dns_message_gettemprdataset");
2693 dns_rdataset_makequestion(rdataset
, getzoneclass(), dns_rdatatype_soa
);
2695 if (userzone
!= NULL
) {
2696 dns_name_init(name
, NULL
);
2697 dns_name_clone(userzone
, name
);
2699 result
= dns_message_firstname(updatemsg
, section
);
2700 if (result
== ISC_R_NOMORE
) {
2701 section
= DNS_SECTION_PREREQUISITE
;
2702 result
= dns_message_firstname(updatemsg
, section
);
2704 if (result
!= ISC_R_SUCCESS
) {
2705 dns_message_puttempname(soaquery
, &name
);
2706 dns_rdataset_disassociate(rdataset
);
2707 dns_message_puttemprdataset(soaquery
, &rdataset
);
2708 dns_message_destroy(&soaquery
);
2713 dns_message_currentname(updatemsg
, section
, &firstname
);
2714 dns_name_init(name
, NULL
);
2715 dns_name_clone(firstname
, name
);
2718 ISC_LIST_INIT(name
->list
);
2719 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
2720 dns_message_addname(soaquery
, name
, DNS_SECTION_QUESTION
);
2722 if (userserver
!= NULL
)
2723 sendrequest(localaddr
, userserver
, soaquery
, &request
);
2726 sendrequest(localaddr
, &servers
[ns_inuse
], soaquery
, &request
);
2732 ddebug("cleanup()");
2735 dns_message_destroy(&answer
);
2738 if (tsigkey
!= NULL
) {
2739 ddebug("detach tsigkey x%p", tsigkey
);
2740 dns_tsigkey_detach(&tsigkey
);
2742 if (gssring
!= NULL
) {
2743 ddebug("Destroying GSS-TSIG keyring");
2744 dns_tsigkeyring_destroy(&gssring
);
2746 if (kserver
!= NULL
) {
2747 isc_mem_put(mctx
, kserver
, sizeof(isc_sockaddr_t
));
2752 ddebug("Shutting down task manager");
2753 isc_taskmgr_destroy(&taskmgr
);
2755 ddebug("Destroying event");
2756 isc_event_free(&global_event
);
2758 ddebug("Shutting down socket manager");
2759 isc_socketmgr_destroy(&socketmgr
);
2761 ddebug("Shutting down timer manager");
2762 isc_timermgr_destroy(&timermgr
);
2764 ddebug("Destroying hash context");
2767 ddebug("Destroying name state");
2770 ddebug("Removing log context");
2771 isc_log_destroy(&lctx
);
2773 ddebug("Destroying memory context");
2775 isc_mem_stats(mctx
, stderr
);
2776 isc_mem_destroy(&mctx
);
2780 getinput(isc_task_t
*task
, isc_event_t
*event
) {
2790 if (global_event
== NULL
)
2791 global_event
= event
;
2794 more
= user_interaction();
2804 main(int argc
, char **argv
) {
2805 isc_result_t result
;
2806 style
= &dns_master_style_debug
;
2810 interactive
= ISC_TF(isatty(0));
2814 pre_parse_args(argc
, argv
);
2816 result
= isc_mem_create(0, 0, &mctx
);
2817 check_result(result
, "isc_mem_create");
2819 parse_args(argc
, argv
, mctx
, &entropy
);
2823 result
= isc_app_onrun(mctx
, global_task
, getinput
, NULL
);
2824 check_result(result
, "isc_app_onrun");
2826 (void)isc_app_run();