Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / nsupdate / nsupdate.c
blob428860674c8e9e210adc467ec0623d988dec80b1
1 /* $NetBSD$ */
3 /*
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 */
22 /*! \file */
24 #include <config.h>
26 #include <ctype.h>
27 #include <errno.h>
28 #include <limits.h>
29 #include <stdlib.h>
30 #include <unistd.h>
32 #include <isc/app.h>
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>
38 #include <isc/file.h>
39 #include <isc/hash.h>
40 #include <isc/lex.h>
41 #include <isc/log.h>
42 #include <isc/mem.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>
51 #include <isc/task.h>
52 #include <isc/timer.h>
53 #include <isc/types.h>
54 #include <isc/util.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>
63 #include <dns/log.h>
64 #include <dns/masterdump.h>
65 #include <dns/message.h>
66 #include <dns/name.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>
76 #include <dns/tkey.h>
77 #include <dns/tsig.h>
79 #include <dst/dst.h>
81 #include <lwres/lwres.h>
82 #include <lwres/net.h>
84 #ifdef GSSAPI
85 #include <dst/gssapi.h>
86 #endif
87 #include <bind9/getaddresses.h>
90 #ifdef HAVE_ADDRINFO
91 #ifdef HAVE_GETADDRINFO
92 #ifdef HAVE_GAISTRERROR
93 #define USE_GETADDRINFO
94 #endif
95 #endif
96 #endif
98 #ifndef USE_GETADDRINFO
99 #ifndef ISC_PLATFORM_NONSTDHERRNO
100 extern int h_errno;
101 #endif
102 #endif
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;
116 #ifndef RESOLV_CONF
117 #define RESOLV_CONF "/etc/resolv.conf"
118 #endif
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;
163 static FILE *input;
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 {
179 dns_message_t *msg;
180 isc_sockaddr_t *addr;
181 } nsu_requestinfo_t;
183 static void
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;
191 static void
192 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
194 static void
195 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
197 #ifdef GSSAPI
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 {
203 dns_message_t *msg;
204 isc_sockaddr_t *addr;
205 gss_ctx_id_t context;
206 } nsu_gssinfo_t;
208 static void
209 start_gssrequest(dns_name_t *master);
210 static void
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);
214 static void
215 recvgss(isc_task_t *task, isc_event_t *event);
216 #endif /* GSSAPI */
218 static void
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;
230 isc_mem_t *mctx;
231 ISC_LINK(entropysource_t) link;
234 static ISC_LIST(entropysource_t) sources;
236 static void
237 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
239 isc_result_t result;
240 isc_entropysource_t *source = NULL;
241 entropysource_t *elt;
242 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
244 REQUIRE(ectx != NULL);
246 if (*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;
255 randomfile = NULL;
258 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
259 usekeyboard);
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));
267 if (elt == NULL)
268 fatal("out of memory");
269 elt->source = source;
270 elt->mctx = mctx;
271 ISC_LINK_INIT(elt, link);
272 ISC_LIST_APPEND(sources, elt, link);
276 static void
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
290 getzoneclass(void) {
291 if (zoneclass == dns_rdataclass_none)
292 zoneclass = defaultclass;
293 return (zoneclass);
296 static isc_boolean_t
297 setzoneclass(dns_rdataclass_t rdclass) {
298 if (zoneclass == dns_rdataclass_none ||
299 rdclass == dns_rdataclass_none)
300 zoneclass = rdclass;
301 if (zoneclass != rdclass)
302 return (ISC_FALSE);
303 return (ISC_TRUE);
306 static void
307 fatal(const char *format, ...) {
308 va_list args;
310 va_start(args, format);
311 vfprintf(stderr, format, args);
312 va_end(args);
313 fprintf(stderr, "\n");
314 exit(1);
317 static void
318 error(const char *format, ...) {
319 va_list args;
321 va_start(args, format);
322 vfprintf(stderr, format, args);
323 va_end(args);
324 fprintf(stderr, "\n");
327 static void
328 debug(const char *format, ...) {
329 va_list args;
331 if (debugging) {
332 va_start(args, format);
333 vfprintf(stderr, format, args);
334 va_end(args);
335 fprintf(stderr, "\n");
339 static void
340 ddebug(const char *format, ...) {
341 va_list args;
343 if (ddebugging) {
344 va_start(args, format);
345 vfprintf(stderr, format, args);
346 va_end(args);
347 fprintf(stderr, "\n");
351 static inline void
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));
357 static void *
358 mem_alloc(void *arg, size_t size) {
359 return (isc_mem_get(arg, size));
362 static void
363 mem_free(void *arg, void *mem, size_t size) {
364 isc_mem_put(arg, mem, size);
367 static char *
368 nsu_strsep(char **stringp, const char *delim) {
369 char *string = *stringp;
370 char *s;
371 const char *d;
372 char sc, dc;
374 if (string == NULL)
375 return (NULL);
377 for (; *string != '\0'; string++) {
378 sc = *string;
379 for (d = delim; (dc = *d) != '\0'; d++) {
380 if (sc == dc)
381 break;
383 if (dc == 0)
384 break;
387 for (s = string; *s != '\0'; s++) {
388 sc = *s;
389 for (d = delim; (dc = *d) != '\0'; d++) {
390 if (sc == dc) {
391 *s++ = '\0';
392 *stringp = s;
393 return (string);
397 *stringp = NULL;
398 return (string);
401 static void
402 reset_system(void) {
403 isc_result_t result;
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);
409 else {
410 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
411 &updatemsg);
412 check_result(result, "dns_message_create");
414 updatemsg->opcode = dns_opcode_update;
415 if (usegsstsig) {
416 if (tsigkey != NULL)
417 dns_tsigkey_detach(&tsigkey);
418 if (gssring != NULL)
419 dns_tsigkeyring_destroy(&gssring);
420 tried_other_gsstsig = ISC_FALSE;
424 static isc_uint16_t
425 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
426 isc_uint16_t digestbits = 0;
427 isc_result_t result;
428 char buf[20];
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);
437 buf[len] = 0;
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;
487 } else
488 fatal("unknown key type '%s'", buf);
489 return (digestbits);
492 static void
493 setup_keystr(void) {
494 unsigned char *secret = NULL;
495 int secretlen;
496 isc_buffer_t secretbuf;
497 isc_result_t result;
498 isc_buffer_t keynamesrc;
499 char *secretstr;
500 char *s, *n;
501 dns_fixedname_t fkeyname;
502 dns_name_t *keyname;
503 char *name;
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");
515 secretstr = s + 1;
516 n = strchr(secretstr, ':');
517 if (n != NULL) {
518 if (n == secretstr || n[1] == 0)
519 fatal("key option must specify [hmac:]keyname:secret");
520 name = secretstr;
521 secretstr = n + 1;
522 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
523 } else {
524 hmacname = DNS_TSIG_HMACMD5_NAME;
525 name = keystr;
526 n = s;
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);
538 if (secret == NULL)
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));
546 goto failure;
549 secretlen = isc_buffer_usedlength(&secretbuf);
551 debug("keycreate");
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));
557 else
558 dst_key_setbits(tsigkey->key, digestbits);
559 failure:
560 if (secret != NULL)
561 isc_mem_free(mctx, secret);
565 * Get a key from a named.conf format keyfile
567 static isc_result_t
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;
574 const char *keyname;
575 const char *secretstr;
576 const char *algorithm;
577 isc_result_t result;
578 int len;
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)
585 goto cleanup;
587 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
588 &sessionkey);
589 if (result != ISC_R_SUCCESS)
590 goto cleanup;
592 result = cfg_map_get(sessionkey, "key", &key);
593 if (result != ISC_R_SUCCESS)
594 goto cleanup;
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);
608 setup_keystr();
610 cleanup:
611 if (pctx != NULL) {
612 if (sessionkey != NULL)
613 cfg_obj_destroy(pctx, &sessionkey);
614 cfg_parser_destroy(&pctx);
617 if (keystr != NULL)
618 isc_mem_free(mctx, keystr);
620 return (result);
623 static void
624 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
625 dst_key_t *dstkey = NULL;
626 isc_result_t result;
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,
634 &dstkey);
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)
640 return;
643 if (result != ISC_R_SUCCESS) {
644 fprintf(stderr, "could not read key from %s: %s\n",
645 keyfile, isc_result_totext(result));
646 return;
649 switch (dst_key_alg(dstkey)) {
650 case DST_ALG_HMACMD5:
651 hmacname = DNS_TSIG_HMACMD5_NAME;
652 break;
653 case DST_ALG_HMACSHA1:
654 hmacname = DNS_TSIG_HMACSHA1_NAME;
655 break;
656 case DST_ALG_HMACSHA224:
657 hmacname = DNS_TSIG_HMACSHA224_NAME;
658 break;
659 case DST_ALG_HMACSHA256:
660 hmacname = DNS_TSIG_HMACSHA256_NAME;
661 break;
662 case DST_ALG_HMACSHA384:
663 hmacname = DNS_TSIG_HMACSHA384_NAME;
664 break;
665 case DST_ALG_HMACSHA512:
666 hmacname = DNS_TSIG_HMACSHA512_NAME;
667 break;
669 if (hmacname != NULL) {
670 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
671 hmacname, dstkey, ISC_FALSE,
672 NULL, 0, 0, mctx, NULL,
673 &tsigkey);
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);
678 return;
680 } else
681 sig0key = dstkey;
684 static void
685 doshutdown(void) {
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);
707 if (is_dst_up) {
708 ddebug("Destroy DST lib");
709 dst_lib_destroy();
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");
724 if (have_ipv4)
725 dns_dispatch_detach(&dispatchv4);
726 if (have_ipv6)
727 dns_dispatch_detach(&dispatchv6);
729 ddebug("Shutting down dispatch manager");
730 dns_dispatchmgr_destroy(&dispatchmgr);
734 static void
735 maybeshutdown(void) {
736 ddebug("Shutting down request manager");
737 dns_requestmgr_shutdown(requestmgr);
739 if (requests != 0)
740 return;
742 doshutdown();
745 static void
746 shutdown_program(isc_task_t *task, isc_event_t *event) {
747 REQUIRE(task == global_task);
748 UNUSED(task);
750 ddebug("shutdown_program()");
751 isc_event_free(&event);
753 shuttingdown = ISC_TRUE;
754 maybeshutdown();
757 static void
758 setup_system(void) {
759 isc_result_t result;
760 isc_sockaddr_t bind_any, bind_any6;
761 lwres_result_t lwresult;
762 unsigned int attrs, attrmask;
763 int i;
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);
785 dns_log_init(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;
801 if (ns_total <= 0) {
802 /* No name servers in resolv.conf; default to loopback. */
803 struct in_addr localhost;
804 ns_total = 1;
805 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
806 if (servers == NULL)
807 fatal("out of memory");
808 localhost.s_addr = htonl(INADDR_LOOPBACK);
809 isc_sockaddr_fromin(&servers[0], &localhost, dnsport);
810 } else {
811 servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
812 if (servers == NULL)
813 fatal("out of memory");
814 for (i = 0; i < ns_total; i++) {
815 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
816 struct in_addr in4;
817 memcpy(&in4, lwconf->nameservers[i].address, 4);
818 isc_sockaddr_fromin(&servers[i], &in4, dnsport);
819 } else {
820 struct in6_addr in6;
821 memcpy(&in6, lwconf->nameservers[i].address, 16);
822 isc_sockaddr_fromin6(&servers[i], &in6,
823 dnsport);
828 setup_entropy(mctx, NULL, &entropy);
830 result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
831 check_result(result, "isc_hash_create");
832 isc_hash_init();
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;
859 if (have_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,
866 4, 2, 3, 5,
867 attrs, attrmask, &dispatchv6);
868 check_result(result, "dns_dispatch_getudp (v6)");
871 if (have_ipv4) {
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,
878 4, 2, 3, 5,
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");
888 if (keystr != NULL)
889 setup_keystr();
890 else if (local_only)
891 read_sessionkey(mctx, lctx);
892 else if (keyfile != NULL)
893 setup_keyfile(mctx, lctx);
896 static void
897 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
898 int count;
899 isc_result_t result;
901 isc_app_block();
902 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
903 isc_app_unblock();
904 if (result != ISC_R_SUCCESS)
905 fatal("couldn't get address for '%s': %s",
906 host, isc_result_totext(result));
907 INSIST(count == 1);
910 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:rR::t:u:"
912 static void
913 pre_parse_args(int argc, char **argv) {
914 int ch;
916 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
917 switch (ch) {
918 case 'M': /* was -dm */
919 debugging = ISC_TRUE;
920 ddebugging = ISC_TRUE;
921 memdebugging = ISC_TRUE;
922 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
923 ISC_MEM_DEBUGRECORD;
924 break;
926 case '?':
927 case 'h':
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");
934 exit(1);
936 default:
937 break;
940 isc_commandline_reset = ISC_TRUE;
941 isc_commandline_index = 1;
944 static void
945 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
946 int ch;
947 isc_uint32_t i;
948 isc_result_t result;
950 debug("parse_args");
951 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
952 switch (ch) {
953 case 'd':
954 debugging = ISC_TRUE;
955 break;
956 case 'D': /* was -dd */
957 debugging = ISC_TRUE;
958 ddebugging = ISC_TRUE;
959 break;
960 case 'M':
961 break;
962 case 'l':
963 local_only = ISC_TRUE;
964 break;
965 case 'L':
966 result = isc_parse_uint32(&i, isc_commandline_argument,
967 10);
968 if (result != ISC_R_SUCCESS) {
969 fprintf(stderr, "bad library debug value "
970 "'%s'\n", isc_commandline_argument);
971 exit(1);
973 logdebuglevel = i;
974 break;
975 case 'y':
976 keystr = isc_commandline_argument;
977 break;
978 case 'v':
979 usevc = ISC_TRUE;
980 break;
981 case 'k':
982 keyfile = isc_commandline_argument;
983 break;
984 case 'g':
985 usegsstsig = ISC_TRUE;
986 use_win2k_gsstsig = ISC_FALSE;
987 break;
988 case 'o':
989 usegsstsig = ISC_TRUE;
990 use_win2k_gsstsig = ISC_TRUE;
991 break;
992 case 'p':
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);
998 exit(1);
1000 break;
1001 case 't':
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);
1006 exit(1);
1008 if (timeout == 0)
1009 timeout = UINT_MAX;
1010 break;
1011 case 'u':
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);
1016 exit(1);
1018 if (udp_timeout == 0)
1019 udp_timeout = UINT_MAX;
1020 break;
1021 case 'r':
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);
1026 exit(1);
1028 break;
1030 case 'R':
1031 setup_entropy(mctx, isc_commandline_argument, ectx);
1032 break;
1034 default:
1035 fprintf(stderr, "%s: unhandled option: %c\n",
1036 argv[0], isc_commandline_option);
1037 exit(1);
1040 if (keyfile != NULL && keystr != NULL) {
1041 fprintf(stderr, "%s: cannot specify both -k and -y\n",
1042 argv[0]);
1043 exit(1);
1046 if (local_only) {
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);
1062 #ifdef GSSAPI
1063 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1064 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1065 argv[0]);
1066 exit(1);
1068 #else
1069 if (usegsstsig) {
1070 fprintf(stderr, "%s: cannot specify -g or -o, " \
1071 "program not linked with GSS API Library\n",
1072 argv[0]);
1073 exit(1);
1075 #endif
1077 if (argv[isc_commandline_index] != NULL) {
1078 if (strcmp(argv[isc_commandline_index], "-") == 0) {
1079 input = stdin;
1080 } else {
1081 result = isc_stdio_open(argv[isc_commandline_index],
1082 "r", &input);
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));
1087 exit(1);
1090 interactive = ISC_FALSE;
1094 static isc_uint16_t
1095 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1096 isc_result_t result;
1097 char *word;
1098 isc_buffer_t *namebuf = NULL;
1099 isc_buffer_t source;
1101 word = nsu_strsep(cmdlinep, " \t\r\n");
1102 if (*word == 0) {
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);
1122 static isc_uint16_t
1123 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1124 dns_rdatatype_t rdatatype, dns_message_t *msg,
1125 dns_rdata_t *rdata)
1127 char *cmdline = *cmdlinep;
1128 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1129 isc_region_t r;
1130 isc_lex_t *lex = NULL;
1131 dns_rdatacallbacks_t callbacks;
1132 isc_result_t result;
1134 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1135 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,
1149 &callbacks);
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);
1160 } else {
1161 fprintf(stderr, "invalid rdata format: %s\n",
1162 isc_result_totext(result));
1163 isc_buffer_free(&buf);
1164 return (STATUS_SYNTAX);
1166 } else {
1167 rdata->flags = DNS_RDATA_UPDATE;
1169 *cmdlinep = cmdline;
1170 return (STATUS_MORE);
1173 static isc_uint16_t
1174 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1175 isc_result_t result;
1176 char *word;
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)
1193 return (retval);
1196 * If this is an rrset prereq, read the class or type.
1198 if (isrrset) {
1199 word = nsu_strsep(&cmdline, " \t\r\n");
1200 if (*word == 0) {
1201 fprintf(stderr, "could not read class or type\n");
1202 goto failure;
1204 region.base = word;
1205 region.length = strlen(word);
1206 result = dns_rdataclass_fromtext(&rdataclass, &region);
1207 if (result == ISC_R_SUCCESS) {
1208 if (!setzoneclass(rdataclass)) {
1209 fprintf(stderr, "class mismatch: %s\n", word);
1210 goto failure;
1213 * Now read the type.
1215 word = nsu_strsep(&cmdline, " \t\r\n");
1216 if (*word == 0) {
1217 fprintf(stderr, "could not read type\n");
1218 goto failure;
1220 region.base = word;
1221 region.length = strlen(word);
1222 result = dns_rdatatype_fromtext(&rdatatype, &region);
1223 if (result != ISC_R_SUCCESS) {
1224 fprintf(stderr, "invalid type: %s\n", word);
1225 goto failure;
1227 } else {
1228 rdataclass = getzoneclass();
1229 result = dns_rdatatype_fromtext(&rdatatype, &region);
1230 if (result != ISC_R_SUCCESS) {
1231 fprintf(stderr, "invalid type: %s\n", word);
1232 goto failure;
1235 } else
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,
1245 updatemsg, rdata);
1246 if (retval != STATUS_MORE)
1247 goto failure;
1248 } else
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;
1257 if (ispositive) {
1258 if (isrrset && rdata->data != NULL)
1259 rdatalist->rdclass = rdataclass;
1260 else
1261 rdatalist->rdclass = dns_rdataclass_any;
1262 } else
1263 rdatalist->rdclass = dns_rdataclass_none;
1264 rdatalist->covers = 0;
1265 rdatalist->ttl = 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);
1277 failure:
1278 if (name != NULL)
1279 dns_message_puttempname(updatemsg, &name);
1280 return (STATUS_SYNTAX);
1283 static isc_uint16_t
1284 evaluate_prereq(char *cmdline) {
1285 char *word;
1286 isc_boolean_t ispositive, isrrset;
1288 ddebug("evaluate_prereq()");
1289 word = nsu_strsep(&cmdline, " \t\r\n");
1290 if (*word == 0) {
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;
1302 isrrset = ISC_TRUE;
1303 } else if (strcasecmp(word, "yxrrset") == 0) {
1304 ispositive = ISC_TRUE;
1305 isrrset = ISC_TRUE;
1306 } else {
1307 fprintf(stderr, "incorrect operation code: %s\n", word);
1308 return (STATUS_SYNTAX);
1310 return (make_prereq(cmdline, ispositive, isrrset));
1313 static isc_uint16_t
1314 evaluate_server(char *cmdline) {
1315 char *word, *server;
1316 long port;
1318 if (local_only) {
1319 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1320 return (STATUS_SYNTAX);
1323 word = nsu_strsep(&cmdline, " \t\r\n");
1324 if (*word == 0) {
1325 fprintf(stderr, "could not read server name\n");
1326 return (STATUS_SYNTAX);
1328 server = word;
1330 word = nsu_strsep(&cmdline, " \t\r\n");
1331 if (*word == 0)
1332 port = dnsport;
1333 else {
1334 char *endp;
1335 port = strtol(word, &endp, 10);
1336 if (*endp != 0) {
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);
1357 static isc_uint16_t
1358 evaluate_local(char *cmdline) {
1359 char *word, *local;
1360 long port;
1361 struct in_addr in4;
1362 struct in6_addr in6;
1364 word = nsu_strsep(&cmdline, " \t\r\n");
1365 if (*word == 0) {
1366 fprintf(stderr, "could not read server name\n");
1367 return (STATUS_SYNTAX);
1369 local = word;
1371 word = nsu_strsep(&cmdline, " \t\r\n");
1372 if (*word == 0)
1373 port = 0;
1374 else {
1375 char *endp;
1376 port = strtol(word, &endp, 10);
1377 if (*endp != 0) {
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);
1397 else {
1398 fprintf(stderr, "invalid address %s", local);
1399 return (STATUS_SYNTAX);
1402 return (STATUS_MORE);
1405 static isc_uint16_t
1406 evaluate_key(char *cmdline) {
1407 char *namestr;
1408 char *secretstr;
1409 isc_buffer_t b;
1410 isc_result_t result;
1411 dns_fixedname_t fkeyname;
1412 dns_name_t *keyname;
1413 int secretlen;
1414 unsigned char *secret = NULL;
1415 isc_buffer_t secretbuf;
1416 dns_name_t *hmacname = NULL;
1417 isc_uint16_t digestbits = 0;
1418 char *n;
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, ':');
1430 if (n != NULL) {
1431 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1432 namestr = n + 1;
1433 } else
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);
1451 if (secret == NULL)
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,
1468 &tsigkey);
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);
1479 static isc_uint16_t
1480 evaluate_zone(char *cmdline) {
1481 char *word;
1482 isc_buffer_t b;
1483 isc_result_t result;
1485 word = nsu_strsep(&cmdline, " \t\r\n");
1486 if (*word == 0) {
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);
1505 static isc_uint16_t
1506 evaluate_ttl(char *cmdline) {
1507 char *word;
1508 isc_result_t result;
1509 isc_uint32_t ttl;
1511 word = nsu_strsep(&cmdline, " \t\r\n");
1512 if (*word == 0) {
1513 fprintf(stderr, "could not ttl\n");
1514 return (STATUS_SYNTAX);
1517 if (!strcasecmp(word, "none")) {
1518 default_ttl = 0;
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",
1529 word, TTL_MAX);
1530 return (STATUS_SYNTAX);
1532 default_ttl = ttl;
1533 default_ttl_set = ISC_TRUE;
1535 return (STATUS_MORE);
1538 static isc_uint16_t
1539 evaluate_class(char *cmdline) {
1540 char *word;
1541 isc_textregion_t r;
1542 isc_result_t result;
1543 dns_rdataclass_t rdclass;
1545 word = nsu_strsep(&cmdline, " \t\r\n");
1546 if (*word == 0) {
1547 fprintf(stderr, "could not read class name\n");
1548 return (STATUS_SYNTAX);
1551 r.base = word;
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);
1558 switch (rdclass) {
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);
1564 default:
1565 defaultclass = rdclass;
1568 return (STATUS_MORE);
1571 static isc_uint16_t
1572 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1573 isc_result_t result;
1574 dns_name_t *name = NULL;
1575 isc_uint32_t ttl;
1576 char *word;
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)
1592 return (retval);
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");
1604 if (*word == 0) {
1605 if (!isdelete) {
1606 fprintf(stderr, "could not read owner ttl\n");
1607 goto failure;
1609 else {
1610 ttl = 0;
1611 rdataclass = dns_rdataclass_any;
1612 rdatatype = dns_rdatatype_any;
1613 rdata->flags = DNS_RDATA_UPDATE;
1614 goto doneparsing;
1617 result = isc_parse_uint32(&ttl, word, 10);
1618 if (result != ISC_R_SUCCESS) {
1619 if (isdelete) {
1620 ttl = 0;
1621 goto parseclass;
1622 } else if (default_ttl_set) {
1623 ttl = default_ttl;
1624 goto parseclass;
1625 } else {
1626 fprintf(stderr, "ttl '%s': %s\n", word,
1627 isc_result_totext(result));
1628 goto failure;
1632 if (isdelete)
1633 ttl = 0;
1634 else if (ttl > TTL_MAX) {
1635 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1636 word, TTL_MAX);
1637 goto failure;
1641 * Read the class or type.
1643 word = nsu_strsep(&cmdline, " \t\r\n");
1644 parseclass:
1645 if (*word == 0) {
1646 if (isdelete) {
1647 rdataclass = dns_rdataclass_any;
1648 rdatatype = dns_rdatatype_any;
1649 rdata->flags = DNS_RDATA_UPDATE;
1650 goto doneparsing;
1651 } else {
1652 fprintf(stderr, "could not read class or type\n");
1653 goto failure;
1656 region.base = word;
1657 region.length = strlen(word);
1658 rdataclass = dns_rdataclass_any;
1659 result = dns_rdataclass_fromtext(&rdataclass, &region);
1660 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1661 if (!setzoneclass(rdataclass)) {
1662 fprintf(stderr, "class mismatch: %s\n", word);
1663 goto failure;
1666 * Now read the type.
1668 word = nsu_strsep(&cmdline, " \t\r\n");
1669 if (*word == 0) {
1670 if (isdelete) {
1671 rdataclass = dns_rdataclass_any;
1672 rdatatype = dns_rdatatype_any;
1673 rdata->flags = DNS_RDATA_UPDATE;
1674 goto doneparsing;
1675 } else {
1676 fprintf(stderr, "could not read type\n");
1677 goto failure;
1680 region.base = word;
1681 region.length = strlen(word);
1682 result = dns_rdatatype_fromtext(&rdatatype, &region);
1683 if (result != ISC_R_SUCCESS) {
1684 fprintf(stderr, "'%s' is not a valid type: %s\n",
1685 word, isc_result_totext(result));
1686 goto failure;
1688 } else {
1689 rdataclass = getzoneclass();
1690 result = dns_rdatatype_fromtext(&rdatatype, &region);
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));
1694 goto failure;
1698 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1699 rdata);
1700 if (retval != STATUS_MORE)
1701 goto failure;
1703 if (isdelete) {
1704 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1705 rdataclass = dns_rdataclass_any;
1706 else
1707 rdataclass = dns_rdataclass_none;
1708 } else {
1709 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1710 fprintf(stderr, "could not read rdata\n");
1711 goto failure;
1715 doneparsing:
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);
1735 failure:
1736 if (name != NULL)
1737 dns_message_puttempname(updatemsg, &name);
1738 dns_message_puttemprdata(updatemsg, &rdata);
1739 return (STATUS_SYNTAX);
1742 static isc_uint16_t
1743 evaluate_update(char *cmdline) {
1744 char *word;
1745 isc_boolean_t isdelete;
1747 ddebug("evaluate_update()");
1748 word = nsu_strsep(&cmdline, " \t\r\n");
1749 if (*word == 0) {
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;
1757 else {
1758 fprintf(stderr, "incorrect operation code: %s\n", word);
1759 return (STATUS_SYNTAX);
1761 return (update_addordelete(cmdline, isdelete));
1764 static void
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);
1775 rdataset != NULL;
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(),
1792 dns_rdatatype_soa);
1793 ISC_LIST_INIT(name->list);
1794 ISC_LIST_APPEND(name->list, rdataset, link);
1795 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1799 static void
1800 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1801 isc_result_t result;
1802 isc_buffer_t *buf = NULL;
1803 int bufsz;
1805 ddebug("show_message()");
1807 setzone(userzone);
1809 bufsz = INITTEXT;
1810 do {
1811 if (bufsz > MAXTEXT) {
1812 fprintf(stderr, "could not allocate large enough "
1813 "buffer to display message\n");
1814 exit(1);
1816 if (buf != NULL)
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);
1821 bufsz *= 2;
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);
1826 return;
1828 fprintf(stream, "%s\n%.*s", description,
1829 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1830 isc_buffer_free(&buf);
1834 static isc_uint16_t
1835 get_next_command(void) {
1836 char cmdlinebuf[MAXCMD];
1837 char *cmdline;
1838 char *word;
1840 ddebug("get_next_command()");
1841 if (interactive) {
1842 fprintf(stdout, "> ");
1843 fflush(stdout);
1845 isc_app_block();
1846 cmdline = fgets(cmdlinebuf, MAXCMD, input);
1847 isc_app_unblock();
1848 if (cmdline == NULL)
1849 return (STATUS_QUIT);
1850 word = nsu_strsep(&cmdline, " \t\r\n");
1852 if (feof(input))
1853 return (STATUS_QUIT);
1854 if (*word == 0)
1855 return (STATUS_SEND);
1856 if (word[0] == ';')
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) {
1875 if (debugging)
1876 ddebugging = ISC_TRUE;
1877 else
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) {
1888 if (answer != NULL)
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) {
1897 #ifdef GSSAPI
1898 usegsstsig = ISC_TRUE;
1899 use_win2k_gsstsig = ISC_FALSE;
1900 #else
1901 fprintf(stderr, "gsstsig not supported\n");
1902 #endif
1903 return (STATUS_MORE);
1905 if (strcasecmp(word, "oldgsstsig") == 0) {
1906 #ifdef GSSAPI
1907 usegsstsig = ISC_TRUE;
1908 use_win2k_gsstsig = ISC_TRUE;
1909 #else
1910 fprintf(stderr, "gsstsig not supported\n");
1911 #endif
1912 return (STATUS_MORE);
1914 if (strcasecmp(word, "help") == 0) {
1915 fprintf(stdout,
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)
1951 return (ISC_TRUE);
1952 return (ISC_FALSE);
1956 static void
1957 done_update(void) {
1958 isc_event_t *event = global_event;
1959 ddebug("done_update()");
1960 isc_task_send(global_task, &event);
1963 static void
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, /*(*/ ")");
1986 static void
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;
1992 UNUSED(task);
1994 ddebug("update_completed()");
1996 requests--;
1998 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
1999 reqev = (dns_requestevent_t *)event;
2000 request = reqev->request;
2002 if (shuttingdown) {
2003 dns_request_destroy(&request);
2004 isc_event_free(&event);
2005 maybeshutdown();
2006 return;
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;
2013 goto done;
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);
2020 switch (result) {
2021 case ISC_R_SUCCESS:
2022 if (answer->verify_attempted)
2023 ddebug("tsig verification successful");
2024 break;
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:
2030 case ISC_R_FAILURE:
2031 #if 0
2032 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2034 * For MS DNS that violates RFC 2845, section 4.2
2036 break;
2038 #endif
2039 fprintf(stderr, "; TSIG error with server: %s\n",
2040 isc_result_totext(result));
2041 seenerror = ISC_TRUE;
2042 break;
2043 default:
2044 check_result(result, "dns_request_getresponse");
2047 if (answer->rcode != dns_rcode_noerror) {
2048 seenerror = ISC_TRUE;
2049 if (!debugging) {
2050 char buf[64];
2051 isc_buffer_t b;
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);
2058 if (rds != NULL)
2059 check_tsig_error(rds, &b);
2060 fprintf(stderr, "update failed: %.*s\n",
2061 (int)isc_buffer_usedlength(&b), buf);
2064 if (debugging)
2065 show_message(stderr, answer, "\nReply from update query:");
2067 done:
2068 dns_request_destroy(&request);
2069 if (usegsstsig) {
2070 dns_name_free(&tmpzonename, mctx);
2071 dns_name_free(&restart_master, mctx);
2073 isc_event_free(&event);
2074 done_update();
2077 static void
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()");
2087 setzone(zonename);
2089 if (usevc)
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");
2095 if (debugging) {
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");
2108 if (debugging)
2109 show_message(stdout, updatemsg, "Outgoing update query:");
2111 requests++;
2114 static void
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;
2125 int pass = 0;
2126 dns_name_t master;
2127 nsu_requestinfo_t *reqinfo;
2128 dns_message_t *soaquery = NULL;
2129 isc_sockaddr_t *addr;
2130 isc_boolean_t seencname = ISC_FALSE;
2131 dns_name_t tname;
2132 unsigned int nlabels;
2134 UNUSED(task);
2136 ddebug("recvsoa()");
2138 requests--;
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;
2148 if (shuttingdown) {
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);
2153 maybeshutdown();
2154 return;
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);
2175 return;
2178 isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
2179 reqinfo = NULL;
2180 isc_event_free(&event);
2181 reqev = NULL;
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,
2201 FIND_TIMEOUT * 20,
2202 FIND_TIMEOUT, 3,
2203 global_task, recvsoa, reqinfo,
2204 &request);
2205 check_result(result, "dns_request_createvia");
2206 requests++;
2207 return;
2209 check_result(result, "dns_request_getresponse");
2210 section = DNS_SECTION_ANSWER;
2211 if (debugging)
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)",
2222 namebuf);
2223 dns_message_destroy(&rcvmsg);
2224 dns_request_destroy(&request);
2225 dns_message_destroy(&soaquery);
2226 ddebug("Out of recvsoa");
2227 done_update();
2228 return;
2231 lookforsoa:
2232 if (pass == 0)
2233 section = DNS_SECTION_ANSWER;
2234 else if (pass == 1)
2235 section = DNS_SECTION_AUTHORITY;
2236 else
2237 goto droplabel;
2239 result = dns_message_firstname(rcvmsg, section);
2240 if (result != ISC_R_SUCCESS) {
2241 pass++;
2242 goto lookforsoa;
2244 while (result == ISC_R_SUCCESS) {
2245 name = NULL;
2246 dns_message_currentname(rcvmsg, section, &name);
2247 soaset = NULL;
2248 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2249 &soaset);
2250 if (result == ISC_R_SUCCESS)
2251 break;
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;
2259 break;
2263 result = dns_message_nextname(rcvmsg, section);
2266 if (soaset == NULL && !seencname) {
2267 pass++;
2268 goto lookforsoa;
2271 if (seencname)
2272 goto droplabel;
2274 if (debugging) {
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;
2293 else
2294 zonename = name;
2296 if (debugging) {
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;
2304 else {
2305 char serverstr[DNS_NAME_MAXTEXT+1];
2306 isc_buffer_t buf;
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);
2317 #ifdef GSSAPI
2318 if (usegsstsig) {
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);
2324 } else {
2325 send_update(zonename, serveraddr, localaddr);
2326 setzoneclass(dns_rdataclass_none);
2328 #else
2329 send_update(zonename, serveraddr, localaddr);
2330 setzoneclass(dns_rdataclass_none);
2331 #endif
2333 dns_message_destroy(&soaquery);
2334 dns_request_destroy(&request);
2336 out:
2337 dns_message_destroy(&rcvmsg);
2338 ddebug("Out of recvsoa");
2339 return;
2341 droplabel:
2342 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2343 INSIST(result == ISC_R_SUCCESS);
2344 name = NULL;
2345 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2346 nlabels = dns_name_countlabels(name);
2347 if (nlabels == 1)
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);
2357 else
2358 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2359 goto out;
2362 static void
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");
2372 reqinfo->msg = msg;
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");
2379 requests++;
2382 #ifdef GSSAPI
2383 static void
2384 start_gssrequest(dns_name_t *master)
2386 gss_ctx_id_t context;
2387 isc_buffer_t buf;
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");
2398 usevc = ISC_TRUE;
2400 if (gssring != NULL)
2401 dns_tsigkeyring_destroy(&gssring);
2402 gssring = NULL;
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);
2417 else
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),
2424 "DNS/%s", namestr);
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",
2440 val, namestr);
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;
2455 rmsg = NULL;
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);
2475 static void
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");
2488 reqinfo->msg = msg;
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,
2496 reqinfo, request);
2497 check_result(result, "dns_request_createvia3");
2498 if (debugging)
2499 show_message(stdout, msg, "Outgoing update query:");
2500 requests++;
2503 static void
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;
2513 isc_buffer_t buf;
2514 dns_name_t *servname;
2515 dns_fixedname_t fname;
2517 UNUSED(task);
2519 ddebug("recvgss()");
2521 requests--;
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;
2532 if (shuttingdown) {
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);
2537 maybeshutdown();
2538 return;
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,
2555 &request);
2556 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2557 isc_event_free(&event);
2558 return;
2560 isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
2562 isc_event_free(&event);
2563 reqev = NULL;
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");
2573 if (debugging)
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;
2582 else
2583 use_win2k_gsstsig = ISC_TRUE;
2584 tried_other_gsstsig = ISC_TRUE;
2585 start_gssrequest(&restart_master);
2586 goto done;
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");
2601 tsigkey = NULL;
2602 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2603 &context, &tsigkey, gssring,
2604 use_win2k_gsstsig);
2605 switch (result) {
2607 case DNS_R_CONTINUE:
2608 send_gssrequest(localaddr, kserver, tsigquery, &request,
2609 context);
2610 break;
2612 case ISC_R_SUCCESS:
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.
2629 #if 0
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");
2640 #endif /* 0 */
2642 send_update(&tmpzonename, serveraddr, localaddr);
2643 setzoneclass(dns_rdataclass_none);
2644 break;
2646 default:
2647 fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
2650 done:
2651 dns_request_destroy(&request);
2652 dns_message_destroy(&tsigquery);
2654 dns_message_destroy(&rcvmsg);
2655 ddebug("Out of recvgss");
2657 #endif
2659 static void
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()");
2671 if (answer != NULL)
2672 dns_message_destroy(&answer);
2674 if (userzone != NULL && userserver != NULL && ! usegsstsig) {
2675 send_update(userzone, userserver, localaddr);
2676 setzoneclass(dns_rdataclass_none);
2677 return;
2680 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2681 &soaquery);
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);
2698 } else {
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);
2709 done_update();
2710 return;
2712 firstname = NULL;
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);
2724 else {
2725 ns_inuse = 0;
2726 sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
2730 static void
2731 cleanup(void) {
2732 ddebug("cleanup()");
2734 if (answer != NULL)
2735 dns_message_destroy(&answer);
2737 #ifdef GSSAPI
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));
2748 kserver = NULL;
2750 #endif
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");
2765 isc_hash_destroy();
2767 ddebug("Destroying name state");
2768 dns_name_destroy();
2770 ddebug("Removing log context");
2771 isc_log_destroy(&lctx);
2773 ddebug("Destroying memory context");
2774 if (memdebugging)
2775 isc_mem_stats(mctx, stderr);
2776 isc_mem_destroy(&mctx);
2779 static void
2780 getinput(isc_task_t *task, isc_event_t *event) {
2781 isc_boolean_t more;
2783 UNUSED(task);
2785 if (shuttingdown) {
2786 maybeshutdown();
2787 return;
2790 if (global_event == NULL)
2791 global_event = event;
2793 reset_system();
2794 more = user_interaction();
2795 if (!more) {
2796 isc_app_shutdown();
2797 return;
2799 start_update();
2800 return;
2804 main(int argc, char **argv) {
2805 isc_result_t result;
2806 style = &dns_master_style_debug;
2808 input = stdin;
2810 interactive = ISC_TF(isatty(0));
2812 isc_app_start();
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);
2821 setup_system();
2823 result = isc_app_onrun(mctx, global_task, getinput, NULL);
2824 check_result(result, "isc_app_onrun");
2826 (void)isc_app_run();
2828 cleanup();
2830 isc_app_finish();
2832 if (seenerror)
2833 return (2);
2834 else
2835 return (0);