etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / nsupdate / nsupdate.c
blob7ccbb4b1a6ebaafc878ef83330e204256859ab25
1 /* $NetBSD: nsupdate.c,v 1.13 2015/07/08 17:28:55 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2015 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 /*! \file */
22 #include <config.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <unistd.h>
30 #include <isc/app.h>
31 #include <isc/base64.h>
32 #include <isc/buffer.h>
33 #include <isc/commandline.h>
34 #include <isc/entropy.h>
35 #include <isc/event.h>
36 #include <isc/file.h>
37 #include <isc/hash.h>
38 #include <isc/lex.h>
39 #include <isc/log.h>
40 #include <isc/mem.h>
41 #include <isc/parseint.h>
42 #include <isc/print.h>
43 #include <isc/random.h>
44 #include <isc/region.h>
45 #include <isc/sockaddr.h>
46 #include <isc/socket.h>
47 #include <isc/stdio.h>
48 #include <isc/string.h>
49 #include <isc/task.h>
50 #include <isc/timer.h>
51 #include <isc/types.h>
52 #include <isc/util.h>
54 #include <isccfg/namedconf.h>
56 #include <dns/callbacks.h>
57 #include <dns/dispatch.h>
58 #include <dns/dnssec.h>
59 #include <dns/events.h>
60 #include <dns/fixedname.h>
61 #include <dns/log.h>
62 #include <dns/masterdump.h>
63 #include <dns/message.h>
64 #include <dns/name.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatastruct.h>
71 #include <dns/rdatatype.h>
72 #include <dns/request.h>
73 #include <dns/result.h>
74 #include <dns/tkey.h>
75 #include <dns/tsig.h>
77 #include <dst/dst.h>
79 #include <lwres/lwres.h>
80 #include <lwres/net.h>
82 #ifdef GSSAPI
83 #include <dst/gssapi.h>
84 #ifdef WIN32
85 #include <krb5/krb5.h>
86 #else
87 #include ISC_PLATFORM_KRB5HEADER
88 #endif
89 #endif
90 #include <bind9/getaddresses.h>
92 #if defined(HAVE_READLINE)
93 #include <readline/readline.h>
94 #include <readline/history.h>
95 #endif
97 #ifdef HAVE_ADDRINFO
98 #ifdef HAVE_GETADDRINFO
99 #ifdef HAVE_GAISTRERROR
100 #define USE_GETADDRINFO
101 #endif
102 #endif
103 #endif
105 #ifndef USE_GETADDRINFO
106 #ifndef ISC_PLATFORM_NONSTDHERRNO
107 extern int h_errno;
108 #endif
109 #endif
111 #define MAXCMD (128 * 1024)
112 #define MAXWIRE (64 * 1024)
113 #define PACKETSIZE ((64 * 1024) - 1)
114 #define INITTEXT (2 * 1024)
115 #define MAXTEXT (128 * 1024)
116 #define FIND_TIMEOUT 5
117 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
119 #define DNSDEFAULTPORT 53
121 /* Number of addresses to request from bind9_getaddresses() */
122 #define MAX_SERVERADDRS 4
124 static isc_uint16_t dnsport = DNSDEFAULTPORT;
126 #ifndef RESOLV_CONF
127 #define RESOLV_CONF "/etc/resolv.conf"
128 #endif
130 static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
131 static isc_boolean_t memdebugging = ISC_FALSE;
132 static isc_boolean_t have_ipv4 = ISC_FALSE;
133 static isc_boolean_t have_ipv6 = ISC_FALSE;
134 static isc_boolean_t is_dst_up = ISC_FALSE;
135 static isc_boolean_t usevc = ISC_FALSE;
136 static isc_boolean_t usegsstsig = ISC_FALSE;
137 static isc_boolean_t use_win2k_gsstsig = ISC_FALSE;
138 static isc_boolean_t tried_other_gsstsig = ISC_FALSE;
139 static isc_boolean_t local_only = ISC_FALSE;
140 static isc_taskmgr_t *taskmgr = NULL;
141 static isc_task_t *global_task = NULL;
142 static isc_event_t *global_event = NULL;
143 static isc_log_t *glctx = NULL;
144 static isc_mem_t *gmctx = NULL;
145 static dns_dispatchmgr_t *dispatchmgr = NULL;
146 static dns_requestmgr_t *requestmgr = NULL;
147 static isc_socketmgr_t *socketmgr = NULL;
148 static isc_timermgr_t *timermgr = NULL;
149 static dns_dispatch_t *dispatchv4 = NULL;
150 static dns_dispatch_t *dispatchv6 = NULL;
151 static dns_message_t *updatemsg = NULL;
152 static dns_fixedname_t fuserzone;
153 static dns_name_t *userzone = NULL;
154 static dns_name_t *zname = NULL;
155 static dns_name_t tmpzonename;
156 static dns_name_t restart_master;
157 static dns_tsig_keyring_t *gssring = NULL;
158 static dns_tsigkey_t *tsigkey = NULL;
159 static dst_key_t *sig0key = NULL;
160 static lwres_context_t *lwctx = NULL;
161 static lwres_conf_t *lwconf;
162 static isc_sockaddr_t *servers = NULL;
163 static isc_sockaddr_t *master_servers = NULL;
164 static isc_boolean_t default_servers = ISC_TRUE;
165 static int ns_inuse = 0;
166 static int master_inuse = 0;
167 static int ns_total = 0;
168 static int master_total = 0;
169 static isc_sockaddr_t *localaddr4 = NULL;
170 static isc_sockaddr_t *localaddr6 = NULL;
171 static const char *keyfile = NULL;
172 static char *keystr = NULL;
173 static isc_entropy_t *entropy = NULL;
174 static isc_boolean_t shuttingdown = ISC_FALSE;
175 static FILE *input;
176 static isc_boolean_t interactive = ISC_TRUE;
177 static isc_boolean_t seenerror = ISC_FALSE;
178 static const dns_master_style_t *style;
179 static int requests = 0;
180 static unsigned int logdebuglevel = 0;
181 static unsigned int timeout = 300;
182 static unsigned int udp_timeout = 3;
183 static unsigned int udp_retries = 3;
184 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
185 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
186 static dns_message_t *answer = NULL;
187 static isc_uint32_t default_ttl = 0;
188 static isc_boolean_t default_ttl_set = ISC_FALSE;
190 typedef struct nsu_requestinfo {
191 dns_message_t *msg;
192 isc_sockaddr_t *addr;
193 } nsu_requestinfo_t;
195 static void
196 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
197 dns_request_t **request);
198 static void
199 send_update(dns_name_t *zonename, isc_sockaddr_t *master);
201 ISC_PLATFORM_NORETURN_PRE static void
202 fatal(const char *format, ...)
203 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
205 static void
206 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
208 static void
209 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
211 #ifdef GSSAPI
212 static dns_fixedname_t fkname;
213 static isc_sockaddr_t *kserver = NULL;
214 static char *realm = NULL;
215 static char servicename[DNS_NAME_FORMATSIZE];
216 static dns_name_t *keyname;
217 typedef struct nsu_gssinfo {
218 dns_message_t *msg;
219 isc_sockaddr_t *addr;
220 gss_ctx_id_t context;
221 } nsu_gssinfo_t;
223 static void
224 start_gssrequest(dns_name_t *master);
225 static void
226 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
227 dns_request_t **request, gss_ctx_id_t context);
228 static void
229 recvgss(isc_task_t *task, isc_event_t *event);
230 #endif /* GSSAPI */
232 static void
233 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
235 #define STATUS_MORE (isc_uint16_t)0
236 #define STATUS_SEND (isc_uint16_t)1
237 #define STATUS_QUIT (isc_uint16_t)2
238 #define STATUS_SYNTAX (isc_uint16_t)3
240 typedef struct entropysource entropysource_t;
242 struct entropysource {
243 isc_entropysource_t *source;
244 isc_mem_t *mctx;
245 ISC_LINK(entropysource_t) link;
248 static ISC_LIST(entropysource_t) sources;
250 static void
251 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
252 isc_result_t result;
253 isc_entropysource_t *source = NULL;
254 entropysource_t *elt;
255 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
257 REQUIRE(ectx != NULL);
259 if (*ectx == NULL) {
260 result = isc_entropy_create(mctx, ectx);
261 if (result != ISC_R_SUCCESS)
262 fatal("could not create entropy object");
263 ISC_LIST_INIT(sources);
266 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
267 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
268 randomfile = NULL;
271 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
272 usekeyboard);
274 if (result != ISC_R_SUCCESS)
275 fatal("could not initialize entropy source: %s",
276 isc_result_totext(result));
278 if (source != NULL) {
279 elt = isc_mem_get(mctx, sizeof(*elt));
280 if (elt == NULL)
281 fatal("out of memory");
282 elt->source = source;
283 elt->mctx = mctx;
284 ISC_LINK_INIT(elt, link);
285 ISC_LIST_APPEND(sources, elt, link);
289 static void
290 cleanup_entropy(isc_entropy_t **ectx) {
291 entropysource_t *source;
292 while (!ISC_LIST_EMPTY(sources)) {
293 source = ISC_LIST_HEAD(sources);
294 ISC_LIST_UNLINK(sources, source, link);
295 isc_entropy_destroysource(&source->source);
296 isc_mem_put(source->mctx, source, sizeof(*source));
298 isc_entropy_detach(ectx);
301 static void
302 master_from_servers(void) {
304 if (master_servers != NULL && master_servers != servers)
305 isc_mem_put(gmctx, master_servers,
306 master_total * sizeof(isc_sockaddr_t));
307 master_servers = servers;
308 master_total = ns_total;
309 master_inuse = ns_inuse;
312 static dns_rdataclass_t
313 getzoneclass(void) {
314 if (zoneclass == dns_rdataclass_none)
315 zoneclass = defaultclass;
316 return (zoneclass);
319 static isc_boolean_t
320 setzoneclass(dns_rdataclass_t rdclass) {
321 if (zoneclass == dns_rdataclass_none ||
322 rdclass == dns_rdataclass_none)
323 zoneclass = rdclass;
324 if (zoneclass != rdclass)
325 return (ISC_FALSE);
326 return (ISC_TRUE);
329 static void
330 fatal(const char *format, ...) {
331 va_list args;
333 va_start(args, format);
334 vfprintf(stderr, format, args);
335 va_end(args);
336 fprintf(stderr, "\n");
337 exit(1);
340 static void
341 error(const char *format, ...) {
342 va_list args;
344 va_start(args, format);
345 vfprintf(stderr, format, args);
346 va_end(args);
347 fprintf(stderr, "\n");
350 static void
351 debug(const char *format, ...) {
352 va_list args;
354 if (debugging) {
355 va_start(args, format);
356 vfprintf(stderr, format, args);
357 va_end(args);
358 fprintf(stderr, "\n");
362 static void
363 ddebug(const char *format, ...) {
364 va_list args;
366 if (ddebugging) {
367 va_start(args, format);
368 vfprintf(stderr, format, args);
369 va_end(args);
370 fprintf(stderr, "\n");
374 static inline void
375 check_result(isc_result_t result, const char *msg) {
376 if (result != ISC_R_SUCCESS)
377 fatal("%s: %s", msg, isc_result_totext(result));
380 static void *
381 mem_alloc(void *arg, size_t size) {
382 return (isc_mem_get(arg, size));
385 static void
386 mem_free(void *arg, void *mem, size_t size) {
387 isc_mem_put(arg, mem, size);
390 static char *
391 nsu_strsep(char **stringp, const char *delim) {
392 char *string = *stringp;
393 char *s;
394 const char *d;
395 char sc, dc;
397 if (string == NULL)
398 return (NULL);
400 for (; *string != '\0'; string++) {
401 sc = *string;
402 for (d = delim; (dc = *d) != '\0'; d++) {
403 if (sc == dc)
404 break;
406 if (dc == 0)
407 break;
410 for (s = string; *s != '\0'; s++) {
411 sc = *s;
412 for (d = delim; (dc = *d) != '\0'; d++) {
413 if (sc == dc) {
414 *s++ = '\0';
415 *stringp = s;
416 return (string);
420 *stringp = NULL;
421 return (string);
424 static void
425 reset_system(void) {
426 isc_result_t result;
428 ddebug("reset_system()");
429 /* If the update message is still around, destroy it */
430 if (updatemsg != NULL)
431 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
432 else {
433 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
434 &updatemsg);
435 check_result(result, "dns_message_create");
437 updatemsg->opcode = dns_opcode_update;
438 if (usegsstsig) {
439 if (tsigkey != NULL)
440 dns_tsigkey_detach(&tsigkey);
441 if (gssring != NULL)
442 dns_tsigkeyring_detach(&gssring);
443 tried_other_gsstsig = ISC_FALSE;
447 static isc_uint16_t
448 parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
449 isc_uint16_t digestbits = 0;
450 isc_result_t result;
451 char buf[20];
453 REQUIRE(hmac != NULL && *hmac == NULL);
454 REQUIRE(hmacstr != NULL);
456 if (len >= sizeof(buf))
457 fatal("unknown key type '%.*s'", (int)(len), hmacstr);
459 strncpy(buf, hmacstr, len);
460 buf[len] = 0;
462 if (strcasecmp(buf, "hmac-md5") == 0) {
463 *hmac = DNS_TSIG_HMACMD5_NAME;
464 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
465 *hmac = DNS_TSIG_HMACMD5_NAME;
466 result = isc_parse_uint16(&digestbits, &buf[9], 10);
467 if (result != ISC_R_SUCCESS || digestbits > 128)
468 fatal("digest-bits out of range [0..128]");
469 digestbits = (digestbits +7) & ~0x7U;
470 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
471 *hmac = DNS_TSIG_HMACSHA1_NAME;
472 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
473 *hmac = DNS_TSIG_HMACSHA1_NAME;
474 result = isc_parse_uint16(&digestbits, &buf[10], 10);
475 if (result != ISC_R_SUCCESS || digestbits > 160)
476 fatal("digest-bits out of range [0..160]");
477 digestbits = (digestbits +7) & ~0x7U;
478 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
479 *hmac = DNS_TSIG_HMACSHA224_NAME;
480 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
481 *hmac = DNS_TSIG_HMACSHA224_NAME;
482 result = isc_parse_uint16(&digestbits, &buf[12], 10);
483 if (result != ISC_R_SUCCESS || digestbits > 224)
484 fatal("digest-bits out of range [0..224]");
485 digestbits = (digestbits +7) & ~0x7U;
486 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
487 *hmac = DNS_TSIG_HMACSHA256_NAME;
488 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
489 *hmac = DNS_TSIG_HMACSHA256_NAME;
490 result = isc_parse_uint16(&digestbits, &buf[12], 10);
491 if (result != ISC_R_SUCCESS || digestbits > 256)
492 fatal("digest-bits out of range [0..256]");
493 digestbits = (digestbits +7) & ~0x7U;
494 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
495 *hmac = DNS_TSIG_HMACSHA384_NAME;
496 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
497 *hmac = DNS_TSIG_HMACSHA384_NAME;
498 result = isc_parse_uint16(&digestbits, &buf[12], 10);
499 if (result != ISC_R_SUCCESS || digestbits > 384)
500 fatal("digest-bits out of range [0..384]");
501 digestbits = (digestbits +7) & ~0x7U;
502 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
503 *hmac = DNS_TSIG_HMACSHA512_NAME;
504 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
505 *hmac = DNS_TSIG_HMACSHA512_NAME;
506 result = isc_parse_uint16(&digestbits, &buf[12], 10);
507 if (result != ISC_R_SUCCESS || digestbits > 512)
508 fatal("digest-bits out of range [0..512]");
509 digestbits = (digestbits +7) & ~0x7U;
510 } else
511 fatal("unknown key type '%s'", buf);
512 return (digestbits);
515 static int
516 basenamelen(const char *file) {
517 int len = strlen(file);
519 if (len > 1 && file[len - 1] == '.')
520 len -= 1;
521 else if (len > 8 && strcmp(file + len - 8, ".private") == 0)
522 len -= 8;
523 else if (len > 4 && strcmp(file + len - 4, ".key") == 0)
524 len -= 4;
525 return (len);
528 static void
529 setup_keystr(void) {
530 unsigned char *secret = NULL;
531 int secretlen;
532 isc_buffer_t secretbuf;
533 isc_result_t result;
534 isc_buffer_t keynamesrc;
535 char *secretstr;
536 char *s, *n;
537 dns_fixedname_t fkeyname;
538 dns_name_t *mykeyname;
539 char *name;
540 dns_name_t *hmacname = NULL;
541 isc_uint16_t digestbits = 0;
543 dns_fixedname_init(&fkeyname);
544 mykeyname = dns_fixedname_name(&fkeyname);
546 debug("Creating key...");
548 s = strchr(keystr, ':');
549 if (s == NULL || s == keystr || s[1] == 0)
550 fatal("key option must specify [hmac:]keyname:secret");
551 secretstr = s + 1;
552 n = strchr(secretstr, ':');
553 if (n != NULL) {
554 if (n == secretstr || n[1] == 0)
555 fatal("key option must specify [hmac:]keyname:secret");
556 name = secretstr;
557 secretstr = n + 1;
558 digestbits = parse_hmac(&hmacname, keystr, s - keystr);
559 } else {
560 hmacname = DNS_TSIG_HMACMD5_NAME;
561 name = keystr;
562 n = s;
565 isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
566 isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
568 debug("namefromtext");
569 result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0,
570 NULL);
571 check_result(result, "dns_name_fromtext");
573 secretlen = strlen(secretstr) * 3 / 4;
574 secret = isc_mem_allocate(gmctx, secretlen);
575 if (secret == NULL)
576 fatal("out of memory");
578 isc_buffer_init(&secretbuf, secret, secretlen);
579 result = isc_base64_decodestring(secretstr, &secretbuf);
580 if (result != ISC_R_SUCCESS) {
581 fprintf(stderr, "could not create key from %s: %s\n",
582 keystr, isc_result_totext(result));
583 goto failure;
586 secretlen = isc_buffer_usedlength(&secretbuf);
588 debug("keycreate");
589 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
590 ISC_FALSE, NULL, 0, 0, gmctx, NULL,
591 &tsigkey);
592 if (result != ISC_R_SUCCESS)
593 fprintf(stderr, "could not create key from %s: %s\n",
594 keystr, dns_result_totext(result));
595 else
596 dst_key_setbits(tsigkey->key, digestbits);
597 failure:
598 if (secret != NULL)
599 isc_mem_free(gmctx, secret);
603 * Get a key from a named.conf format keyfile
605 static isc_result_t
606 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
607 cfg_parser_t *pctx = NULL;
608 cfg_obj_t *sessionkey = NULL;
609 const cfg_obj_t *key = NULL;
610 const cfg_obj_t *secretobj = NULL;
611 const cfg_obj_t *algorithmobj = NULL;
612 const char *mykeyname;
613 const char *secretstr;
614 const char *algorithm;
615 isc_result_t result;
616 int len;
618 if (! isc_file_exists(keyfile))
619 return (ISC_R_FILENOTFOUND);
621 result = cfg_parser_create(mctx, lctx, &pctx);
622 if (result != ISC_R_SUCCESS)
623 goto cleanup;
625 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
626 &sessionkey);
627 if (result != ISC_R_SUCCESS)
628 goto cleanup;
630 result = cfg_map_get(sessionkey, "key", &key);
631 if (result != ISC_R_SUCCESS)
632 goto cleanup;
634 (void) cfg_map_get(key, "secret", &secretobj);
635 (void) cfg_map_get(key, "algorithm", &algorithmobj);
636 if (secretobj == NULL || algorithmobj == NULL)
637 fatal("key must have algorithm and secret");
639 mykeyname = cfg_obj_asstring(cfg_map_getname(key));
640 secretstr = cfg_obj_asstring(secretobj);
641 algorithm = cfg_obj_asstring(algorithmobj);
643 len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3;
644 keystr = isc_mem_allocate(mctx, len);
645 snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr);
646 setup_keystr();
648 cleanup:
649 if (pctx != NULL) {
650 if (sessionkey != NULL)
651 cfg_obj_destroy(pctx, &sessionkey);
652 cfg_parser_destroy(&pctx);
655 if (keystr != NULL)
656 isc_mem_free(mctx, keystr);
658 return (result);
661 static void
662 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
663 dst_key_t *dstkey = NULL;
664 isc_result_t result;
665 dns_name_t *hmacname = NULL;
667 debug("Creating key...");
669 if (sig0key != NULL)
670 dst_key_free(&sig0key);
672 /* Try reading the key from a K* pair */
673 result = dst_key_fromnamedfile(keyfile, NULL,
674 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
675 &dstkey);
677 /* If that didn't work, try reading it as a session.key keyfile */
678 if (result != ISC_R_SUCCESS) {
679 result = read_sessionkey(mctx, lctx);
680 if (result == ISC_R_SUCCESS)
681 return;
684 if (result != ISC_R_SUCCESS) {
685 fprintf(stderr, "could not read key from %.*s.{private,key}: "
686 "%s\n", basenamelen(keyfile), keyfile,
687 isc_result_totext(result));
688 return;
691 switch (dst_key_alg(dstkey)) {
692 case DST_ALG_HMACMD5:
693 hmacname = DNS_TSIG_HMACMD5_NAME;
694 break;
695 case DST_ALG_HMACSHA1:
696 hmacname = DNS_TSIG_HMACSHA1_NAME;
697 break;
698 case DST_ALG_HMACSHA224:
699 hmacname = DNS_TSIG_HMACSHA224_NAME;
700 break;
701 case DST_ALG_HMACSHA256:
702 hmacname = DNS_TSIG_HMACSHA256_NAME;
703 break;
704 case DST_ALG_HMACSHA384:
705 hmacname = DNS_TSIG_HMACSHA384_NAME;
706 break;
707 case DST_ALG_HMACSHA512:
708 hmacname = DNS_TSIG_HMACSHA512_NAME;
709 break;
711 if (hmacname != NULL) {
712 result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
713 hmacname, dstkey, ISC_FALSE,
714 NULL, 0, 0, mctx, NULL,
715 &tsigkey);
716 dst_key_free(&dstkey);
717 if (result != ISC_R_SUCCESS) {
718 fprintf(stderr, "could not create key from %s: %s\n",
719 keyfile, isc_result_totext(result));
720 return;
722 } else {
723 dst_key_attach(dstkey, &sig0key);
724 dst_key_free(&dstkey);
728 static void
729 doshutdown(void) {
730 isc_task_detach(&global_task);
733 * The isc_mem_put of master_servers must be before the
734 * isc_mem_put of servers as it sets the servers pointer
735 * to NULL.
737 if (master_servers != NULL && master_servers != servers)
738 isc_mem_put(gmctx, master_servers,
739 master_total * sizeof(isc_sockaddr_t));
741 if (servers != NULL)
742 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
744 if (localaddr4 != NULL)
745 isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
747 if (localaddr6 != NULL)
748 isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t));
750 if (tsigkey != NULL) {
751 ddebug("Freeing TSIG key");
752 dns_tsigkey_detach(&tsigkey);
755 if (sig0key != NULL) {
756 ddebug("Freeing SIG(0) key");
757 dst_key_free(&sig0key);
760 if (updatemsg != NULL)
761 dns_message_destroy(&updatemsg);
763 if (is_dst_up) {
764 ddebug("Destroy DST lib");
765 dst_lib_destroy();
766 is_dst_up = ISC_FALSE;
769 cleanup_entropy(&entropy);
771 lwres_conf_clear(lwctx);
772 lwres_context_destroy(&lwctx);
774 ddebug("Destroying request manager");
775 dns_requestmgr_detach(&requestmgr);
777 ddebug("Freeing the dispatchers");
778 if (have_ipv4)
779 dns_dispatch_detach(&dispatchv4);
780 if (have_ipv6)
781 dns_dispatch_detach(&dispatchv6);
783 ddebug("Shutting down dispatch manager");
784 dns_dispatchmgr_destroy(&dispatchmgr);
788 static void
789 maybeshutdown(void) {
790 ddebug("Shutting down request manager");
791 dns_requestmgr_shutdown(requestmgr);
793 if (requests != 0)
794 return;
796 doshutdown();
799 static void
800 shutdown_program(isc_task_t *task, isc_event_t *event) {
801 REQUIRE(task == global_task);
802 UNUSED(task);
804 ddebug("shutdown_program()");
805 isc_event_free(&event);
807 shuttingdown = ISC_TRUE;
808 maybeshutdown();
811 static void
812 setup_system(void) {
813 isc_result_t result;
814 isc_sockaddr_t bind_any, bind_any6;
815 lwres_result_t lwresult;
816 unsigned int attrs, attrmask;
817 int i;
818 isc_logconfig_t *logconfig = NULL;
820 ddebug("setup_system()");
822 dns_result_register();
824 result = isc_net_probeipv4();
825 if (result == ISC_R_SUCCESS)
826 have_ipv4 = ISC_TRUE;
828 result = isc_net_probeipv6();
829 if (result == ISC_R_SUCCESS)
830 have_ipv6 = ISC_TRUE;
832 if (!have_ipv4 && !have_ipv6)
833 fatal("could not find either IPv4 or IPv6");
835 result = isc_log_create(gmctx, &glctx, &logconfig);
836 check_result(result, "isc_log_create");
838 isc_log_setcontext(glctx);
839 dns_log_init(glctx);
840 dns_log_setcontext(glctx);
842 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
843 check_result(result, "isc_log_usechannel");
845 isc_log_setdebuglevel(glctx, logdebuglevel);
847 lwresult = lwres_context_create(&lwctx, gmctx, mem_alloc, mem_free, 1);
848 if (lwresult != LWRES_R_SUCCESS)
849 fatal("lwres_context_create failed");
851 (void)lwres_conf_parse(lwctx, RESOLV_CONF);
852 lwconf = lwres_conf_get(lwctx);
854 if (servers != NULL) {
855 if (master_servers == servers)
856 master_servers = NULL;
857 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
860 ns_inuse = 0;
861 if (local_only || lwconf->nsnext <= 0) {
862 struct in_addr in;
863 struct in6_addr in6;
865 if (local_only && keyfile == NULL)
866 keyfile = SESSION_KEYFILE;
868 default_servers = !local_only;
870 ns_total = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
871 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
872 if (servers == NULL)
873 fatal("out of memory");
875 if (have_ipv4) {
876 in.s_addr = htonl(INADDR_LOOPBACK);
877 isc_sockaddr_fromin(&servers[0], &in, dnsport);
879 if (have_ipv6) {
880 memset(&in6, 0, sizeof(in6));
881 in6.s6_addr[15] = 1;
882 isc_sockaddr_fromin6(&servers[(have_ipv4 ? 1 : 0)],
883 &in6, dnsport);
885 } else {
886 ns_total = lwconf->nsnext;
887 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
888 if (servers == NULL)
889 fatal("out of memory");
890 for (i = 0; i < ns_total; i++) {
891 if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4)
893 struct in_addr in4;
894 memmove(&in4,
895 lwconf->nameservers[i].address, 4);
896 isc_sockaddr_fromin(&servers[i],
897 &in4, dnsport);
898 } else {
899 struct in6_addr in6;
900 memmove(&in6,
901 lwconf->nameservers[i].address, 16);
902 isc_sockaddr_fromin6(&servers[i],
903 &in6, dnsport);
908 setup_entropy(gmctx, NULL, &entropy);
910 result = isc_hash_create(gmctx, entropy, DNS_NAME_MAXWIRE);
911 check_result(result, "isc_hash_create");
912 isc_hash_init();
914 result = dns_dispatchmgr_create(gmctx, entropy, &dispatchmgr);
915 check_result(result, "dns_dispatchmgr_create");
917 result = isc_socketmgr_create(gmctx, &socketmgr);
918 check_result(result, "dns_socketmgr_create");
920 result = isc_timermgr_create(gmctx, &timermgr);
921 check_result(result, "dns_timermgr_create");
923 result = isc_taskmgr_create(gmctx, 1, 0, &taskmgr);
924 check_result(result, "isc_taskmgr_create");
926 result = isc_task_create(taskmgr, 0, &global_task);
927 check_result(result, "isc_task_create");
929 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
930 check_result(result, "isc_task_onshutdown");
932 result = dst_lib_init(gmctx, entropy, 0);
933 check_result(result, "dst_lib_init");
934 is_dst_up = ISC_TRUE;
936 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
937 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
939 if (have_ipv6) {
940 attrs = DNS_DISPATCHATTR_UDP;
941 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
942 attrs |= DNS_DISPATCHATTR_IPV6;
943 isc_sockaddr_any6(&bind_any6);
944 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
945 &bind_any6, PACKETSIZE,
946 4, 2, 3, 5,
947 attrs, attrmask, &dispatchv6);
948 check_result(result, "dns_dispatch_getudp (v6)");
951 if (have_ipv4) {
952 attrs = DNS_DISPATCHATTR_UDP;
953 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
954 attrs |= DNS_DISPATCHATTR_IPV4;
955 isc_sockaddr_any(&bind_any);
956 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
957 &bind_any, PACKETSIZE,
958 4, 2, 3, 5,
959 attrs, attrmask, &dispatchv4);
960 check_result(result, "dns_dispatch_getudp (v4)");
963 result = dns_requestmgr_create(gmctx, timermgr,
964 socketmgr, taskmgr, dispatchmgr,
965 dispatchv4, dispatchv6, &requestmgr);
966 check_result(result, "dns_requestmgr_create");
968 if (keystr != NULL)
969 setup_keystr();
970 else if (local_only) {
971 result = read_sessionkey(gmctx, glctx);
972 if (result != ISC_R_SUCCESS)
973 fatal("can't read key from %s: %s\n",
974 keyfile, isc_result_totext(result));
975 } else if (keyfile != NULL)
976 setup_keyfile(gmctx, glctx);
979 static void
980 get_addresses(char *host, in_port_t port,
981 isc_sockaddr_t *sockaddr, int naddrs)
983 int count;
984 isc_result_t result;
986 isc_app_block();
987 result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
988 isc_app_unblock();
989 if (result != ISC_R_SUCCESS)
990 fatal("couldn't get address for '%s': %s",
991 host, isc_result_totext(result));
994 static void
995 version(void) {
996 fputs("nsupdate " VERSION "\n", stderr);
999 #define PARSE_ARGS_FMT "dDML:y:ghlovk:p:Pr:R::t:Tu:V"
1001 static void
1002 pre_parse_args(int argc, char **argv) {
1003 dns_rdatatype_t t;
1004 int ch;
1005 char buf[100];
1006 isc_boolean_t doexit = ISC_FALSE;
1008 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1009 switch (ch) {
1010 case 'M': /* was -dm */
1011 debugging = ISC_TRUE;
1012 ddebugging = ISC_TRUE;
1013 memdebugging = ISC_TRUE;
1014 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
1015 ISC_MEM_DEBUGRECORD;
1016 break;
1018 case '?':
1019 case 'h':
1020 if (isc_commandline_option != '?')
1021 fprintf(stderr, "%s: invalid argument -%c\n",
1022 argv[0], isc_commandline_option);
1023 fprintf(stderr, "usage: nsupdate [-dD] [-L level] [-l]"
1024 "[-g | -o | -y keyname:secret | -k keyfile] "
1025 "[-v] [-V] [filename]\n");
1026 exit(1);
1028 case 'P':
1029 for (t = 0xff00; t <= 0xfffe; t++) {
1030 if (dns_rdatatype_ismeta(t))
1031 continue;
1032 dns_rdatatype_format(t, buf, sizeof(buf));
1033 if (strncmp(buf, "TYPE", 4) != 0)
1034 fprintf(stdout, "%s\n", buf);
1036 doexit = ISC_TRUE;
1037 break;
1039 case 'T':
1040 for (t = 1; t <= 0xfeff; t++) {
1041 if (dns_rdatatype_ismeta(t))
1042 continue;
1043 dns_rdatatype_format(t, buf, sizeof(buf));
1044 if (strncmp(buf, "TYPE", 4) != 0)
1045 fprintf(stdout, "%s\n", buf);
1047 doexit = ISC_TRUE;
1048 break;
1050 case 'V':
1051 version();
1052 doexit = ISC_TRUE;
1053 break;
1055 default:
1056 break;
1059 if (doexit)
1060 exit(0);
1061 isc_commandline_reset = ISC_TRUE;
1062 isc_commandline_index = 1;
1065 static void
1066 parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
1067 int ch;
1068 isc_uint32_t i;
1069 isc_result_t result;
1071 debug("parse_args");
1072 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1073 switch (ch) {
1074 case 'd':
1075 debugging = ISC_TRUE;
1076 break;
1077 case 'D': /* was -dd */
1078 debugging = ISC_TRUE;
1079 ddebugging = ISC_TRUE;
1080 break;
1081 case 'M':
1082 break;
1083 case 'l':
1084 local_only = ISC_TRUE;
1085 break;
1086 case 'L':
1087 result = isc_parse_uint32(&i, isc_commandline_argument,
1088 10);
1089 if (result != ISC_R_SUCCESS) {
1090 fprintf(stderr, "bad library debug value "
1091 "'%s'\n", isc_commandline_argument);
1092 exit(1);
1094 logdebuglevel = i;
1095 break;
1096 case 'y':
1097 keystr = isc_commandline_argument;
1098 break;
1099 case 'v':
1100 usevc = ISC_TRUE;
1101 break;
1102 case 'k':
1103 keyfile = isc_commandline_argument;
1104 break;
1105 case 'g':
1106 usegsstsig = ISC_TRUE;
1107 use_win2k_gsstsig = ISC_FALSE;
1108 break;
1109 case 'o':
1110 usegsstsig = ISC_TRUE;
1111 use_win2k_gsstsig = ISC_TRUE;
1112 break;
1113 case 'p':
1114 result = isc_parse_uint16(&dnsport,
1115 isc_commandline_argument, 10);
1116 if (result != ISC_R_SUCCESS) {
1117 fprintf(stderr, "bad port number "
1118 "'%s'\n", isc_commandline_argument);
1119 exit(1);
1121 break;
1122 case 't':
1123 result = isc_parse_uint32(&timeout,
1124 isc_commandline_argument, 10);
1125 if (result != ISC_R_SUCCESS) {
1126 fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
1127 exit(1);
1129 if (timeout == 0)
1130 timeout = UINT_MAX;
1131 break;
1132 case 'u':
1133 result = isc_parse_uint32(&udp_timeout,
1134 isc_commandline_argument, 10);
1135 if (result != ISC_R_SUCCESS) {
1136 fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
1137 exit(1);
1139 if (udp_timeout == 0)
1140 udp_timeout = UINT_MAX;
1141 break;
1142 case 'r':
1143 result = isc_parse_uint32(&udp_retries,
1144 isc_commandline_argument, 10);
1145 if (result != ISC_R_SUCCESS) {
1146 fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
1147 exit(1);
1149 break;
1151 case 'R':
1152 setup_entropy(mctx, isc_commandline_argument, ectx);
1153 break;
1155 default:
1156 fprintf(stderr, "%s: unhandled option: %c\n",
1157 argv[0], isc_commandline_option);
1158 exit(1);
1161 if (keyfile != NULL && keystr != NULL) {
1162 fprintf(stderr, "%s: cannot specify both -k and -y\n",
1163 argv[0]);
1164 exit(1);
1167 #ifdef GSSAPI
1168 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1169 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1170 argv[0]);
1171 exit(1);
1173 #else
1174 if (usegsstsig) {
1175 fprintf(stderr, "%s: cannot specify -g or -o, " \
1176 "program not linked with GSS API Library\n",
1177 argv[0]);
1178 exit(1);
1180 #endif
1182 if (argv[isc_commandline_index] != NULL) {
1183 if (strcmp(argv[isc_commandline_index], "-") == 0) {
1184 input = stdin;
1185 } else {
1186 result = isc_stdio_open(argv[isc_commandline_index],
1187 "r", &input);
1188 if (result != ISC_R_SUCCESS) {
1189 fprintf(stderr, "could not open '%s': %s\n",
1190 argv[isc_commandline_index],
1191 isc_result_totext(result));
1192 exit(1);
1195 interactive = ISC_FALSE;
1199 static isc_uint16_t
1200 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1201 isc_result_t result;
1202 char *word;
1203 isc_buffer_t *namebuf = NULL;
1204 isc_buffer_t source;
1206 word = nsu_strsep(cmdlinep, " \t\r\n");
1207 if (word == NULL || *word == 0) {
1208 fprintf(stderr, "could not read owner name\n");
1209 return (STATUS_SYNTAX);
1212 result = dns_message_gettempname(msg, namep);
1213 check_result(result, "dns_message_gettempname");
1214 result = isc_buffer_allocate(gmctx, &namebuf, DNS_NAME_MAXWIRE);
1215 check_result(result, "isc_buffer_allocate");
1216 dns_name_init(*namep, NULL);
1217 dns_name_setbuffer(*namep, namebuf);
1218 dns_message_takebuffer(msg, &namebuf);
1219 isc_buffer_init(&source, word, strlen(word));
1220 isc_buffer_add(&source, strlen(word));
1221 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
1222 check_result(result, "dns_name_fromtext");
1223 isc_buffer_invalidate(&source);
1224 return (STATUS_MORE);
1227 static isc_uint16_t
1228 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1229 dns_rdatatype_t rdatatype, dns_message_t *msg,
1230 dns_rdata_t *rdata)
1232 char *cmdline = *cmdlinep;
1233 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1234 isc_region_t r;
1235 isc_lex_t *lex = NULL;
1236 dns_rdatacallbacks_t callbacks;
1237 isc_result_t result;
1239 if (cmdline == NULL) {
1240 rdata->flags = DNS_RDATA_UPDATE;
1241 return (STATUS_MORE);
1244 while (*cmdline != 0 && isspace((unsigned char)*cmdline))
1245 cmdline++;
1247 if (*cmdline != 0) {
1248 dns_rdatacallbacks_init(&callbacks);
1249 result = isc_lex_create(gmctx, strlen(cmdline), &lex);
1250 check_result(result, "isc_lex_create");
1251 isc_buffer_init(&source, cmdline, strlen(cmdline));
1252 isc_buffer_add(&source, strlen(cmdline));
1253 result = isc_lex_openbuffer(lex, &source);
1254 check_result(result, "isc_lex_openbuffer");
1255 result = isc_buffer_allocate(gmctx, &buf, MAXWIRE);
1256 check_result(result, "isc_buffer_allocate");
1257 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1258 dns_rootname, 0, gmctx, buf,
1259 &callbacks);
1260 isc_lex_destroy(&lex);
1261 if (result == ISC_R_SUCCESS) {
1262 isc_buffer_usedregion(buf, &r);
1263 result = isc_buffer_allocate(gmctx, &newbuf, r.length);
1264 check_result(result, "isc_buffer_allocate");
1265 isc_buffer_putmem(newbuf, r.base, r.length);
1266 isc_buffer_usedregion(newbuf, &r);
1267 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1268 isc_buffer_free(&buf);
1269 dns_message_takebuffer(msg, &newbuf);
1270 } else {
1271 fprintf(stderr, "invalid rdata format: %s\n",
1272 isc_result_totext(result));
1273 isc_buffer_free(&buf);
1274 return (STATUS_SYNTAX);
1276 } else {
1277 rdata->flags = DNS_RDATA_UPDATE;
1279 *cmdlinep = cmdline;
1280 return (STATUS_MORE);
1283 static isc_uint16_t
1284 make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
1285 isc_result_t result;
1286 char *word;
1287 dns_name_t *name = NULL;
1288 isc_textregion_t region;
1289 dns_rdataset_t *rdataset = NULL;
1290 dns_rdatalist_t *rdatalist = NULL;
1291 dns_rdataclass_t rdataclass;
1292 dns_rdatatype_t rdatatype;
1293 dns_rdata_t *rdata = NULL;
1294 isc_uint16_t retval;
1296 ddebug("make_prereq()");
1299 * Read the owner name
1301 retval = parse_name(&cmdline, updatemsg, &name);
1302 if (retval != STATUS_MORE)
1303 return (retval);
1306 * If this is an rrset prereq, read the class or type.
1308 if (isrrset) {
1309 word = nsu_strsep(&cmdline, " \t\r\n");
1310 if (word == NULL || *word == 0) {
1311 fprintf(stderr, "could not read class or type\n");
1312 goto failure;
1314 region.base = word;
1315 region.length = strlen(word);
1316 result = dns_rdataclass_fromtext(&rdataclass, &region);
1317 if (result == ISC_R_SUCCESS) {
1318 if (!setzoneclass(rdataclass)) {
1319 fprintf(stderr, "class mismatch: %s\n", word);
1320 goto failure;
1323 * Now read the type.
1325 word = nsu_strsep(&cmdline, " \t\r\n");
1326 if (word == NULL || *word == 0) {
1327 fprintf(stderr, "could not read type\n");
1328 goto failure;
1330 region.base = word;
1331 region.length = strlen(word);
1332 result = dns_rdatatype_fromtext(&rdatatype, &region);
1333 if (result != ISC_R_SUCCESS) {
1334 fprintf(stderr, "invalid type: %s\n", word);
1335 goto failure;
1337 } else {
1338 rdataclass = getzoneclass();
1339 result = dns_rdatatype_fromtext(&rdatatype, &region);
1340 if (result != ISC_R_SUCCESS) {
1341 fprintf(stderr, "invalid type: %s\n", word);
1342 goto failure;
1345 } else
1346 rdatatype = dns_rdatatype_any;
1348 result = dns_message_gettemprdata(updatemsg, &rdata);
1349 check_result(result, "dns_message_gettemprdata");
1351 dns_rdata_init(rdata);
1353 if (isrrset && ispositive) {
1354 retval = parse_rdata(&cmdline, rdataclass, rdatatype,
1355 updatemsg, rdata);
1356 if (retval != STATUS_MORE)
1357 goto failure;
1358 } else
1359 rdata->flags = DNS_RDATA_UPDATE;
1361 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1362 check_result(result, "dns_message_gettemprdatalist");
1363 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1364 check_result(result, "dns_message_gettemprdataset");
1365 dns_rdatalist_init(rdatalist);
1366 rdatalist->type = rdatatype;
1367 if (ispositive) {
1368 if (isrrset && rdata->data != NULL)
1369 rdatalist->rdclass = rdataclass;
1370 else
1371 rdatalist->rdclass = dns_rdataclass_any;
1372 } else
1373 rdatalist->rdclass = dns_rdataclass_none;
1374 rdatalist->covers = 0;
1375 rdatalist->ttl = 0;
1376 rdata->rdclass = rdatalist->rdclass;
1377 rdata->type = rdatatype;
1378 ISC_LIST_INIT(rdatalist->rdata);
1379 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1380 dns_rdatalist_tordataset(rdatalist, rdataset);
1381 ISC_LIST_INIT(name->list);
1382 ISC_LIST_APPEND(name->list, rdataset, link);
1383 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1384 return (STATUS_MORE);
1386 failure:
1387 if (name != NULL)
1388 dns_message_puttempname(updatemsg, &name);
1389 return (STATUS_SYNTAX);
1392 static isc_uint16_t
1393 evaluate_prereq(char *cmdline) {
1394 char *word;
1395 isc_boolean_t ispositive, isrrset;
1397 ddebug("evaluate_prereq()");
1398 word = nsu_strsep(&cmdline, " \t\r\n");
1399 if (word == NULL || *word == 0) {
1400 fprintf(stderr, "could not read operation code\n");
1401 return (STATUS_SYNTAX);
1403 if (strcasecmp(word, "nxdomain") == 0) {
1404 ispositive = ISC_FALSE;
1405 isrrset = ISC_FALSE;
1406 } else if (strcasecmp(word, "yxdomain") == 0) {
1407 ispositive = ISC_TRUE;
1408 isrrset = ISC_FALSE;
1409 } else if (strcasecmp(word, "nxrrset") == 0) {
1410 ispositive = ISC_FALSE;
1411 isrrset = ISC_TRUE;
1412 } else if (strcasecmp(word, "yxrrset") == 0) {
1413 ispositive = ISC_TRUE;
1414 isrrset = ISC_TRUE;
1415 } else {
1416 fprintf(stderr, "incorrect operation code: %s\n", word);
1417 return (STATUS_SYNTAX);
1419 return (make_prereq(cmdline, ispositive, isrrset));
1422 static isc_uint16_t
1423 evaluate_server(char *cmdline) {
1424 char *word, *server;
1425 long port;
1427 if (local_only) {
1428 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1429 return (STATUS_SYNTAX);
1432 word = nsu_strsep(&cmdline, " \t\r\n");
1433 if (word == NULL || *word == 0) {
1434 fprintf(stderr, "could not read server name\n");
1435 return (STATUS_SYNTAX);
1437 server = word;
1439 word = nsu_strsep(&cmdline, " \t\r\n");
1440 if (word == NULL || *word == 0)
1441 port = dnsport;
1442 else {
1443 char *endp;
1444 port = strtol(word, &endp, 10);
1445 if (*endp != 0) {
1446 fprintf(stderr, "port '%s' is not numeric\n", word);
1447 return (STATUS_SYNTAX);
1448 } else if (port < 1 || port > 65535) {
1449 fprintf(stderr, "port '%s' is out of range "
1450 "(1 to 65535)\n", word);
1451 return (STATUS_SYNTAX);
1455 if (servers != NULL) {
1456 if (master_servers == servers)
1457 master_servers = NULL;
1458 isc_mem_put(gmctx, servers, ns_total * sizeof(isc_sockaddr_t));
1461 default_servers = ISC_FALSE;
1463 ns_total = MAX_SERVERADDRS;
1464 ns_inuse = 0;
1465 servers = isc_mem_get(gmctx, ns_total * sizeof(isc_sockaddr_t));
1466 if (servers == NULL)
1467 fatal("out of memory");
1469 memset(servers, 0, ns_total * sizeof(isc_sockaddr_t));
1470 get_addresses(server, (in_port_t)port, servers, ns_total);
1472 return (STATUS_MORE);
1475 static isc_uint16_t
1476 evaluate_local(char *cmdline) {
1477 char *word, *local;
1478 long port;
1479 struct in_addr in4;
1480 struct in6_addr in6;
1482 word = nsu_strsep(&cmdline, " \t\r\n");
1483 if (word == NULL || *word == 0) {
1484 fprintf(stderr, "could not read server name\n");
1485 return (STATUS_SYNTAX);
1487 local = word;
1489 word = nsu_strsep(&cmdline, " \t\r\n");
1490 if (word == NULL || *word == 0)
1491 port = 0;
1492 else {
1493 char *endp;
1494 port = strtol(word, &endp, 10);
1495 if (*endp != 0) {
1496 fprintf(stderr, "port '%s' is not numeric\n", word);
1497 return (STATUS_SYNTAX);
1498 } else if (port < 1 || port > 65535) {
1499 fprintf(stderr, "port '%s' is out of range "
1500 "(1 to 65535)\n", word);
1501 return (STATUS_SYNTAX);
1505 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) {
1506 if (localaddr6 == NULL)
1507 localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1508 if (localaddr6 == NULL)
1509 fatal("out of memory");
1510 isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port);
1511 } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) {
1512 if (localaddr4 == NULL)
1513 localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1514 if (localaddr4 == NULL)
1515 fatal("out of memory");
1516 isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port);
1517 } else {
1518 fprintf(stderr, "invalid address %s", local);
1519 return (STATUS_SYNTAX);
1522 return (STATUS_MORE);
1525 static isc_uint16_t
1526 evaluate_key(char *cmdline) {
1527 char *namestr;
1528 char *secretstr;
1529 isc_buffer_t b;
1530 isc_result_t result;
1531 dns_fixedname_t fkeyname;
1532 dns_name_t *mykeyname;
1533 int secretlen;
1534 unsigned char *secret = NULL;
1535 isc_buffer_t secretbuf;
1536 dns_name_t *hmacname = NULL;
1537 isc_uint16_t digestbits = 0;
1538 char *n;
1540 namestr = nsu_strsep(&cmdline, " \t\r\n");
1541 if (namestr == NULL || *namestr == 0) {
1542 fprintf(stderr, "could not read key name\n");
1543 return (STATUS_SYNTAX);
1546 dns_fixedname_init(&fkeyname);
1547 mykeyname = dns_fixedname_name(&fkeyname);
1549 n = strchr(namestr, ':');
1550 if (n != NULL) {
1551 digestbits = parse_hmac(&hmacname, namestr, n - namestr);
1552 namestr = n + 1;
1553 } else
1554 hmacname = DNS_TSIG_HMACMD5_NAME;
1556 isc_buffer_init(&b, namestr, strlen(namestr));
1557 isc_buffer_add(&b, strlen(namestr));
1558 result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL);
1559 if (result != ISC_R_SUCCESS) {
1560 fprintf(stderr, "could not parse key name\n");
1561 return (STATUS_SYNTAX);
1564 secretstr = nsu_strsep(&cmdline, "\r\n");
1565 if (secretstr == NULL || *secretstr == 0) {
1566 fprintf(stderr, "could not read key secret\n");
1567 return (STATUS_SYNTAX);
1569 secretlen = strlen(secretstr) * 3 / 4;
1570 secret = isc_mem_allocate(gmctx, secretlen);
1571 if (secret == NULL)
1572 fatal("out of memory");
1574 isc_buffer_init(&secretbuf, secret, secretlen);
1575 result = isc_base64_decodestring(secretstr, &secretbuf);
1576 if (result != ISC_R_SUCCESS) {
1577 fprintf(stderr, "could not create key from %s: %s\n",
1578 secretstr, isc_result_totext(result));
1579 isc_mem_free(gmctx, secret);
1580 return (STATUS_SYNTAX);
1582 secretlen = isc_buffer_usedlength(&secretbuf);
1584 if (tsigkey != NULL)
1585 dns_tsigkey_detach(&tsigkey);
1586 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
1587 ISC_FALSE, NULL, 0, 0, gmctx, NULL,
1588 &tsigkey);
1589 isc_mem_free(gmctx, secret);
1590 if (result != ISC_R_SUCCESS) {
1591 fprintf(stderr, "could not create key from %s %s: %s\n",
1592 namestr, secretstr, dns_result_totext(result));
1593 return (STATUS_SYNTAX);
1595 dst_key_setbits(tsigkey->key, digestbits);
1596 return (STATUS_MORE);
1599 static isc_uint16_t
1600 evaluate_zone(char *cmdline) {
1601 char *word;
1602 isc_buffer_t b;
1603 isc_result_t result;
1605 word = nsu_strsep(&cmdline, " \t\r\n");
1606 if (word == NULL || *word == 0) {
1607 fprintf(stderr, "could not read zone name\n");
1608 return (STATUS_SYNTAX);
1611 dns_fixedname_init(&fuserzone);
1612 userzone = dns_fixedname_name(&fuserzone);
1613 isc_buffer_init(&b, word, strlen(word));
1614 isc_buffer_add(&b, strlen(word));
1615 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1616 if (result != ISC_R_SUCCESS) {
1617 userzone = NULL; /* Lest it point to an invalid name */
1618 fprintf(stderr, "could not parse zone name\n");
1619 return (STATUS_SYNTAX);
1622 return (STATUS_MORE);
1625 static isc_uint16_t
1626 evaluate_realm(char *cmdline) {
1627 #ifdef GSSAPI
1628 char *word;
1629 char buf[1024];
1630 int n;
1632 if (realm != NULL) {
1633 isc_mem_free(gmctx, realm);
1634 realm = NULL;
1637 word = nsu_strsep(&cmdline, " \t\r\n");
1638 if (word == NULL || *word == 0)
1639 return (STATUS_MORE);
1641 n = snprintf(buf, sizeof(buf), "@%s", word);
1642 if (n < 0 || (size_t)n >= sizeof(buf))
1643 fatal("realm is too long");
1644 realm = isc_mem_strdup(gmctx, buf);
1645 if (realm == NULL)
1646 fatal("out of memory");
1647 return (STATUS_MORE);
1648 #else
1649 UNUSED(cmdline);
1650 return (STATUS_SYNTAX);
1651 #endif
1654 static isc_uint16_t
1655 evaluate_ttl(char *cmdline) {
1656 char *word;
1657 isc_result_t result;
1658 isc_uint32_t ttl;
1660 word = nsu_strsep(&cmdline, " \t\r\n");
1661 if (word == NULL || *word == 0) {
1662 fprintf(stderr, "could not ttl\n");
1663 return (STATUS_SYNTAX);
1666 if (!strcasecmp(word, "none")) {
1667 default_ttl = 0;
1668 default_ttl_set = ISC_FALSE;
1669 return (STATUS_MORE);
1672 result = isc_parse_uint32(&ttl, word, 10);
1673 if (result != ISC_R_SUCCESS)
1674 return (STATUS_SYNTAX);
1676 if (ttl > TTL_MAX) {
1677 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1678 word, TTL_MAX);
1679 return (STATUS_SYNTAX);
1681 default_ttl = ttl;
1682 default_ttl_set = ISC_TRUE;
1684 return (STATUS_MORE);
1687 static isc_uint16_t
1688 evaluate_class(char *cmdline) {
1689 char *word;
1690 isc_textregion_t r;
1691 isc_result_t result;
1692 dns_rdataclass_t rdclass;
1694 word = nsu_strsep(&cmdline, " \t\r\n");
1695 if (word == NULL || *word == 0) {
1696 fprintf(stderr, "could not read class name\n");
1697 return (STATUS_SYNTAX);
1700 r.base = word;
1701 r.length = strlen(word);
1702 result = dns_rdataclass_fromtext(&rdclass, &r);
1703 if (result != ISC_R_SUCCESS) {
1704 fprintf(stderr, "could not parse class name: %s\n", word);
1705 return (STATUS_SYNTAX);
1707 switch (rdclass) {
1708 case dns_rdataclass_none:
1709 case dns_rdataclass_any:
1710 case dns_rdataclass_reserved0:
1711 fprintf(stderr, "bad default class: %s\n", word);
1712 return (STATUS_SYNTAX);
1713 default:
1714 defaultclass = rdclass;
1717 return (STATUS_MORE);
1720 static isc_uint16_t
1721 update_addordelete(char *cmdline, isc_boolean_t isdelete) {
1722 isc_result_t result;
1723 dns_name_t *name = NULL;
1724 isc_uint32_t ttl;
1725 char *word;
1726 dns_rdataclass_t rdataclass;
1727 dns_rdatatype_t rdatatype;
1728 dns_rdata_t *rdata = NULL;
1729 dns_rdatalist_t *rdatalist = NULL;
1730 dns_rdataset_t *rdataset = NULL;
1731 isc_textregion_t region;
1732 isc_uint16_t retval;
1734 ddebug("update_addordelete()");
1737 * Read the owner name.
1739 retval = parse_name(&cmdline, updatemsg, &name);
1740 if (retval != STATUS_MORE)
1741 return (retval);
1743 result = dns_message_gettemprdata(updatemsg, &rdata);
1744 check_result(result, "dns_message_gettemprdata");
1746 dns_rdata_init(rdata);
1749 * If this is an add, read the TTL and verify that it's in range.
1750 * If it's a delete, ignore a TTL if present (for compatibility).
1752 word = nsu_strsep(&cmdline, " \t\r\n");
1753 if (word == NULL || *word == 0) {
1754 if (!isdelete) {
1755 fprintf(stderr, "could not read owner ttl\n");
1756 goto failure;
1758 else {
1759 ttl = 0;
1760 rdataclass = dns_rdataclass_any;
1761 rdatatype = dns_rdatatype_any;
1762 rdata->flags = DNS_RDATA_UPDATE;
1763 goto doneparsing;
1766 result = isc_parse_uint32(&ttl, word, 10);
1767 if (result != ISC_R_SUCCESS) {
1768 if (isdelete) {
1769 ttl = 0;
1770 goto parseclass;
1771 } else if (default_ttl_set) {
1772 ttl = default_ttl;
1773 goto parseclass;
1774 } else {
1775 fprintf(stderr, "ttl '%s': %s\n", word,
1776 isc_result_totext(result));
1777 goto failure;
1781 if (isdelete)
1782 ttl = 0;
1783 else if (ttl > TTL_MAX) {
1784 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
1785 word, TTL_MAX);
1786 goto failure;
1790 * Read the class or type.
1792 word = nsu_strsep(&cmdline, " \t\r\n");
1793 parseclass:
1794 if (word == NULL || *word == 0) {
1795 if (isdelete) {
1796 rdataclass = dns_rdataclass_any;
1797 rdatatype = dns_rdatatype_any;
1798 rdata->flags = DNS_RDATA_UPDATE;
1799 goto doneparsing;
1800 } else {
1801 fprintf(stderr, "could not read class or type\n");
1802 goto failure;
1805 region.base = word;
1806 region.length = strlen(word);
1807 rdataclass = dns_rdataclass_any;
1808 result = dns_rdataclass_fromtext(&rdataclass, &region);
1809 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1810 if (!setzoneclass(rdataclass)) {
1811 fprintf(stderr, "class mismatch: %s\n", word);
1812 goto failure;
1815 * Now read the type.
1817 word = nsu_strsep(&cmdline, " \t\r\n");
1818 if (word == NULL || *word == 0) {
1819 if (isdelete) {
1820 rdataclass = dns_rdataclass_any;
1821 rdatatype = dns_rdatatype_any;
1822 rdata->flags = DNS_RDATA_UPDATE;
1823 goto doneparsing;
1824 } else {
1825 fprintf(stderr, "could not read type\n");
1826 goto failure;
1829 region.base = word;
1830 region.length = strlen(word);
1831 result = dns_rdatatype_fromtext(&rdatatype, &region);
1832 if (result != ISC_R_SUCCESS) {
1833 fprintf(stderr, "'%s' is not a valid type: %s\n",
1834 word, isc_result_totext(result));
1835 goto failure;
1837 } else {
1838 rdataclass = getzoneclass();
1839 result = dns_rdatatype_fromtext(&rdatatype, &region);
1840 if (result != ISC_R_SUCCESS) {
1841 fprintf(stderr, "'%s' is not a valid class or type: "
1842 "%s\n", word, isc_result_totext(result));
1843 goto failure;
1847 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1848 rdata);
1849 if (retval != STATUS_MORE)
1850 goto failure;
1852 if (isdelete) {
1853 if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
1854 rdataclass = dns_rdataclass_any;
1855 else
1856 rdataclass = dns_rdataclass_none;
1857 } else {
1858 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1859 fprintf(stderr, "could not read rdata\n");
1860 goto failure;
1864 doneparsing:
1866 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1867 check_result(result, "dns_message_gettemprdatalist");
1868 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1869 check_result(result, "dns_message_gettemprdataset");
1870 dns_rdatalist_init(rdatalist);
1871 rdatalist->type = rdatatype;
1872 rdatalist->rdclass = rdataclass;
1873 rdatalist->covers = rdatatype;
1874 rdatalist->ttl = (dns_ttl_t)ttl;
1875 ISC_LIST_INIT(rdatalist->rdata);
1876 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1877 dns_rdatalist_tordataset(rdatalist, rdataset);
1878 ISC_LIST_INIT(name->list);
1879 ISC_LIST_APPEND(name->list, rdataset, link);
1880 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
1881 return (STATUS_MORE);
1883 failure:
1884 if (name != NULL)
1885 dns_message_puttempname(updatemsg, &name);
1886 dns_message_puttemprdata(updatemsg, &rdata);
1887 return (STATUS_SYNTAX);
1890 static isc_uint16_t
1891 evaluate_update(char *cmdline) {
1892 char *word;
1893 isc_boolean_t isdelete;
1895 ddebug("evaluate_update()");
1896 word = nsu_strsep(&cmdline, " \t\r\n");
1897 if (word == NULL || *word == 0) {
1898 fprintf(stderr, "could not read operation code\n");
1899 return (STATUS_SYNTAX);
1901 if (strcasecmp(word, "delete") == 0)
1902 isdelete = ISC_TRUE;
1903 else if (strcasecmp(word, "del") == 0)
1904 isdelete = ISC_TRUE;
1905 else if (strcasecmp(word, "add") == 0)
1906 isdelete = ISC_FALSE;
1907 else {
1908 fprintf(stderr, "incorrect operation code: %s\n", word);
1909 return (STATUS_SYNTAX);
1911 return (update_addordelete(cmdline, isdelete));
1914 static void
1915 setzone(dns_name_t *zonename) {
1916 isc_result_t result;
1917 dns_name_t *name = NULL;
1918 dns_rdataset_t *rdataset = NULL;
1920 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
1921 if (result == ISC_R_SUCCESS) {
1922 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
1923 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
1924 for (rdataset = ISC_LIST_HEAD(name->list);
1925 rdataset != NULL;
1926 rdataset = ISC_LIST_HEAD(name->list)) {
1927 ISC_LIST_UNLINK(name->list, rdataset, link);
1928 dns_rdataset_disassociate(rdataset);
1929 dns_message_puttemprdataset(updatemsg, &rdataset);
1931 dns_message_puttempname(updatemsg, &name);
1934 if (zonename != NULL) {
1935 result = dns_message_gettempname(updatemsg, &name);
1936 check_result(result, "dns_message_gettempname");
1937 dns_name_init(name, NULL);
1938 dns_name_clone(zonename, name);
1939 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1940 check_result(result, "dns_message_gettemprdataset");
1941 dns_rdataset_makequestion(rdataset, getzoneclass(),
1942 dns_rdatatype_soa);
1943 ISC_LIST_INIT(name->list);
1944 ISC_LIST_APPEND(name->list, rdataset, link);
1945 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
1949 static void
1950 show_message(FILE *stream, dns_message_t *msg, const char *description) {
1951 isc_result_t result;
1952 isc_buffer_t *buf = NULL;
1953 int bufsz;
1955 ddebug("show_message()");
1957 setzone(userzone);
1959 bufsz = INITTEXT;
1960 do {
1961 if (bufsz > MAXTEXT) {
1962 fprintf(stderr, "could not allocate large enough "
1963 "buffer to display message\n");
1964 exit(1);
1966 if (buf != NULL)
1967 isc_buffer_free(&buf);
1968 result = isc_buffer_allocate(gmctx, &buf, bufsz);
1969 check_result(result, "isc_buffer_allocate");
1970 result = dns_message_totext(msg, style, 0, buf);
1971 bufsz *= 2;
1972 } while (result == ISC_R_NOSPACE);
1973 if (result != ISC_R_SUCCESS) {
1974 fprintf(stderr, "could not convert message to text format.\n");
1975 isc_buffer_free(&buf);
1976 return;
1978 fprintf(stream, "%s\n%.*s", description,
1979 (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
1980 isc_buffer_free(&buf);
1983 static isc_uint16_t
1984 do_next_command(char *cmdline) {
1985 char *word;
1987 ddebug("do_next_command()");
1988 word = nsu_strsep(&cmdline, " \t\r\n");
1990 if (word == NULL || *word == 0)
1991 return (STATUS_SEND);
1992 if (word[0] == ';')
1993 return (STATUS_MORE);
1994 if (strcasecmp(word, "quit") == 0)
1995 return (STATUS_QUIT);
1996 if (strcasecmp(word, "prereq") == 0)
1997 return (evaluate_prereq(cmdline));
1998 if (strcasecmp(word, "nxdomain") == 0)
1999 return (make_prereq(cmdline, ISC_FALSE, ISC_FALSE));
2000 if (strcasecmp(word, "yxdomain") == 0)
2001 return (make_prereq(cmdline, ISC_TRUE, ISC_FALSE));
2002 if (strcasecmp(word, "nxrrset") == 0)
2003 return (make_prereq(cmdline, ISC_FALSE, ISC_TRUE));
2004 if (strcasecmp(word, "yxrrset") == 0)
2005 return (make_prereq(cmdline, ISC_TRUE, ISC_TRUE));
2006 if (strcasecmp(word, "update") == 0)
2007 return (evaluate_update(cmdline));
2008 if (strcasecmp(word, "delete") == 0)
2009 return (update_addordelete(cmdline, ISC_TRUE));
2010 if (strcasecmp(word, "del") == 0)
2011 return (update_addordelete(cmdline, ISC_TRUE));
2012 if (strcasecmp(word, "add") == 0)
2013 return (update_addordelete(cmdline, ISC_FALSE));
2014 if (strcasecmp(word, "server") == 0)
2015 return (evaluate_server(cmdline));
2016 if (strcasecmp(word, "local") == 0)
2017 return (evaluate_local(cmdline));
2018 if (strcasecmp(word, "zone") == 0)
2019 return (evaluate_zone(cmdline));
2020 if (strcasecmp(word, "class") == 0)
2021 return (evaluate_class(cmdline));
2022 if (strcasecmp(word, "send") == 0)
2023 return (STATUS_SEND);
2024 if (strcasecmp(word, "debug") == 0) {
2025 if (debugging)
2026 ddebugging = ISC_TRUE;
2027 else
2028 debugging = ISC_TRUE;
2029 return (STATUS_MORE);
2031 if (strcasecmp(word, "ttl") == 0)
2032 return (evaluate_ttl(cmdline));
2033 if (strcasecmp(word, "show") == 0) {
2034 show_message(stdout, updatemsg, "Outgoing update query:");
2035 return (STATUS_MORE);
2037 if (strcasecmp(word, "answer") == 0) {
2038 if (answer != NULL)
2039 show_message(stdout, answer, "Answer:");
2040 return (STATUS_MORE);
2042 if (strcasecmp(word, "key") == 0) {
2043 usegsstsig = ISC_FALSE;
2044 return (evaluate_key(cmdline));
2046 if (strcasecmp(word, "realm") == 0)
2047 return (evaluate_realm(cmdline));
2048 if (strcasecmp(word, "gsstsig") == 0) {
2049 #ifdef GSSAPI
2050 usegsstsig = ISC_TRUE;
2051 use_win2k_gsstsig = ISC_FALSE;
2052 #else
2053 fprintf(stderr, "gsstsig not supported\n");
2054 #endif
2055 return (STATUS_MORE);
2057 if (strcasecmp(word, "oldgsstsig") == 0) {
2058 #ifdef GSSAPI
2059 usegsstsig = ISC_TRUE;
2060 use_win2k_gsstsig = ISC_TRUE;
2061 #else
2062 fprintf(stderr, "gsstsig not supported\n");
2063 #endif
2064 return (STATUS_MORE);
2066 if (strcasecmp(word, "help") == 0) {
2067 fprintf(stdout,
2068 "nsupdate " VERSION ":\n"
2069 "local address [port] (set local resolver)\n"
2070 "server address [port] (set master server for zone)\n"
2071 "send (send the update request)\n"
2072 "show (show the update request)\n"
2073 "answer (show the answer to the last request)\n"
2074 "quit (quit, any pending update is not sent\n"
2075 "help (display this message_\n"
2076 "key [hmac:]keyname secret (use TSIG to sign the request)\n"
2077 "gsstsig (use GSS_TSIG to sign the request)\n"
2078 "oldgsstsig (use Microsoft's GSS_TSIG to sign the request)\n"
2079 "zone name (set the zone to be updated)\n"
2080 "class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
2081 "[prereq] nxdomain name (does this name not exist)\n"
2082 "[prereq] yxdomain name (does this name exist)\n"
2083 "[prereq] nxrrset .... (does this RRset exist)\n"
2084 "[prereq] yxrrset .... (does this RRset not exist)\n"
2085 "[update] add .... (add the given record to the zone)\n"
2086 "[update] del[ete] .... (remove the given record(s) from the zone)\n");
2087 return (STATUS_MORE);
2089 if (strcasecmp(word, "version") == 0) {
2090 fprintf(stdout, "nsupdate " VERSION "\n");
2091 return (STATUS_MORE);
2093 fprintf(stderr, "incorrect section name: %s\n", word);
2094 return (STATUS_SYNTAX);
2097 static isc_uint16_t
2098 get_next_command(void) {
2099 isc_uint16_t result = STATUS_QUIT;
2100 char cmdlinebuf[MAXCMD];
2101 char *cmdline;
2103 isc_app_block();
2104 if (interactive) {
2105 #ifdef HAVE_READLINE
2106 cmdline = readline("> ");
2107 if (cmdline != NULL)
2108 add_history(cmdline);
2109 #else
2110 fprintf(stdout, "> ");
2111 fflush(stdout);
2112 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2113 #endif
2114 } else
2115 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2116 isc_app_unblock();
2118 if (cmdline != NULL) {
2119 char *tmp = cmdline;
2122 * Normalize input by removing any eol as readline()
2123 * removes eol but fgets doesn't.
2125 (void)nsu_strsep(&tmp, "\r\n");
2126 result = do_next_command(cmdline);
2128 #ifdef HAVE_READLINE
2129 if (interactive)
2130 free(cmdline);
2131 #endif
2132 return (result);
2135 static isc_boolean_t
2136 user_interaction(void) {
2137 isc_uint16_t result = STATUS_MORE;
2139 ddebug("user_interaction()");
2140 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
2141 result = get_next_command();
2142 if (!interactive && result == STATUS_SYNTAX)
2143 fatal("syntax error");
2145 if (result == STATUS_SEND)
2146 return (ISC_TRUE);
2147 return (ISC_FALSE);
2151 static void
2152 done_update(void) {
2153 isc_event_t *event = global_event;
2154 ddebug("done_update()");
2155 isc_task_send(global_task, &event);
2158 static void
2159 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2160 isc_result_t result;
2161 dns_rdata_t rdata = DNS_RDATA_INIT;
2162 dns_rdata_any_tsig_t tsig;
2164 result = dns_rdataset_first(rdataset);
2165 check_result(result, "dns_rdataset_first");
2166 dns_rdataset_current(rdataset, &rdata);
2167 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2168 check_result(result, "dns_rdata_tostruct");
2169 if (tsig.error != 0) {
2170 if (isc_buffer_remaininglength(b) < 1)
2171 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2172 isc_buffer_putstr(b, "(" /*)*/);
2173 result = dns_tsigrcode_totext(tsig.error, b);
2174 check_result(result, "dns_tsigrcode_totext");
2175 if (isc_buffer_remaininglength(b) < 1)
2176 check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
2177 isc_buffer_putstr(b, /*(*/ ")");
2181 static isc_boolean_t
2182 next_master(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2183 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2185 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2186 fprintf(stderr, "; Communication with %s failed: %s\n",
2187 addrbuf, isc_result_totext(eresult));
2188 if (++master_inuse >= master_total)
2189 return (ISC_FALSE);
2190 ddebug("%s: trying next server", caller);
2191 return (ISC_TRUE);
2194 static void
2195 update_completed(isc_task_t *task, isc_event_t *event) {
2196 dns_requestevent_t *reqev = NULL;
2197 isc_result_t result;
2198 dns_request_t *request;
2200 UNUSED(task);
2202 ddebug("update_completed()");
2204 requests--;
2206 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2207 reqev = (dns_requestevent_t *)event;
2208 request = reqev->request;
2210 if (shuttingdown) {
2211 dns_request_destroy(&request);
2212 isc_event_free(&event);
2213 maybeshutdown();
2214 return;
2217 if (reqev->result != ISC_R_SUCCESS) {
2218 if (!next_master("recvsoa", &master_servers[master_inuse],
2219 reqev->result)) {
2220 seenerror = ISC_TRUE;
2221 goto done;
2224 ddebug("Destroying request [%p]", request);
2225 dns_request_destroy(&request);
2226 dns_message_renderreset(updatemsg);
2227 dns_message_settsigkey(updatemsg, NULL);
2228 send_update(zname, &master_servers[master_inuse]);
2229 isc_event_free(&event);
2230 return;
2233 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer);
2234 check_result(result, "dns_message_create");
2235 result = dns_request_getresponse(request, answer,
2236 DNS_MESSAGEPARSE_PRESERVEORDER);
2237 switch (result) {
2238 case ISC_R_SUCCESS:
2239 if (answer->verify_attempted)
2240 ddebug("tsig verification successful");
2241 break;
2242 case DNS_R_CLOCKSKEW:
2243 case DNS_R_EXPECTEDTSIG:
2244 case DNS_R_TSIGERRORSET:
2245 case DNS_R_TSIGVERIFYFAILURE:
2246 case DNS_R_UNEXPECTEDTSIG:
2247 case ISC_R_FAILURE:
2248 #if 0
2249 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2251 * For MS DNS that violates RFC 2845, section 4.2
2253 break;
2255 #endif
2256 fprintf(stderr, "; TSIG error with server: %s\n",
2257 isc_result_totext(result));
2258 seenerror = ISC_TRUE;
2259 break;
2260 default:
2261 check_result(result, "dns_request_getresponse");
2264 if (answer->rcode != dns_rcode_noerror) {
2265 seenerror = ISC_TRUE;
2266 if (!debugging) {
2267 char buf[64];
2268 isc_buffer_t b;
2269 dns_rdataset_t *rds;
2271 isc_buffer_init(&b, buf, sizeof(buf) - 1);
2272 result = dns_rcode_totext(answer->rcode, &b);
2273 check_result(result, "dns_rcode_totext");
2274 rds = dns_message_gettsig(answer, NULL);
2275 if (rds != NULL)
2276 check_tsig_error(rds, &b);
2277 fprintf(stderr, "update failed: %.*s\n",
2278 (int)isc_buffer_usedlength(&b), buf);
2281 if (debugging)
2282 show_message(stderr, answer, "\nReply from update query:");
2284 done:
2285 dns_request_destroy(&request);
2286 if (usegsstsig) {
2287 dns_name_free(&tmpzonename, gmctx);
2288 dns_name_free(&restart_master, gmctx);
2290 isc_event_free(&event);
2291 done_update();
2294 static void
2295 send_update(dns_name_t *zone, isc_sockaddr_t *master) {
2296 isc_result_t result;
2297 dns_request_t *request = NULL;
2298 unsigned int options = DNS_REQUESTOPT_CASE;
2299 isc_sockaddr_t *srcaddr;
2301 ddebug("send_update()");
2303 setzone(zone);
2305 if (usevc)
2306 options |= DNS_REQUESTOPT_TCP;
2307 if (tsigkey == NULL && sig0key != NULL) {
2308 result = dns_message_setsig0key(updatemsg, sig0key);
2309 check_result(result, "dns_message_setsig0key");
2311 if (debugging) {
2312 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2314 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2315 fprintf(stderr, "Sending update to %s\n", addrbuf);
2318 if (isc_sockaddr_pf(master) == AF_INET6)
2319 srcaddr = localaddr6;
2320 else
2321 srcaddr = localaddr4;
2323 /* Windows doesn't like the tsig name to be compressed. */
2324 if (updatemsg->tsigname)
2325 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2327 result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
2328 master, options, tsigkey, timeout,
2329 udp_timeout, udp_retries, global_task,
2330 update_completed, NULL, &request);
2331 check_result(result, "dns_request_createvia3");
2333 if (debugging)
2334 show_message(stdout, updatemsg, "Outgoing update query:");
2336 requests++;
2339 static void
2340 next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2341 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2343 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2344 fprintf(stderr, "; Communication with %s failed: %s\n",
2345 addrbuf, isc_result_totext(eresult));
2346 if (++ns_inuse >= ns_total)
2347 fatal("could not reach any name server");
2348 else
2349 ddebug("%s: trying next server", caller);
2352 static void
2353 recvsoa(isc_task_t *task, isc_event_t *event) {
2354 dns_requestevent_t *reqev = NULL;
2355 dns_request_t *request = NULL;
2356 isc_result_t result, eresult;
2357 dns_message_t *rcvmsg = NULL;
2358 dns_section_t section;
2359 dns_name_t *name = NULL;
2360 dns_rdataset_t *soaset = NULL;
2361 dns_rdata_soa_t soa;
2362 dns_rdata_t soarr = DNS_RDATA_INIT;
2363 int pass = 0;
2364 dns_name_t master;
2365 nsu_requestinfo_t *reqinfo;
2366 dns_message_t *soaquery = NULL;
2367 isc_sockaddr_t *addr;
2368 isc_sockaddr_t *srcaddr;
2369 isc_boolean_t seencname = ISC_FALSE;
2370 dns_name_t tname;
2371 unsigned int nlabels;
2373 UNUSED(task);
2375 ddebug("recvsoa()");
2377 requests--;
2379 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2380 reqev = (dns_requestevent_t *)event;
2381 request = reqev->request;
2382 eresult = reqev->result;
2383 reqinfo = reqev->ev_arg;
2384 soaquery = reqinfo->msg;
2385 addr = reqinfo->addr;
2387 if (shuttingdown) {
2388 dns_request_destroy(&request);
2389 dns_message_destroy(&soaquery);
2390 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2391 isc_event_free(&event);
2392 maybeshutdown();
2393 return;
2396 if (eresult != ISC_R_SUCCESS) {
2397 next_server("recvsoa", addr, eresult);
2398 ddebug("Destroying request [%p]", request);
2399 dns_request_destroy(&request);
2400 dns_message_renderreset(soaquery);
2401 dns_message_settsigkey(soaquery, NULL);
2402 sendrequest(&servers[ns_inuse], soaquery, &request);
2403 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2404 isc_event_free(&event);
2405 setzoneclass(dns_rdataclass_none);
2406 return;
2409 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2410 reqinfo = NULL;
2411 isc_event_free(&event);
2412 reqev = NULL;
2414 ddebug("About to create rcvmsg");
2415 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2416 check_result(result, "dns_message_create");
2417 result = dns_request_getresponse(request, rcvmsg,
2418 DNS_MESSAGEPARSE_PRESERVEORDER);
2419 if (result == DNS_R_TSIGERRORSET && servers != NULL) {
2420 dns_message_destroy(&rcvmsg);
2421 ddebug("Destroying request [%p]", request);
2422 dns_request_destroy(&request);
2423 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
2424 if (reqinfo == NULL)
2425 fatal("out of memory");
2426 reqinfo->msg = soaquery;
2427 reqinfo->addr = addr;
2428 dns_message_renderreset(soaquery);
2429 ddebug("retrying soa request without TSIG");
2431 if (isc_sockaddr_pf(addr) == AF_INET6)
2432 srcaddr = localaddr6;
2433 else
2434 srcaddr = localaddr4;
2436 result = dns_request_createvia3(requestmgr, soaquery, srcaddr,
2437 addr, 0, NULL,
2438 FIND_TIMEOUT * 20,
2439 FIND_TIMEOUT, 3,
2440 global_task, recvsoa, reqinfo,
2441 &request);
2442 check_result(result, "dns_request_createvia");
2443 requests++;
2444 return;
2446 check_result(result, "dns_request_getresponse");
2447 section = DNS_SECTION_ANSWER;
2448 POST(section);
2449 if (debugging)
2450 show_message(stderr, rcvmsg, "Reply from SOA query:");
2452 if (rcvmsg->rcode != dns_rcode_noerror &&
2453 rcvmsg->rcode != dns_rcode_nxdomain)
2454 fatal("response to SOA query was unsuccessful");
2456 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2457 char namebuf[DNS_NAME_FORMATSIZE];
2458 dns_name_format(userzone, namebuf, sizeof(namebuf));
2459 error("specified zone '%s' does not exist (NXDOMAIN)",
2460 namebuf);
2461 dns_message_destroy(&rcvmsg);
2462 dns_request_destroy(&request);
2463 dns_message_destroy(&soaquery);
2464 ddebug("Out of recvsoa");
2465 done_update();
2466 seenerror = ISC_TRUE;
2467 return;
2470 lookforsoa:
2471 if (pass == 0)
2472 section = DNS_SECTION_ANSWER;
2473 else if (pass == 1)
2474 section = DNS_SECTION_AUTHORITY;
2475 else
2476 goto droplabel;
2478 result = dns_message_firstname(rcvmsg, section);
2479 if (result != ISC_R_SUCCESS) {
2480 pass++;
2481 goto lookforsoa;
2483 while (result == ISC_R_SUCCESS) {
2484 name = NULL;
2485 dns_message_currentname(rcvmsg, section, &name);
2486 soaset = NULL;
2487 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2488 &soaset);
2489 if (result == ISC_R_SUCCESS)
2490 break;
2491 if (section == DNS_SECTION_ANSWER) {
2492 dns_rdataset_t *tset = NULL;
2493 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2494 &tset) == ISC_R_SUCCESS ||
2495 dns_message_findtype(name, dns_rdatatype_dname, 0,
2496 &tset) == ISC_R_SUCCESS ) {
2497 seencname = ISC_TRUE;
2498 break;
2502 result = dns_message_nextname(rcvmsg, section);
2505 if (soaset == NULL && !seencname) {
2506 pass++;
2507 goto lookforsoa;
2510 if (seencname)
2511 goto droplabel;
2513 if (debugging) {
2514 char namestr[DNS_NAME_FORMATSIZE];
2515 dns_name_format(name, namestr, sizeof(namestr));
2516 fprintf(stderr, "Found zone name: %s\n", namestr);
2519 result = dns_rdataset_first(soaset);
2520 check_result(result, "dns_rdataset_first");
2522 dns_rdata_init(&soarr);
2523 dns_rdataset_current(soaset, &soarr);
2524 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2525 check_result(result, "dns_rdata_tostruct");
2527 dns_name_init(&master, NULL);
2528 dns_name_clone(&soa.origin, &master);
2530 if (userzone != NULL)
2531 zname = userzone;
2532 else
2533 zname = name;
2535 if (debugging) {
2536 char namestr[DNS_NAME_FORMATSIZE];
2537 dns_name_format(&master, namestr, sizeof(namestr));
2538 fprintf(stderr, "The master is: %s\n", namestr);
2541 if (default_servers) {
2542 char serverstr[DNS_NAME_MAXTEXT+1];
2543 isc_buffer_t buf;
2544 size_t size;
2546 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2547 result = dns_name_totext(&master, ISC_TRUE, &buf);
2548 check_result(result, "dns_name_totext");
2549 serverstr[isc_buffer_usedlength(&buf)] = 0;
2551 if (master_servers != NULL && master_servers != servers)
2552 isc_mem_put(gmctx, master_servers,
2553 master_total * sizeof(isc_sockaddr_t));
2554 master_total = MAX_SERVERADDRS;
2555 size = master_total * sizeof(isc_sockaddr_t);
2556 master_servers = isc_mem_get(gmctx, size);
2557 if (master_servers == NULL)
2558 fatal("out of memory");
2560 memset(master_servers, 0, size);
2561 get_addresses(serverstr, dnsport, master_servers, master_total);
2562 master_inuse = 0;
2563 } else
2564 master_from_servers();
2565 dns_rdata_freestruct(&soa);
2567 #ifdef GSSAPI
2568 if (usegsstsig) {
2569 dns_name_init(&tmpzonename, NULL);
2570 dns_name_dup(zname, gmctx, &tmpzonename);
2571 dns_name_init(&restart_master, NULL);
2572 dns_name_dup(&master, gmctx, &restart_master);
2573 start_gssrequest(&master);
2574 } else {
2575 send_update(zname, &master_servers[master_inuse]);
2576 setzoneclass(dns_rdataclass_none);
2578 #else
2579 send_update(zname, &master_servers[master_inuse]);
2580 setzoneclass(dns_rdataclass_none);
2581 #endif
2583 dns_message_destroy(&soaquery);
2584 dns_request_destroy(&request);
2586 out:
2587 dns_message_destroy(&rcvmsg);
2588 ddebug("Out of recvsoa");
2589 return;
2591 droplabel:
2592 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2593 INSIST(result == ISC_R_SUCCESS);
2594 name = NULL;
2595 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2596 nlabels = dns_name_countlabels(name);
2597 if (nlabels == 1)
2598 fatal("could not find enclosing zone");
2599 dns_name_init(&tname, NULL);
2600 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2601 dns_name_clone(&tname, name);
2602 dns_request_destroy(&request);
2603 dns_message_renderreset(soaquery);
2604 dns_message_settsigkey(soaquery, NULL);
2605 sendrequest(&servers[ns_inuse], soaquery, &request);
2606 goto out;
2609 static void
2610 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
2611 dns_request_t **request)
2613 isc_result_t result;
2614 nsu_requestinfo_t *reqinfo;
2615 isc_sockaddr_t *srcaddr;
2617 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
2618 if (reqinfo == NULL)
2619 fatal("out of memory");
2620 reqinfo->msg = msg;
2621 reqinfo->addr = destaddr;
2623 if (isc_sockaddr_pf(destaddr) == AF_INET6)
2624 srcaddr = localaddr6;
2625 else
2626 srcaddr = localaddr4;
2628 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
2629 default_servers ? NULL : tsigkey,
2630 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2631 global_task, recvsoa, reqinfo, request);
2632 check_result(result, "dns_request_createvia");
2633 requests++;
2636 #ifdef GSSAPI
2639 * Get the realm from the users kerberos ticket if possible
2641 static void
2642 get_ticket_realm(isc_mem_t *mctx) {
2643 krb5_context ctx;
2644 krb5_error_code rc;
2645 krb5_ccache ccache;
2646 krb5_principal princ;
2647 char *name, *ticket_realm;
2649 rc = krb5_init_context(&ctx);
2650 if (rc != 0)
2651 return;
2653 rc = krb5_cc_default(ctx, &ccache);
2654 if (rc != 0) {
2655 krb5_free_context(ctx);
2656 return;
2659 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2660 if (rc != 0) {
2661 krb5_cc_close(ctx, ccache);
2662 krb5_free_context(ctx);
2663 return;
2666 rc = krb5_unparse_name(ctx, princ, &name);
2667 if (rc != 0) {
2668 krb5_free_principal(ctx, princ);
2669 krb5_cc_close(ctx, ccache);
2670 krb5_free_context(ctx);
2671 return;
2674 ticket_realm = strrchr(name, '@');
2675 if (ticket_realm != NULL) {
2676 realm = isc_mem_strdup(mctx, ticket_realm);
2679 free(name);
2680 krb5_free_principal(ctx, princ);
2681 krb5_cc_close(ctx, ccache);
2682 krb5_free_context(ctx);
2683 if (realm != NULL && debugging)
2684 fprintf(stderr, "Found realm from ticket: %s\n", realm+1);
2688 static void
2689 start_gssrequest(dns_name_t *master) {
2690 gss_ctx_id_t context;
2691 isc_buffer_t buf;
2692 isc_result_t result;
2693 isc_uint32_t val = 0;
2694 dns_message_t *rmsg;
2695 dns_request_t *request = NULL;
2696 dns_name_t *servname;
2697 dns_fixedname_t fname;
2698 char namestr[DNS_NAME_FORMATSIZE];
2699 char mykeystr[DNS_NAME_FORMATSIZE];
2700 char *err_message = NULL;
2702 debug("start_gssrequest");
2703 usevc = ISC_TRUE;
2705 if (gssring != NULL)
2706 dns_tsigkeyring_detach(&gssring);
2707 gssring = NULL;
2708 result = dns_tsigkeyring_create(gmctx, &gssring);
2710 if (result != ISC_R_SUCCESS)
2711 fatal("dns_tsigkeyring_create failed: %s",
2712 isc_result_totext(result));
2714 dns_name_format(master, namestr, sizeof(namestr));
2715 if (kserver == NULL) {
2716 kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
2717 if (kserver == NULL)
2718 fatal("out of memory");
2720 if (servers == NULL)
2721 get_addresses(namestr, dnsport, kserver, 1);
2722 else
2723 memmove(kserver, &servers[ns_inuse], sizeof(isc_sockaddr_t));
2725 dns_fixedname_init(&fname);
2726 servname = dns_fixedname_name(&fname);
2728 if (realm == NULL)
2729 get_ticket_realm(gmctx);
2731 result = isc_string_printf(servicename, sizeof(servicename),
2732 "DNS/%s%s", namestr, realm ? realm : "");
2733 if (result != ISC_R_SUCCESS)
2734 fatal("isc_string_printf(servicename) failed: %s",
2735 isc_result_totext(result));
2736 isc_buffer_init(&buf, servicename, strlen(servicename));
2737 isc_buffer_add(&buf, strlen(servicename));
2738 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2739 if (result != ISC_R_SUCCESS)
2740 fatal("dns_name_fromtext(servname) failed: %s",
2741 isc_result_totext(result));
2743 dns_fixedname_init(&fkname);
2744 keyname = dns_fixedname_name(&fkname);
2746 isc_random_get(&val);
2747 result = isc_string_printf(mykeystr, sizeof(mykeystr), "%u.sig-%s",
2748 val, namestr);
2749 if (result != ISC_R_SUCCESS)
2750 fatal("isc_string_printf(mykeystr) failed: %s",
2751 isc_result_totext(result));
2752 isc_buffer_init(&buf, mykeystr, strlen(mykeystr));
2753 isc_buffer_add(&buf, strlen(mykeystr));
2755 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
2756 if (result != ISC_R_SUCCESS)
2757 fatal("dns_name_fromtext(keyname) failed: %s",
2758 isc_result_totext(result));
2760 /* Windows doesn't recognize name compression in the key name. */
2761 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2763 rmsg = NULL;
2764 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
2765 if (result != ISC_R_SUCCESS)
2766 fatal("dns_message_create failed: %s",
2767 isc_result_totext(result));
2769 /* Build first request. */
2770 context = GSS_C_NO_CONTEXT;
2771 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
2772 &context, use_win2k_gsstsig,
2773 gmctx, &err_message);
2774 if (result == ISC_R_FAILURE)
2775 fatal("tkey query failed: %s",
2776 err_message != NULL ? err_message : "unknown error");
2777 if (result != ISC_R_SUCCESS)
2778 fatal("dns_tkey_buildgssquery failed: %s",
2779 isc_result_totext(result));
2781 send_gssrequest(kserver, rmsg, &request, context);
2784 static void
2785 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
2786 dns_request_t **request, gss_ctx_id_t context)
2788 isc_result_t result;
2789 nsu_gssinfo_t *reqinfo;
2790 unsigned int options = 0;
2791 isc_sockaddr_t *srcaddr;
2793 debug("send_gssrequest");
2794 reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
2795 if (reqinfo == NULL)
2796 fatal("out of memory");
2797 reqinfo->msg = msg;
2798 reqinfo->addr = destaddr;
2799 reqinfo->context = context;
2801 options |= DNS_REQUESTOPT_TCP;
2803 if (isc_sockaddr_pf(destaddr) == AF_INET6)
2804 srcaddr = localaddr6;
2805 else
2806 srcaddr = localaddr4;
2808 result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
2809 options, tsigkey, FIND_TIMEOUT * 20,
2810 FIND_TIMEOUT, 3, global_task, recvgss,
2811 reqinfo, request);
2812 check_result(result, "dns_request_createvia3");
2813 if (debugging)
2814 show_message(stdout, msg, "Outgoing update query:");
2815 requests++;
2818 static void
2819 recvgss(isc_task_t *task, isc_event_t *event) {
2820 dns_requestevent_t *reqev = NULL;
2821 dns_request_t *request = NULL;
2822 isc_result_t result, eresult;
2823 dns_message_t *rcvmsg = NULL;
2824 nsu_gssinfo_t *reqinfo;
2825 dns_message_t *tsigquery = NULL;
2826 isc_sockaddr_t *addr;
2827 gss_ctx_id_t context;
2828 isc_buffer_t buf;
2829 dns_name_t *servname;
2830 dns_fixedname_t fname;
2831 char *err_message = NULL;
2833 UNUSED(task);
2835 ddebug("recvgss()");
2837 requests--;
2839 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2840 reqev = (dns_requestevent_t *)event;
2841 request = reqev->request;
2842 eresult = reqev->result;
2843 reqinfo = reqev->ev_arg;
2844 tsigquery = reqinfo->msg;
2845 context = reqinfo->context;
2846 addr = reqinfo->addr;
2848 if (shuttingdown) {
2849 dns_request_destroy(&request);
2850 dns_message_destroy(&tsigquery);
2851 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
2852 isc_event_free(&event);
2853 maybeshutdown();
2854 return;
2857 if (eresult != ISC_R_SUCCESS) {
2858 next_server("recvgss", addr, eresult);
2859 ddebug("Destroying request [%p]", request);
2860 dns_request_destroy(&request);
2861 dns_message_renderreset(tsigquery);
2862 sendrequest(&servers[ns_inuse], tsigquery, &request);
2863 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
2864 isc_event_free(&event);
2865 return;
2867 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
2869 isc_event_free(&event);
2870 reqev = NULL;
2872 ddebug("recvgss creating rcvmsg");
2873 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2874 check_result(result, "dns_message_create");
2876 result = dns_request_getresponse(request, rcvmsg,
2877 DNS_MESSAGEPARSE_PRESERVEORDER);
2878 check_result(result, "dns_request_getresponse");
2880 if (debugging)
2881 show_message(stderr, rcvmsg,
2882 "recvmsg reply from GSS-TSIG query");
2884 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
2885 ddebug("recvgss trying %s GSS-TSIG",
2886 use_win2k_gsstsig ? "Standard" : "Win2k");
2887 if (use_win2k_gsstsig)
2888 use_win2k_gsstsig = ISC_FALSE;
2889 else
2890 use_win2k_gsstsig = ISC_TRUE;
2891 tried_other_gsstsig = ISC_TRUE;
2892 start_gssrequest(&restart_master);
2893 goto done;
2896 if (rcvmsg->rcode != dns_rcode_noerror &&
2897 rcvmsg->rcode != dns_rcode_nxdomain)
2898 fatal("response to GSS-TSIG query was unsuccessful");
2901 dns_fixedname_init(&fname);
2902 servname = dns_fixedname_name(&fname);
2903 isc_buffer_init(&buf, servicename, strlen(servicename));
2904 isc_buffer_add(&buf, strlen(servicename));
2905 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
2906 check_result(result, "dns_name_fromtext");
2908 tsigkey = NULL;
2909 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
2910 &context, &tsigkey, gssring,
2911 use_win2k_gsstsig,
2912 &err_message);
2913 switch (result) {
2915 case DNS_R_CONTINUE:
2916 send_gssrequest(kserver, tsigquery, &request, context);
2917 break;
2919 case ISC_R_SUCCESS:
2921 * XXXSRA Waaay too much fun here. There's no good
2922 * reason why we need a TSIG here (the people who put
2923 * it into the spec admitted at the time that it was
2924 * not a security issue), and Windows clients don't
2925 * seem to work if named complies with the spec and
2926 * includes the gratuitous TSIG. So we're in the
2927 * bizarre situation of having to choose between
2928 * complying with a useless requirement in the spec
2929 * and interoperating. This is nuts. If we can
2930 * confirm this behavior, we should ask the WG to
2931 * consider removing the requirement for the
2932 * gratuitous TSIG here. For the moment, we ignore
2933 * the TSIG -- this too is a spec violation, but it's
2934 * the least insane thing to do.
2936 #if 0
2938 * Verify the signature.
2940 rcvmsg->state = DNS_SECTION_ANY;
2941 dns_message_setquerytsig(rcvmsg, NULL);
2942 result = dns_message_settsigkey(rcvmsg, tsigkey);
2943 check_result(result, "dns_message_settsigkey");
2944 result = dns_message_checksig(rcvmsg, NULL);
2945 ddebug("tsig verification: %s", dns_result_totext(result));
2946 check_result(result, "dns_message_checksig");
2947 #endif /* 0 */
2949 send_update(&tmpzonename, &master_servers[master_inuse]);
2950 setzoneclass(dns_rdataclass_none);
2951 break;
2953 default:
2954 fatal("dns_tkey_negotiategss: %s %s",
2955 isc_result_totext(result),
2956 err_message != NULL ? err_message : "");
2959 done:
2960 dns_request_destroy(&request);
2961 dns_message_destroy(&tsigquery);
2963 dns_message_destroy(&rcvmsg);
2964 ddebug("Out of recvgss");
2966 #endif
2968 static void
2969 start_update(void) {
2970 isc_result_t result;
2971 dns_rdataset_t *rdataset = NULL;
2972 dns_name_t *name = NULL;
2973 dns_request_t *request = NULL;
2974 dns_message_t *soaquery = NULL;
2975 dns_name_t *firstname;
2976 dns_section_t section = DNS_SECTION_UPDATE;
2978 ddebug("start_update()");
2980 if (answer != NULL)
2981 dns_message_destroy(&answer);
2984 * If we have both the zone and the servers we have enough information
2985 * to send the update straight away otherwise we need to discover
2986 * the zone and / or the master server.
2988 if (userzone != NULL && !default_servers && !usegsstsig) {
2989 master_from_servers();
2990 send_update(userzone, &master_servers[master_inuse]);
2991 setzoneclass(dns_rdataclass_none);
2992 return;
2995 result = dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER,
2996 &soaquery);
2997 check_result(result, "dns_message_create");
2999 if (default_servers)
3000 soaquery->flags |= DNS_MESSAGEFLAG_RD;
3002 result = dns_message_gettempname(soaquery, &name);
3003 check_result(result, "dns_message_gettempname");
3005 result = dns_message_gettemprdataset(soaquery, &rdataset);
3006 check_result(result, "dns_message_gettemprdataset");
3008 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
3010 if (userzone != NULL) {
3011 dns_name_init(name, NULL);
3012 dns_name_clone(userzone, name);
3013 } else {
3014 dns_rdataset_t *tmprdataset;
3015 result = dns_message_firstname(updatemsg, section);
3016 if (result == ISC_R_NOMORE) {
3017 section = DNS_SECTION_PREREQUISITE;
3018 result = dns_message_firstname(updatemsg, section);
3020 if (result != ISC_R_SUCCESS) {
3021 dns_message_puttempname(soaquery, &name);
3022 dns_rdataset_disassociate(rdataset);
3023 dns_message_puttemprdataset(soaquery, &rdataset);
3024 dns_message_destroy(&soaquery);
3025 done_update();
3026 return;
3028 firstname = NULL;
3029 dns_message_currentname(updatemsg, section, &firstname);
3030 dns_name_init(name, NULL);
3031 dns_name_clone(firstname, name);
3033 * Looks to see if the first name references a DS record
3034 * and if that name is not the root remove a label as DS
3035 * records live in the parent zone so we need to start our
3036 * search one label up.
3038 tmprdataset = ISC_LIST_HEAD(firstname->list);
3039 if (section == DNS_SECTION_UPDATE &&
3040 !dns_name_equal(firstname, dns_rootname) &&
3041 tmprdataset->type == dns_rdatatype_ds) {
3042 unsigned int labels = dns_name_countlabels(name);
3043 dns_name_getlabelsequence(name, 1, labels - 1, name);
3047 ISC_LIST_INIT(name->list);
3048 ISC_LIST_APPEND(name->list, rdataset, link);
3049 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
3051 ns_inuse = 0;
3052 sendrequest(&servers[ns_inuse], soaquery, &request);
3055 static void
3056 cleanup(void) {
3057 ddebug("cleanup()");
3059 if (answer != NULL)
3060 dns_message_destroy(&answer);
3062 #ifdef GSSAPI
3063 if (tsigkey != NULL) {
3064 ddebug("detach tsigkey x%p", tsigkey);
3065 dns_tsigkey_detach(&tsigkey);
3067 if (gssring != NULL) {
3068 ddebug("Detaching GSS-TSIG keyring");
3069 dns_tsigkeyring_detach(&gssring);
3071 if (kserver != NULL) {
3072 isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
3073 kserver = NULL;
3075 if (realm != NULL) {
3076 isc_mem_free(gmctx, realm);
3077 realm = NULL;
3079 #endif
3081 if (sig0key != NULL)
3082 dst_key_free(&sig0key);
3084 ddebug("Shutting down task manager");
3085 isc_taskmgr_destroy(&taskmgr);
3087 ddebug("Destroying event");
3088 isc_event_free(&global_event);
3090 ddebug("Shutting down socket manager");
3091 isc_socketmgr_destroy(&socketmgr);
3093 ddebug("Shutting down timer manager");
3094 isc_timermgr_destroy(&timermgr);
3096 ddebug("Destroying hash context");
3097 isc_hash_destroy();
3099 ddebug("Destroying name state");
3100 dns_name_destroy();
3102 ddebug("Removing log context");
3103 isc_log_destroy(&glctx);
3105 ddebug("Destroying memory context");
3106 if (memdebugging)
3107 isc_mem_stats(gmctx, stderr);
3108 isc_mem_destroy(&gmctx);
3111 static void
3112 getinput(isc_task_t *task, isc_event_t *event) {
3113 isc_boolean_t more;
3115 UNUSED(task);
3117 if (shuttingdown) {
3118 maybeshutdown();
3119 return;
3122 if (global_event == NULL)
3123 global_event = event;
3125 reset_system();
3126 more = user_interaction();
3127 if (!more) {
3128 isc_app_shutdown();
3129 return;
3131 start_update();
3132 return;
3136 main(int argc, char **argv) {
3137 isc_result_t result;
3138 style = &dns_master_style_debug;
3140 input = stdin;
3142 interactive = ISC_TF(isatty(0));
3144 isc_app_start();
3146 pre_parse_args(argc, argv);
3148 result = isc_mem_create(0, 0, &gmctx);
3149 check_result(result, "isc_mem_create");
3151 parse_args(argc, argv, gmctx, &entropy);
3153 setup_system();
3155 result = isc_app_onrun(gmctx, global_task, getinput, NULL);
3156 check_result(result, "isc_app_onrun");
3158 (void)isc_app_run();
3160 cleanup();
3162 isc_app_finish();
3164 if (seenerror)
3165 return (2);
3166 else
3167 return (0);