1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <ctype.h>
17 #include <errno.h>
18 #include <inttypes.h>
19 #include <limits.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23
24 #include <isc/app.h>
25 #include <isc/base64.h>
26 #include <isc/buffer.h>
27 #include <isc/commandline.h>
28 #include <isc/event.h>
29 #include <isc/file.h>
30 #include <isc/hash.h>
31 #include <isc/lex.h>
32 #include <isc/log.h>
33 #include <isc/managers.h>
34 #include <isc/mem.h>
35 #include <isc/nonce.h>
36 #include <isc/parseint.h>
37 #include <isc/platform.h>
38 #include <isc/portset.h>
39 #include <isc/print.h>
40 #include <isc/random.h>
41 #include <isc/region.h>
42 #include <isc/sockaddr.h>
43 #include <isc/socket.h>
44 #include <isc/stdio.h>
45 #include <isc/string.h>
46 #include <isc/task.h>
47 #include <isc/timer.h>
48 #include <isc/types.h>
49 #include <isc/util.h>
50
51 #include <pk11/site.h>
52
53 #include <dns/callbacks.h>
54 #include <dns/dispatch.h>
55 #include <dns/dnssec.h>
56 #include <dns/events.h>
57 #include <dns/fixedname.h>
58 #include <dns/log.h>
59 #include <dns/masterdump.h>
60 #include <dns/message.h>
61 #include <dns/name.h>
62 #include <dns/nsec3.h>
63 #include <dns/rcode.h>
64 #include <dns/rdata.h>
65 #include <dns/rdataclass.h>
66 #include <dns/rdatalist.h>
67 #include <dns/rdataset.h>
68 #include <dns/rdatastruct.h>
69 #include <dns/rdatatype.h>
70 #include <dns/request.h>
71 #include <dns/result.h>
72 #include <dns/tkey.h>
73 #include <dns/tsig.h>
74
75 #include <dst/dst.h>
76
77 #include <isccfg/namedconf.h>
78
79 #include <irs/resconf.h>
80
81 #ifdef GSSAPI
82 #include <dst/gssapi.h>
83 #ifdef WIN32
84 #include <gssapi/gssapi.h>
85 #include <gssapi/gssapi_krb5.h>
86 #include <krb5/krb5.h>
87 #else /* ifdef WIN32 */
88 #include ISC_PLATFORM_GSSAPIHEADER
89 #ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER
90 #include ISC_PLATFORM_GSSAPI_KRB5_HEADER
91 #endif /* ifdef ISC_PLATFORM_GSSAPI_KRB5_HEADER */
92 #include ISC_PLATFORM_KRB5HEADER
93 #endif /* ifdef WIN32 */
94 #endif /* ifdef GSSAPI */
95 #include <bind9/getaddresses.h>
96
97 #if defined(HAVE_READLINE)
98 #if defined(HAVE_EDIT_READLINE_READLINE_H)
99 #include <edit/readline/readline.h>
100 #if defined(HAVE_EDIT_READLINE_HISTORY_H)
101 #include <edit/readline/history.h>
102 #endif /* if defined(HAVE_EDIT_READLINE_HISTORY_H) */
103 #elif defined(HAVE_EDITLINE_READLINE_H)
104 #include <editline/readline.h>
105 #else /* if defined(HAVE_EDIT_READLINE_READLINE_H) */
106 /* Prevent deprecated functions being declared. */
107 #define _FUNCTION_DEF 1
108 /* Ensure rl_message() gets prototype. */
109 #define USE_VARARGS 1
110 #define PREFER_STDARG 1
111 #include <readline/history.h>
112 #include <readline/readline.h>
113 #endif /* if defined(HAVE_EDIT_READLINE_READLINE_H) */
114 #endif /* if defined(HAVE_READLINE) */
115
116 #define MAXCMD (128 * 1024)
117 #define MAXWIRE (64 * 1024)
118 #define PACKETSIZE ((64 * 1024) - 1)
119 #define INITTEXT (2 * 1024)
120 #define MAXTEXT (128 * 1024)
121 #define FIND_TIMEOUT 5
122 #define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
123
124 #define DNSDEFAULTPORT 53
125
126 /* Number of addresses to request from bind9_getaddresses() */
127 #define MAX_SERVERADDRS 4
128
129 static uint16_t dnsport = DNSDEFAULTPORT;
130
131 #ifndef RESOLV_CONF
132 #define RESOLV_CONF "/etc/resolv.conf"
133 #endif /* ifndef RESOLV_CONF */
134
135 static bool debugging = false, ddebugging = false;
136 static bool memdebugging = false;
137 static bool have_ipv4 = false;
138 static bool have_ipv6 = false;
139 static bool is_dst_up = false;
140 static bool usevc = false;
141 static bool usegsstsig = false;
142 static bool use_win2k_gsstsig = false;
143 static bool tried_other_gsstsig = false;
144 static bool local_only = false;
145 static isc_nm_t *netmgr = NULL;
146 static isc_taskmgr_t *taskmgr = NULL;
147 static isc_task_t *global_task = NULL;
148 static isc_event_t *global_event = NULL;
149 static isc_log_t *glctx = NULL;
150 static isc_mem_t *gmctx = NULL;
151 static dns_dispatchmgr_t *dispatchmgr = NULL;
152 static dns_requestmgr_t *requestmgr = NULL;
153 static isc_socketmgr_t *socketmgr = NULL;
154 static isc_timermgr_t *timermgr = NULL;
155 static dns_dispatch_t *dispatchv4 = NULL;
156 static dns_dispatch_t *dispatchv6 = NULL;
157 static dns_message_t *updatemsg = NULL;
158 static dns_fixedname_t fuserzone;
159 static dns_fixedname_t fzname;
160 static dns_name_t *userzone = NULL;
161 static dns_name_t *zname = NULL;
162 static dns_name_t tmpzonename = DNS_NAME_INITEMPTY;
163 static dns_name_t restart_master = DNS_NAME_INITEMPTY;
164 static dns_tsig_keyring_t *gssring = NULL;
165 static dns_tsigkey_t *tsigkey = NULL;
166 static dst_key_t *sig0key = NULL;
167 static isc_sockaddr_t *servers = NULL;
168 static isc_sockaddr_t *master_servers = NULL;
169 static bool default_servers = true;
170 static int ns_inuse = 0;
171 static int master_inuse = 0;
172 static int ns_total = 0;
173 static int ns_alloc = 0;
174 static int master_total = 0;
175 static int master_alloc = 0;
176 static isc_sockaddr_t *localaddr4 = NULL;
177 static isc_sockaddr_t *localaddr6 = NULL;
178 static const char *keyfile = NULL;
179 static char *keystr = NULL;
180 static bool shuttingdown = false;
181 static FILE *input;
182 static bool interactive = true;
183 static bool seenerror = false;
184 static const dns_master_style_t *style;
185 static int requests = 0;
186 static unsigned int logdebuglevel = 0;
187 static unsigned int timeout = 300;
188 static unsigned int udp_timeout = 3;
189 static unsigned int udp_retries = 3;
190 static dns_rdataclass_t defaultclass = dns_rdataclass_in;
191 static dns_rdataclass_t zoneclass = dns_rdataclass_none;
192 static isc_mutex_t answer_lock;
193 static dns_message_t *answer = NULL;
194 static uint32_t default_ttl = 0;
195 static bool default_ttl_set = false;
196 static bool checknames = true;
197
198 typedef struct nsu_requestinfo {
199 dns_message_t *msg;
200 isc_sockaddr_t *addr;
201 } nsu_requestinfo_t;
202
203 static void
204 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
205 dns_request_t **request);
206 static void
207 send_update(dns_name_t *zonename, isc_sockaddr_t *master);
208
209 ISC_PLATFORM_NORETURN_PRE static void
210 fatal(const char *format, ...)
211 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
212
213 static void
214 debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
215
216 static void
217 ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
218
219 #ifdef GSSAPI
220 static dns_fixedname_t fkname;
221 static isc_sockaddr_t *kserver = NULL;
222 static char *realm = NULL;
223 static char servicename[DNS_NAME_FORMATSIZE];
224 static dns_name_t *keyname;
225 typedef struct nsu_gssinfo {
226 dns_message_t *msg;
227 isc_sockaddr_t *addr;
228 dns_gss_ctx_id_t context;
229 } nsu_gssinfo_t;
230
231 static void
232 failed_gssrequest();
233 static void
234 start_gssrequest(dns_name_t *master);
235 static void
236 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
237 dns_request_t **request, dns_gss_ctx_id_t context);
238 static void
239 recvgss(isc_task_t *task, isc_event_t *event);
240 #endif /* GSSAPI */
241
242 static void
243 error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
244
245 #define STATUS_MORE (uint16_t)0
246 #define STATUS_SEND (uint16_t)1
247 #define STATUS_QUIT (uint16_t)2
248 #define STATUS_SYNTAX (uint16_t)3
249
250 static void
master_from_servers(void)251 master_from_servers(void) {
252 if (master_servers != NULL && master_servers != servers) {
253 isc_mem_put(gmctx, master_servers,
254 master_alloc * sizeof(isc_sockaddr_t));
255 }
256 master_servers = servers;
257 master_total = ns_total;
258 master_alloc = ns_alloc;
259 master_inuse = ns_inuse;
260 }
261
262 static dns_rdataclass_t
getzoneclass(void)263 getzoneclass(void) {
264 if (zoneclass == dns_rdataclass_none) {
265 zoneclass = defaultclass;
266 }
267 return (zoneclass);
268 }
269
270 static bool
setzoneclass(dns_rdataclass_t rdclass)271 setzoneclass(dns_rdataclass_t rdclass) {
272 if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none)
273 {
274 zoneclass = rdclass;
275 }
276 if (zoneclass != rdclass) {
277 return (false);
278 }
279 return (true);
280 }
281
282 static void
fatal(const char * format,...)283 fatal(const char *format, ...) {
284 va_list args;
285
286 va_start(args, format);
287 vfprintf(stderr, format, args);
288 va_end(args);
289 fprintf(stderr, "\n");
290 exit(1);
291 }
292
293 static void
error(const char * format,...)294 error(const char *format, ...) {
295 va_list args;
296
297 va_start(args, format);
298 vfprintf(stderr, format, args);
299 va_end(args);
300 fprintf(stderr, "\n");
301 }
302
303 static void
debug(const char * format,...)304 debug(const char *format, ...) {
305 va_list args;
306
307 if (debugging) {
308 va_start(args, format);
309 vfprintf(stderr, format, args);
310 va_end(args);
311 fprintf(stderr, "\n");
312 }
313 }
314
315 static void
ddebug(const char * format,...)316 ddebug(const char *format, ...) {
317 va_list args;
318
319 if (ddebugging) {
320 va_start(args, format);
321 vfprintf(stderr, format, args);
322 va_end(args);
323 fprintf(stderr, "\n");
324 }
325 }
326
327 static inline void
check_result(isc_result_t result,const char * msg)328 check_result(isc_result_t result, const char *msg) {
329 if (result != ISC_R_SUCCESS) {
330 fatal("%s: %s", msg, isc_result_totext(result));
331 }
332 }
333
334 static char *
nsu_strsep(char ** stringp,const char * delim)335 nsu_strsep(char **stringp, const char *delim) {
336 char *string = *stringp;
337 *stringp = NULL;
338 char *s;
339 const char *d;
340 char sc, dc;
341
342 if (string == NULL) {
343 return (NULL);
344 }
345
346 for (; *string != '\0'; string++) {
347 sc = *string;
348 for (d = delim; (dc = *d) != '\0'; d++) {
349 if (sc == dc) {
350 break;
351 }
352 }
353 if (dc == 0) {
354 break;
355 }
356 }
357
358 for (s = string; *s != '\0'; s++) {
359 sc = *s;
360 for (d = delim; (dc = *d) != '\0'; d++) {
361 if (sc == dc) {
362 *s++ = '\0';
363 *stringp = s;
364 return (string);
365 }
366 }
367 }
368 return (string);
369 }
370
371 static void
reset_system(void)372 reset_system(void) {
373 ddebug("reset_system()");
374 /* If the update message is still around, destroy it */
375 if (updatemsg != NULL) {
376 dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
377 } else {
378 dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &updatemsg);
379 }
380 updatemsg->opcode = dns_opcode_update;
381 if (usegsstsig) {
382 if (tsigkey != NULL) {
383 dns_tsigkey_detach(&tsigkey);
384 }
385 if (gssring != NULL) {
386 dns_tsigkeyring_detach(&gssring);
387 }
388 tried_other_gsstsig = false;
389 }
390 }
391
392 static bool
parse_hmac(const dns_name_t ** hmac,const char * hmacstr,size_t len,uint16_t * digestbitsp)393 parse_hmac(const dns_name_t **hmac, const char *hmacstr, size_t len,
394 uint16_t *digestbitsp) {
395 uint16_t digestbits = 0;
396 isc_result_t result;
397 char buf[20];
398
399 REQUIRE(hmac != NULL && *hmac == NULL);
400 REQUIRE(hmacstr != NULL);
401
402 if (len >= sizeof(buf)) {
403 error("unknown key type '%.*s'", (int)(len), hmacstr);
404 return (false);
405 }
406
407 /* Copy len bytes and NUL terminate. */
408 strlcpy(buf, hmacstr, ISC_MIN(len + 1, sizeof(buf)));
409
410 if (strcasecmp(buf, "hmac-md5") == 0) {
411 *hmac = DNS_TSIG_HMACMD5_NAME;
412 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
413 *hmac = DNS_TSIG_HMACMD5_NAME;
414 result = isc_parse_uint16(&digestbits, &buf[9], 10);
415 if (result != ISC_R_SUCCESS || digestbits > 128) {
416 error("digest-bits out of range [0..128]");
417 return (false);
418 }
419 *digestbitsp = (digestbits + 7) & ~0x7U;
420 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
421 *hmac = DNS_TSIG_HMACSHA1_NAME;
422 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
423 *hmac = DNS_TSIG_HMACSHA1_NAME;
424 result = isc_parse_uint16(&digestbits, &buf[10], 10);
425 if (result != ISC_R_SUCCESS || digestbits > 160) {
426 error("digest-bits out of range [0..160]");
427 return (false);
428 }
429 *digestbitsp = (digestbits + 7) & ~0x7U;
430 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
431 *hmac = DNS_TSIG_HMACSHA224_NAME;
432 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
433 *hmac = DNS_TSIG_HMACSHA224_NAME;
434 result = isc_parse_uint16(&digestbits, &buf[12], 10);
435 if (result != ISC_R_SUCCESS || digestbits > 224) {
436 error("digest-bits out of range [0..224]");
437 return (false);
438 }
439 *digestbitsp = (digestbits + 7) & ~0x7U;
440 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
441 *hmac = DNS_TSIG_HMACSHA256_NAME;
442 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
443 *hmac = DNS_TSIG_HMACSHA256_NAME;
444 result = isc_parse_uint16(&digestbits, &buf[12], 10);
445 if (result != ISC_R_SUCCESS || digestbits > 256) {
446 error("digest-bits out of range [0..256]");
447 return (false);
448 }
449 *digestbitsp = (digestbits + 7) & ~0x7U;
450 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
451 *hmac = DNS_TSIG_HMACSHA384_NAME;
452 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
453 *hmac = DNS_TSIG_HMACSHA384_NAME;
454 result = isc_parse_uint16(&digestbits, &buf[12], 10);
455 if (result != ISC_R_SUCCESS || digestbits > 384) {
456 error("digest-bits out of range [0..384]");
457 return (false);
458 }
459 *digestbitsp = (digestbits + 7) & ~0x7U;
460 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
461 *hmac = DNS_TSIG_HMACSHA512_NAME;
462 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
463 *hmac = DNS_TSIG_HMACSHA512_NAME;
464 result = isc_parse_uint16(&digestbits, &buf[12], 10);
465 if (result != ISC_R_SUCCESS || digestbits > 512) {
466 error("digest-bits out of range [0..512]");
467 return (false);
468 }
469 *digestbitsp = (digestbits + 7) & ~0x7U;
470 } else {
471 error("unknown key type '%s'", buf);
472 return (false);
473 }
474 return (true);
475 }
476
477 static int
basenamelen(const char * file)478 basenamelen(const char *file) {
479 int len = strlen(file);
480
481 if (len > 1 && file[len - 1] == '.') {
482 len -= 1;
483 } else if (len > 8 && strcmp(file + len - 8, ".private") == 0) {
484 len -= 8;
485 } else if (len > 4 && strcmp(file + len - 4, ".key") == 0) {
486 len -= 4;
487 }
488 return (len);
489 }
490
491 static void
setup_keystr(void)492 setup_keystr(void) {
493 unsigned char *secret = NULL;
494 int secretlen;
495 isc_buffer_t secretbuf;
496 isc_result_t result;
497 isc_buffer_t keynamesrc;
498 char *secretstr;
499 char *s, *n;
500 dns_fixedname_t fkeyname;
501 dns_name_t *mykeyname;
502 char *name;
503 const dns_name_t *hmacname = NULL;
504 uint16_t digestbits = 0;
505
506 mykeyname = dns_fixedname_initname(&fkeyname);
507
508 debug("Creating key...");
509
510 s = strchr(keystr, ':');
511 if (s == NULL || s == keystr || s[1] == 0) {
512 fatal("key option must specify [hmac:]keyname:secret");
513 }
514 secretstr = s + 1;
515 n = strchr(secretstr, ':');
516 if (n != NULL) {
517 if (n == secretstr || n[1] == 0) {
518 fatal("key option must specify [hmac:]keyname:secret");
519 }
520 name = secretstr;
521 secretstr = n + 1;
522 if (!parse_hmac(&hmacname, keystr, s - keystr, &digestbits)) {
523 exit(1);
524 }
525 } else {
526 hmacname = DNS_TSIG_HMACMD5_NAME;
527 name = keystr;
528 n = s;
529 }
530
531 isc_buffer_init(&keynamesrc, name, (unsigned int)(n - name));
532 isc_buffer_add(&keynamesrc, (unsigned int)(n - name));
533
534 debug("namefromtext");
535 result = dns_name_fromtext(mykeyname, &keynamesrc, dns_rootname, 0,
536 NULL);
537 check_result(result, "dns_name_fromtext");
538
539 secretlen = strlen(secretstr) * 3 / 4;
540 secret = isc_mem_allocate(gmctx, secretlen);
541
542 isc_buffer_init(&secretbuf, secret, secretlen);
543 result = isc_base64_decodestring(secretstr, &secretbuf);
544 if (result != ISC_R_SUCCESS) {
545 fprintf(stderr, "could not create key from %s: %s\n", keystr,
546 isc_result_totext(result));
547 goto failure;
548 }
549
550 secretlen = isc_buffer_usedlength(&secretbuf);
551
552 debug("keycreate");
553 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
554 false, NULL, 0, 0, gmctx, NULL, &tsigkey);
555 if (result != ISC_R_SUCCESS) {
556 fprintf(stderr, "could not create key from %s: %s\n", keystr,
557 dns_result_totext(result));
558 } else {
559 dst_key_setbits(tsigkey->key, digestbits);
560 }
561 failure:
562 if (secret != NULL) {
563 isc_mem_free(gmctx, secret);
564 }
565 }
566
567 /*
568 * Get a key from a named.conf format keyfile
569 */
570 static isc_result_t
read_sessionkey(isc_mem_t * mctx,isc_log_t * lctx)571 read_sessionkey(isc_mem_t *mctx, isc_log_t *lctx) {
572 cfg_parser_t *pctx = NULL;
573 cfg_obj_t *sessionkey = NULL;
574 const cfg_obj_t *key = NULL;
575 const cfg_obj_t *secretobj = NULL;
576 const cfg_obj_t *algorithmobj = NULL;
577 const char *mykeyname;
578 const char *secretstr;
579 const char *algorithm;
580 isc_result_t result;
581 int len;
582
583 if (!isc_file_exists(keyfile)) {
584 return (ISC_R_FILENOTFOUND);
585 }
586
587 result = cfg_parser_create(mctx, lctx, &pctx);
588 if (result != ISC_R_SUCCESS) {
589 goto cleanup;
590 }
591
592 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
593 &sessionkey);
594 if (result != ISC_R_SUCCESS) {
595 goto cleanup;
596 }
597
598 result = cfg_map_get(sessionkey, "key", &key);
599 if (result != ISC_R_SUCCESS) {
600 goto cleanup;
601 }
602
603 (void)cfg_map_get(key, "secret", &secretobj);
604 (void)cfg_map_get(key, "algorithm", &algorithmobj);
605 if (secretobj == NULL || algorithmobj == NULL) {
606 fatal("key must have algorithm and secret");
607 }
608
609 mykeyname = cfg_obj_asstring(cfg_map_getname(key));
610 secretstr = cfg_obj_asstring(secretobj);
611 algorithm = cfg_obj_asstring(algorithmobj);
612
613 len = strlen(algorithm) + strlen(mykeyname) + strlen(secretstr) + 3;
614 keystr = isc_mem_allocate(mctx, len);
615 snprintf(keystr, len, "%s:%s:%s", algorithm, mykeyname, secretstr);
616 setup_keystr();
617
618 cleanup:
619 if (pctx != NULL) {
620 if (sessionkey != NULL) {
621 cfg_obj_destroy(pctx, &sessionkey);
622 }
623 cfg_parser_destroy(&pctx);
624 }
625
626 if (keystr != NULL) {
627 isc_mem_free(mctx, keystr);
628 }
629
630 return (result);
631 }
632
633 static void
setup_keyfile(isc_mem_t * mctx,isc_log_t * lctx)634 setup_keyfile(isc_mem_t *mctx, isc_log_t *lctx) {
635 dst_key_t *dstkey = NULL;
636 isc_result_t result;
637 const dns_name_t *hmacname = NULL;
638
639 debug("Creating key...");
640
641 if (sig0key != NULL) {
642 dst_key_free(&sig0key);
643 }
644
645 /* Try reading the key from a K* pair */
646 result = dst_key_fromnamedfile(
647 keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey);
648
649 /* If that didn't work, try reading it as a session.key keyfile */
650 if (result != ISC_R_SUCCESS) {
651 result = read_sessionkey(mctx, lctx);
652 if (result == ISC_R_SUCCESS) {
653 return;
654 }
655 }
656
657 if (result != ISC_R_SUCCESS) {
658 fprintf(stderr,
659 "could not read key from %.*s.{private,key}: "
660 "%s\n",
661 basenamelen(keyfile), keyfile,
662 isc_result_totext(result));
663 return;
664 }
665
666 switch (dst_key_alg(dstkey)) {
667 case DST_ALG_HMACMD5:
668 hmacname = DNS_TSIG_HMACMD5_NAME;
669 break;
670 case DST_ALG_HMACSHA1:
671 hmacname = DNS_TSIG_HMACSHA1_NAME;
672 break;
673 case DST_ALG_HMACSHA224:
674 hmacname = DNS_TSIG_HMACSHA224_NAME;
675 break;
676 case DST_ALG_HMACSHA256:
677 hmacname = DNS_TSIG_HMACSHA256_NAME;
678 break;
679 case DST_ALG_HMACSHA384:
680 hmacname = DNS_TSIG_HMACSHA384_NAME;
681 break;
682 case DST_ALG_HMACSHA512:
683 hmacname = DNS_TSIG_HMACSHA512_NAME;
684 break;
685 }
686 if (hmacname != NULL) {
687 result = dns_tsigkey_createfromkey(
688 dst_key_name(dstkey), hmacname, dstkey, false, NULL, 0,
689 0, mctx, NULL, &tsigkey);
690 dst_key_free(&dstkey);
691 if (result != ISC_R_SUCCESS) {
692 fprintf(stderr, "could not create key from %s: %s\n",
693 keyfile, isc_result_totext(result));
694 return;
695 }
696 } else {
697 dst_key_attach(dstkey, &sig0key);
698 dst_key_free(&dstkey);
699 }
700 }
701
702 static void
doshutdown(void)703 doshutdown(void) {
704 isc_task_detach(&global_task);
705
706 /*
707 * The isc_mem_put of master_servers must be before the
708 * isc_mem_put of servers as it sets the servers pointer
709 * to NULL.
710 */
711 if (master_servers != NULL && master_servers != servers) {
712 isc_mem_put(gmctx, master_servers,
713 master_alloc * sizeof(isc_sockaddr_t));
714 }
715
716 if (servers != NULL) {
717 isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
718 }
719
720 if (localaddr4 != NULL) {
721 isc_mem_put(gmctx, localaddr4, sizeof(isc_sockaddr_t));
722 }
723
724 if (localaddr6 != NULL) {
725 isc_mem_put(gmctx, localaddr6, sizeof(isc_sockaddr_t));
726 }
727
728 if (tsigkey != NULL) {
729 ddebug("Freeing TSIG key");
730 dns_tsigkey_detach(&tsigkey);
731 }
732
733 if (sig0key != NULL) {
734 ddebug("Freeing SIG(0) key");
735 dst_key_free(&sig0key);
736 }
737
738 if (updatemsg != NULL) {
739 dns_message_detach(&updatemsg);
740 }
741
742 if (is_dst_up) {
743 ddebug("Destroy DST lib");
744 dst_lib_destroy();
745 is_dst_up = false;
746 }
747
748 ddebug("Destroying request manager");
749 dns_requestmgr_detach(&requestmgr);
750
751 ddebug("Freeing the dispatchers");
752 if (have_ipv4) {
753 dns_dispatch_detach(&dispatchv4);
754 }
755 if (have_ipv6) {
756 dns_dispatch_detach(&dispatchv6);
757 }
758
759 ddebug("Shutting down dispatch manager");
760 dns_dispatchmgr_destroy(&dispatchmgr);
761 }
762
763 static void
maybeshutdown(void)764 maybeshutdown(void) {
765 /* when called from getinput, doshutdown might be already finished */
766 if (requestmgr == NULL)
767 return;
768
769 ddebug("Shutting down request manager");
770 dns_requestmgr_shutdown(requestmgr);
771
772 if (requests != 0) {
773 return;
774 }
775
776 doshutdown();
777 }
778
779 static void
shutdown_program(isc_task_t * task,isc_event_t * event)780 shutdown_program(isc_task_t *task, isc_event_t *event) {
781 REQUIRE(task == global_task);
782 UNUSED(task);
783
784 ddebug("shutdown_program()");
785 isc_event_free(&event);
786
787 shuttingdown = true;
788 maybeshutdown();
789 }
790
791 /*
792 * Try honoring the operating system's preferred ephemeral port range.
793 */
794 static void
set_source_ports(dns_dispatchmgr_t * manager)795 set_source_ports(dns_dispatchmgr_t *manager) {
796 isc_portset_t *v4portset = NULL, *v6portset = NULL;
797 in_port_t udpport_low, udpport_high;
798 isc_result_t result;
799
800 result = isc_portset_create(gmctx, &v4portset);
801 check_result(result, "isc_portset_create (v4)");
802 result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
803 check_result(result, "isc_net_getudpportrange (v4)");
804 isc_portset_addrange(v4portset, udpport_low, udpport_high);
805
806 result = isc_portset_create(gmctx, &v6portset);
807 check_result(result, "isc_portset_create (v6)");
808 result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
809 check_result(result, "isc_net_getudpportrange (v6)");
810 isc_portset_addrange(v6portset, udpport_low, udpport_high);
811
812 result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
813 check_result(result, "dns_dispatchmgr_setavailports");
814
815 isc_portset_destroy(gmctx, &v4portset);
816 isc_portset_destroy(gmctx, &v6portset);
817 }
818
819 static void
setup_system(void)820 setup_system(void) {
821 isc_result_t result;
822 isc_sockaddr_t bind_any, bind_any6;
823 unsigned int attrs, attrmask;
824 isc_sockaddrlist_t *nslist;
825 isc_logconfig_t *logconfig = NULL;
826 irs_resconf_t *resconf = NULL;
827
828 ddebug("setup_system()");
829
830 dns_result_register();
831
832 isc_log_create(gmctx, &glctx, &logconfig);
833 isc_log_setcontext(glctx);
834 dns_log_init(glctx);
835 dns_log_setcontext(glctx);
836
837 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
838 check_result(result, "isc_log_usechannel");
839
840 isc_log_setdebuglevel(glctx, logdebuglevel);
841
842 result = irs_resconf_load(gmctx, RESOLV_CONF, &resconf);
843 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
844 fatal("parse of %s failed", RESOLV_CONF);
845 }
846
847 nslist = irs_resconf_getnameservers(resconf);
848
849 if (servers != NULL) {
850 if (master_servers == servers) {
851 master_servers = NULL;
852 }
853 isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
854 }
855
856 ns_inuse = 0;
857 if (local_only || ISC_LIST_EMPTY(*nslist)) {
858 struct in_addr in;
859 struct in6_addr in6;
860
861 if (local_only && keyfile == NULL) {
862 keyfile = SESSION_KEYFILE;
863 }
864
865 default_servers = !local_only;
866
867 ns_total = ns_alloc = (have_ipv4 ? 1 : 0) + (have_ipv6 ? 1 : 0);
868 servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
869
870 if (have_ipv6) {
871 memset(&in6, 0, sizeof(in6));
872 in6.s6_addr[15] = 1;
873 isc_sockaddr_fromin6(&servers[0], &in6, dnsport);
874 }
875 if (have_ipv4) {
876 in.s_addr = htonl(INADDR_LOOPBACK);
877 isc_sockaddr_fromin(&servers[(have_ipv6 ? 1 : 0)], &in,
878 dnsport);
879 }
880 } else {
881 isc_sockaddr_t *sa;
882 int i;
883
884 /*
885 * Count the nameservers (skipping any that we can't use
886 * because of address family restrictions) and allocate
887 * the servers array.
888 */
889 ns_total = 0;
890 for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
891 sa = ISC_LIST_NEXT(sa, link)) {
892 switch (sa->type.sa.sa_family) {
893 case AF_INET:
894 if (have_ipv4) {
895 ns_total++;
896 }
897 break;
898 case AF_INET6:
899 if (have_ipv6) {
900 ns_total++;
901 }
902 break;
903 default:
904 fatal("bad family");
905 }
906 }
907
908 ns_alloc = ns_total;
909 servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
910
911 i = 0;
912 for (sa = ISC_LIST_HEAD(*nslist); sa != NULL;
913 sa = ISC_LIST_NEXT(sa, link)) {
914 switch (sa->type.sa.sa_family) {
915 case AF_INET:
916 if (have_ipv4) {
917 sa->type.sin.sin_port = htons(dnsport);
918 } else {
919 continue;
920 }
921 break;
922 case AF_INET6:
923 if (have_ipv6) {
924 sa->type.sin6.sin6_port =
925 htons(dnsport);
926 } else {
927 continue;
928 }
929 break;
930 default:
931 fatal("bad family");
932 }
933 INSIST(i < ns_alloc);
934 servers[i++] = *sa;
935 }
936 }
937
938 irs_resconf_destroy(&resconf);
939
940 result = dns_dispatchmgr_create(gmctx, &dispatchmgr);
941 check_result(result, "dns_dispatchmgr_create");
942
943 result = isc_socketmgr_create(gmctx, &socketmgr);
944 check_result(result, "dns_socketmgr_create");
945
946 result = isc_timermgr_create(gmctx, &timermgr);
947 check_result(result, "dns_timermgr_create");
948
949 result = isc_managers_create(gmctx, 1, 0, &netmgr, &taskmgr);
950 check_result(result, "isc_managers_create");
951
952 result = isc_task_create(taskmgr, 0, &global_task);
953 check_result(result, "isc_task_create");
954
955 result = isc_task_onshutdown(global_task, shutdown_program, NULL);
956 check_result(result, "isc_task_onshutdown");
957
958 result = dst_lib_init(gmctx, NULL);
959 check_result(result, "dst_lib_init");
960 is_dst_up = true;
961
962 set_source_ports(dispatchmgr);
963
964 attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
965 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
966
967 if (have_ipv6) {
968 attrs = DNS_DISPATCHATTR_UDP;
969 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
970 attrs |= DNS_DISPATCHATTR_IPV6;
971 isc_sockaddr_any6(&bind_any6);
972 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
973 &bind_any6, PACKETSIZE, 4, 2, 3, 5,
974 attrs, attrmask, &dispatchv6);
975 check_result(result, "dns_dispatch_getudp (v6)");
976 }
977
978 if (have_ipv4) {
979 attrs = DNS_DISPATCHATTR_UDP;
980 attrs |= DNS_DISPATCHATTR_MAKEQUERY;
981 attrs |= DNS_DISPATCHATTR_IPV4;
982 isc_sockaddr_any(&bind_any);
983 result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
984 &bind_any, PACKETSIZE, 4, 2, 3, 5,
985 attrs, attrmask, &dispatchv4);
986 check_result(result, "dns_dispatch_getudp (v4)");
987 }
988
989 result = dns_requestmgr_create(gmctx, timermgr, socketmgr, taskmgr,
990 dispatchmgr, dispatchv4, dispatchv6,
991 &requestmgr);
992 check_result(result, "dns_requestmgr_create");
993
994 if (keystr != NULL) {
995 setup_keystr();
996 } else if (local_only) {
997 result = read_sessionkey(gmctx, glctx);
998 if (result != ISC_R_SUCCESS) {
999 fatal("can't read key from %s: %s\n", keyfile,
1000 isc_result_totext(result));
1001 }
1002 } else if (keyfile != NULL) {
1003 setup_keyfile(gmctx, glctx);
1004 }
1005
1006 isc_mutex_init(&answer_lock);
1007 }
1008
1009 static int
get_addresses(char * host,in_port_t port,isc_sockaddr_t * sockaddr,int naddrs)1010 get_addresses(char *host, in_port_t port, isc_sockaddr_t *sockaddr,
1011 int naddrs) {
1012 int count = 0;
1013 isc_result_t result;
1014
1015 isc_app_block();
1016 result = bind9_getaddresses(host, port, sockaddr, naddrs, &count);
1017 isc_app_unblock();
1018 if (result != ISC_R_SUCCESS) {
1019 error("couldn't get address for '%s': %s", host,
1020 isc_result_totext(result));
1021 }
1022 return (count);
1023 }
1024
1025 static void
version(void)1026 version(void) {
1027 fputs("nsupdate " VERSION "\n", stderr);
1028 }
1029
1030 #define PARSE_ARGS_FMT "46dDML:y:ghilovk:p:Pr:R::t:Tu:V"
1031
1032 static void
pre_parse_args(int argc,char ** argv)1033 pre_parse_args(int argc, char **argv) {
1034 dns_rdatatype_t t;
1035 int ch;
1036 char buf[100];
1037 bool doexit = false;
1038 bool ipv4only = false, ipv6only = false;
1039
1040 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1041 switch (ch) {
1042 case 'M': /* was -dm */
1043 debugging = true;
1044 ddebugging = true;
1045 memdebugging = true;
1046 isc_mem_debugging = ISC_MEM_DEBUGTRACE |
1047 ISC_MEM_DEBUGRECORD;
1048 break;
1049
1050 case '4':
1051 if (ipv6only) {
1052 fatal("only one of -4 and -6 allowed");
1053 }
1054 ipv4only = true;
1055 break;
1056
1057 case '6':
1058 if (ipv4only) {
1059 fatal("only one of -4 and -6 allowed");
1060 }
1061 ipv6only = true;
1062 break;
1063
1064 case '?':
1065 case 'h':
1066 if (isc_commandline_option != '?') {
1067 fprintf(stderr, "%s: invalid argument -%c\n",
1068 argv[0], isc_commandline_option);
1069 }
1070 fprintf(stderr, "usage: nsupdate [-dDi] [-L level] [-l]"
1071 "[-g | -o | -y keyname:secret | -k "
1072 "keyfile] "
1073 "[-v] [-V] [-P] [-T] [-4 | -6] "
1074 "[filename]\n");
1075 exit(1);
1076
1077 case 'P':
1078 for (t = 0xff00; t <= 0xfffe; t++) {
1079 if (dns_rdatatype_ismeta(t)) {
1080 continue;
1081 }
1082 dns_rdatatype_format(t, buf, sizeof(buf));
1083 if (strncmp(buf, "TYPE", 4) != 0) {
1084 fprintf(stdout, "%s\n", buf);
1085 }
1086 }
1087 doexit = true;
1088 break;
1089
1090 case 'T':
1091 for (t = 1; t <= 0xfeff; t++) {
1092 if (dns_rdatatype_ismeta(t)) {
1093 continue;
1094 }
1095 dns_rdatatype_format(t, buf, sizeof(buf));
1096 if (strncmp(buf, "TYPE", 4) != 0) {
1097 fprintf(stdout, "%s\n", buf);
1098 }
1099 }
1100 doexit = true;
1101 break;
1102
1103 case 'V':
1104 version();
1105 doexit = true;
1106 break;
1107
1108 default:
1109 break;
1110 }
1111 }
1112 if (doexit) {
1113 exit(0);
1114 }
1115 isc_commandline_reset = true;
1116 isc_commandline_index = 1;
1117 }
1118
1119 static void
parse_args(int argc,char ** argv)1120 parse_args(int argc, char **argv) {
1121 int ch;
1122 uint32_t i;
1123 isc_result_t result;
1124 bool force_interactive = false;
1125
1126 debug("parse_args");
1127 while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
1128 switch (ch) {
1129 case '4':
1130 if (have_ipv4) {
1131 isc_net_disableipv6();
1132 have_ipv6 = false;
1133 } else {
1134 fatal("can't find IPv4 networking");
1135 }
1136 break;
1137 case '6':
1138 if (have_ipv6) {
1139 isc_net_disableipv4();
1140 have_ipv4 = false;
1141 } else {
1142 fatal("can't find IPv6 networking");
1143 }
1144 break;
1145 case 'd':
1146 debugging = true;
1147 break;
1148 case 'D': /* was -dd */
1149 debugging = true;
1150 ddebugging = true;
1151 break;
1152 case 'M':
1153 break;
1154 case 'i':
1155 force_interactive = true;
1156 interactive = true;
1157 break;
1158 case 'l':
1159 local_only = true;
1160 break;
1161 case 'L':
1162 result = isc_parse_uint32(&i, isc_commandline_argument,
1163 10);
1164 if (result != ISC_R_SUCCESS) {
1165 fprintf(stderr,
1166 "bad library debug value "
1167 "'%s'\n",
1168 isc_commandline_argument);
1169 exit(1);
1170 }
1171 logdebuglevel = i;
1172 break;
1173 case 'y':
1174 keystr = isc_commandline_argument;
1175 break;
1176 case 'v':
1177 usevc = true;
1178 break;
1179 case 'k':
1180 keyfile = isc_commandline_argument;
1181 break;
1182 case 'g':
1183 usegsstsig = true;
1184 use_win2k_gsstsig = false;
1185 break;
1186 case 'o':
1187 usegsstsig = true;
1188 use_win2k_gsstsig = true;
1189 break;
1190 case 'p':
1191 result = isc_parse_uint16(&dnsport,
1192 isc_commandline_argument, 10);
1193 if (result != ISC_R_SUCCESS) {
1194 fprintf(stderr,
1195 "bad port number "
1196 "'%s'\n",
1197 isc_commandline_argument);
1198 exit(1);
1199 }
1200 break;
1201 case 't':
1202 result = isc_parse_uint32(&timeout,
1203 isc_commandline_argument, 10);
1204 if (result != ISC_R_SUCCESS) {
1205 fprintf(stderr, "bad timeout '%s'\n",
1206 isc_commandline_argument);
1207 exit(1);
1208 }
1209 if (timeout == 0) {
1210 timeout = UINT_MAX;
1211 }
1212 break;
1213 case 'u':
1214 result = isc_parse_uint32(&udp_timeout,
1215 isc_commandline_argument, 10);
1216 if (result != ISC_R_SUCCESS) {
1217 fprintf(stderr, "bad udp timeout '%s'\n",
1218 isc_commandline_argument);
1219 exit(1);
1220 }
1221 if (udp_timeout == 0) {
1222 udp_timeout = UINT_MAX;
1223 }
1224 break;
1225 case 'r':
1226 result = isc_parse_uint32(&udp_retries,
1227 isc_commandline_argument, 10);
1228 if (result != ISC_R_SUCCESS) {
1229 fprintf(stderr, "bad udp retries '%s'\n",
1230 isc_commandline_argument);
1231 exit(1);
1232 }
1233 break;
1234
1235 case 'R':
1236 fatal("The -R options has been deprecated.\n");
1237 break;
1238
1239 default:
1240 fprintf(stderr, "%s: unhandled option: %c\n", argv[0],
1241 isc_commandline_option);
1242 exit(1);
1243 }
1244 }
1245 if (keyfile != NULL && keystr != NULL) {
1246 fprintf(stderr, "%s: cannot specify both -k and -y\n", argv[0]);
1247 exit(1);
1248 }
1249
1250 #ifdef GSSAPI
1251 if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
1252 fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
1253 argv[0]);
1254 exit(1);
1255 }
1256 #else /* ifdef GSSAPI */
1257 if (usegsstsig) {
1258 fprintf(stderr,
1259 "%s: cannot specify -g or -o, "
1260 "program not linked with GSS API Library\n",
1261 argv[0]);
1262 exit(1);
1263 }
1264 #endif /* ifdef GSSAPI */
1265
1266 if (argv[isc_commandline_index] != NULL) {
1267 if (strcmp(argv[isc_commandline_index], "-") == 0) {
1268 input = stdin;
1269 } else {
1270 result = isc_stdio_open(argv[isc_commandline_index],
1271 "r", &input);
1272 if (result != ISC_R_SUCCESS) {
1273 fprintf(stderr, "could not open '%s': %s\n",
1274 argv[isc_commandline_index],
1275 isc_result_totext(result));
1276 exit(1);
1277 }
1278 }
1279 if (!force_interactive) {
1280 interactive = false;
1281 }
1282 }
1283 }
1284
1285 static uint16_t
parse_name(char ** cmdlinep,dns_message_t * msg,dns_name_t ** namep)1286 parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
1287 isc_result_t result;
1288 char *word;
1289 isc_buffer_t source;
1290
1291 word = nsu_strsep(cmdlinep, " \t\r\n");
1292 if (word == NULL || *word == 0) {
1293 fprintf(stderr, "could not read owner name\n");
1294 return (STATUS_SYNTAX);
1295 }
1296
1297 result = dns_message_gettempname(msg, namep);
1298 check_result(result, "dns_message_gettempname");
1299 isc_buffer_init(&source, word, strlen(word));
1300 isc_buffer_add(&source, strlen(word));
1301 result = dns_name_fromtext(*namep, &source, dns_rootname, 0, NULL);
1302 if (result != ISC_R_SUCCESS) {
1303 error("invalid owner name: %s", isc_result_totext(result));
1304 isc_buffer_invalidate(&source);
1305 dns_message_puttempname(msg, namep);
1306 return (STATUS_SYNTAX);
1307 }
1308 isc_buffer_invalidate(&source);
1309 return (STATUS_MORE);
1310 }
1311
1312 static uint16_t
parse_rdata(char ** cmdlinep,dns_rdataclass_t rdataclass,dns_rdatatype_t rdatatype,dns_message_t * msg,dns_rdata_t * rdata)1313 parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
1314 dns_rdatatype_t rdatatype, dns_message_t *msg, dns_rdata_t *rdata) {
1315 char *cmdline = *cmdlinep;
1316 isc_buffer_t source, *buf = NULL, *newbuf = NULL;
1317 isc_region_t r;
1318 isc_lex_t *lex = NULL;
1319 dns_rdatacallbacks_t callbacks;
1320 isc_result_t result;
1321
1322 if (cmdline == NULL) {
1323 rdata->flags = DNS_RDATA_UPDATE;
1324 return (STATUS_MORE);
1325 }
1326
1327 while (*cmdline != 0 && isspace((unsigned char)*cmdline)) {
1328 cmdline++;
1329 }
1330
1331 if (*cmdline != 0) {
1332 dns_rdatacallbacks_init(&callbacks);
1333 result = isc_lex_create(gmctx, strlen(cmdline), &lex);
1334 check_result(result, "isc_lex_create");
1335 isc_buffer_init(&source, cmdline, strlen(cmdline));
1336 isc_buffer_add(&source, strlen(cmdline));
1337 result = isc_lex_openbuffer(lex, &source);
1338 check_result(result, "isc_lex_openbuffer");
1339 isc_buffer_allocate(gmctx, &buf, MAXWIRE);
1340 result = dns_rdata_fromtext(NULL, rdataclass, rdatatype, lex,
1341 dns_rootname, 0, gmctx, buf,
1342 &callbacks);
1343 isc_lex_destroy(&lex);
1344 if (result == ISC_R_SUCCESS) {
1345 isc_buffer_usedregion(buf, &r);
1346 isc_buffer_allocate(gmctx, &newbuf, r.length);
1347 isc_buffer_putmem(newbuf, r.base, r.length);
1348 isc_buffer_usedregion(newbuf, &r);
1349 dns_rdata_fromregion(rdata, rdataclass, rdatatype, &r);
1350 isc_buffer_free(&buf);
1351 dns_message_takebuffer(msg, &newbuf);
1352 } else {
1353 fprintf(stderr, "invalid rdata format: %s\n",
1354 isc_result_totext(result));
1355 isc_buffer_free(&buf);
1356 return (STATUS_SYNTAX);
1357 }
1358 } else {
1359 rdata->flags = DNS_RDATA_UPDATE;
1360 }
1361 *cmdlinep = cmdline;
1362 return (STATUS_MORE);
1363 }
1364
1365 static uint16_t
make_prereq(char * cmdline,bool ispositive,bool isrrset)1366 make_prereq(char *cmdline, bool ispositive, bool isrrset) {
1367 isc_result_t result;
1368 char *word;
1369 dns_name_t *name = NULL;
1370 isc_textregion_t region;
1371 dns_rdataset_t *rdataset = NULL;
1372 dns_rdatalist_t *rdatalist = NULL;
1373 dns_rdataclass_t rdataclass;
1374 dns_rdatatype_t rdatatype;
1375 dns_rdata_t *rdata = NULL;
1376 uint16_t retval;
1377
1378 ddebug("make_prereq()");
1379
1380 /*
1381 * Read the owner name
1382 */
1383 retval = parse_name(&cmdline, updatemsg, &name);
1384 if (retval != STATUS_MORE) {
1385 return (retval);
1386 }
1387
1388 /*
1389 * If this is an rrset prereq, read the class or type.
1390 */
1391 if (isrrset) {
1392 word = nsu_strsep(&cmdline, " \t\r\n");
1393 if (word == NULL || *word == 0) {
1394 fprintf(stderr, "could not read class or type\n");
1395 goto failure;
1396 }
1397 region.base = word;
1398 region.length = strlen(word);
1399 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1400 if (result == ISC_R_SUCCESS) {
1401 if (!setzoneclass(rdataclass)) {
1402 fprintf(stderr, "class mismatch: %s\n", word);
1403 goto failure;
1404 }
1405 /*
1406 * Now read the type.
1407 */
1408 word = nsu_strsep(&cmdline, " \t\r\n");
1409 if (word == NULL || *word == 0) {
1410 fprintf(stderr, "could not read type\n");
1411 goto failure;
1412 }
1413 region.base = word;
1414 region.length = strlen(word);
1415 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1416 if (result != ISC_R_SUCCESS) {
1417 fprintf(stderr, "invalid type: %s\n", word);
1418 goto failure;
1419 }
1420 } else {
1421 rdataclass = getzoneclass();
1422 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1423 if (result != ISC_R_SUCCESS) {
1424 fprintf(stderr, "invalid type: %s\n", word);
1425 goto failure;
1426 }
1427 }
1428 } else {
1429 rdatatype = dns_rdatatype_any;
1430 }
1431
1432 result = dns_message_gettemprdata(updatemsg, &rdata);
1433 check_result(result, "dns_message_gettemprdata");
1434
1435 dns_rdata_init(rdata);
1436
1437 if (isrrset && ispositive) {
1438 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
1439 rdata);
1440 if (retval != STATUS_MORE) {
1441 goto failure;
1442 }
1443 } else {
1444 rdata->flags = DNS_RDATA_UPDATE;
1445 }
1446
1447 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1448 check_result(result, "dns_message_gettemprdatalist");
1449 result = dns_message_gettemprdataset(updatemsg, &rdataset);
1450 check_result(result, "dns_message_gettemprdataset");
1451 rdatalist->type = rdatatype;
1452 if (ispositive) {
1453 if (isrrset && rdata->data != NULL) {
1454 rdatalist->rdclass = rdataclass;
1455 } else {
1456 rdatalist->rdclass = dns_rdataclass_any;
1457 }
1458 } else {
1459 rdatalist->rdclass = dns_rdataclass_none;
1460 }
1461 rdata->rdclass = rdatalist->rdclass;
1462 rdata->type = rdatatype;
1463 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1464 dns_rdatalist_tordataset(rdatalist, rdataset);
1465 ISC_LIST_INIT(name->list);
1466 ISC_LIST_APPEND(name->list, rdataset, link);
1467 dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
1468 return (STATUS_MORE);
1469
1470 failure:
1471 if (name != NULL) {
1472 dns_message_puttempname(updatemsg, &name);
1473 }
1474 return (STATUS_SYNTAX);
1475 }
1476
1477 static uint16_t
evaluate_prereq(char * cmdline)1478 evaluate_prereq(char *cmdline) {
1479 char *word;
1480 bool ispositive, isrrset;
1481
1482 ddebug("evaluate_prereq()");
1483 word = nsu_strsep(&cmdline, " \t\r\n");
1484 if (word == NULL || *word == 0) {
1485 fprintf(stderr, "could not read operation code\n");
1486 return (STATUS_SYNTAX);
1487 }
1488 if (strcasecmp(word, "nxdomain") == 0) {
1489 ispositive = false;
1490 isrrset = false;
1491 } else if (strcasecmp(word, "yxdomain") == 0) {
1492 ispositive = true;
1493 isrrset = false;
1494 } else if (strcasecmp(word, "nxrrset") == 0) {
1495 ispositive = false;
1496 isrrset = true;
1497 } else if (strcasecmp(word, "yxrrset") == 0) {
1498 ispositive = true;
1499 isrrset = true;
1500 } else {
1501 fprintf(stderr, "incorrect operation code: %s\n", word);
1502 return (STATUS_SYNTAX);
1503 }
1504 return (make_prereq(cmdline, ispositive, isrrset));
1505 }
1506
1507 static uint16_t
evaluate_server(char * cmdline)1508 evaluate_server(char *cmdline) {
1509 char *word, *server;
1510 long port;
1511
1512 if (local_only) {
1513 fprintf(stderr, "cannot reset server in localhost-only mode\n");
1514 return (STATUS_SYNTAX);
1515 }
1516
1517 word = nsu_strsep(&cmdline, " \t\r\n");
1518 if (word == NULL || *word == 0) {
1519 fprintf(stderr, "could not read server name\n");
1520 return (STATUS_SYNTAX);
1521 }
1522 server = word;
1523
1524 word = nsu_strsep(&cmdline, " \t\r\n");
1525 if (word == NULL || *word == 0) {
1526 port = dnsport;
1527 } else {
1528 char *endp;
1529 port = strtol(word, &endp, 10);
1530 if (*endp != 0) {
1531 fprintf(stderr, "port '%s' is not numeric\n", word);
1532 return (STATUS_SYNTAX);
1533 } else if (port < 1 || port > 65535) {
1534 fprintf(stderr,
1535 "port '%s' is out of range "
1536 "(1 to 65535)\n",
1537 word);
1538 return (STATUS_SYNTAX);
1539 }
1540 }
1541
1542 if (servers != NULL) {
1543 if (master_servers == servers) {
1544 master_servers = NULL;
1545 }
1546 isc_mem_put(gmctx, servers, ns_alloc * sizeof(isc_sockaddr_t));
1547 }
1548
1549 default_servers = false;
1550
1551 ns_alloc = MAX_SERVERADDRS;
1552 ns_inuse = 0;
1553 servers = isc_mem_get(gmctx, ns_alloc * sizeof(isc_sockaddr_t));
1554
1555 memset(servers, 0, ns_alloc * sizeof(isc_sockaddr_t));
1556 ns_total = get_addresses(server, (in_port_t)port, servers, ns_alloc);
1557 if (ns_total == 0) {
1558 return (STATUS_SYNTAX);
1559 }
1560
1561 return (STATUS_MORE);
1562 }
1563
1564 static uint16_t
evaluate_local(char * cmdline)1565 evaluate_local(char *cmdline) {
1566 char *word, *local;
1567 long port;
1568 struct in_addr in4;
1569 struct in6_addr in6;
1570
1571 word = nsu_strsep(&cmdline, " \t\r\n");
1572 if (word == NULL || *word == 0) {
1573 fprintf(stderr, "could not read server name\n");
1574 return (STATUS_SYNTAX);
1575 }
1576 local = word;
1577
1578 word = nsu_strsep(&cmdline, " \t\r\n");
1579 if (word == NULL || *word == 0) {
1580 port = 0;
1581 } else {
1582 char *endp;
1583 port = strtol(word, &endp, 10);
1584 if (*endp != 0) {
1585 fprintf(stderr, "port '%s' is not numeric\n", word);
1586 return (STATUS_SYNTAX);
1587 } else if (port < 1 || port > 65535) {
1588 fprintf(stderr,
1589 "port '%s' is out of range "
1590 "(1 to 65535)\n",
1591 word);
1592 return (STATUS_SYNTAX);
1593 }
1594 }
1595
1596 if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1) {
1597 if (localaddr6 == NULL) {
1598 localaddr6 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1599 }
1600 isc_sockaddr_fromin6(localaddr6, &in6, (in_port_t)port);
1601 } else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1) {
1602 if (localaddr4 == NULL) {
1603 localaddr4 = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
1604 }
1605 isc_sockaddr_fromin(localaddr4, &in4, (in_port_t)port);
1606 } else {
1607 fprintf(stderr, "invalid address %s", local);
1608 return (STATUS_SYNTAX);
1609 }
1610
1611 return (STATUS_MORE);
1612 }
1613
1614 static uint16_t
evaluate_key(char * cmdline)1615 evaluate_key(char *cmdline) {
1616 char *namestr;
1617 char *secretstr;
1618 isc_buffer_t b;
1619 isc_result_t result;
1620 dns_fixedname_t fkeyname;
1621 dns_name_t *mykeyname;
1622 int secretlen;
1623 unsigned char *secret = NULL;
1624 isc_buffer_t secretbuf;
1625 const dns_name_t *hmacname = NULL;
1626 uint16_t digestbits = 0;
1627 char *n;
1628
1629 namestr = nsu_strsep(&cmdline, " \t\r\n");
1630 if (namestr == NULL || *namestr == 0) {
1631 fprintf(stderr, "could not read key name\n");
1632 return (STATUS_SYNTAX);
1633 }
1634
1635 mykeyname = dns_fixedname_initname(&fkeyname);
1636
1637 n = strchr(namestr, ':');
1638 if (n != NULL) {
1639 if (!parse_hmac(&hmacname, namestr, n - namestr, &digestbits)) {
1640 return (STATUS_SYNTAX);
1641 }
1642 namestr = n + 1;
1643 } else {
1644 hmacname = DNS_TSIG_HMACMD5_NAME;
1645 }
1646
1647 isc_buffer_init(&b, namestr, strlen(namestr));
1648 isc_buffer_add(&b, strlen(namestr));
1649 result = dns_name_fromtext(mykeyname, &b, dns_rootname, 0, NULL);
1650 if (result != ISC_R_SUCCESS) {
1651 fprintf(stderr, "could not parse key name\n");
1652 return (STATUS_SYNTAX);
1653 }
1654
1655 secretstr = nsu_strsep(&cmdline, "\r\n");
1656 if (secretstr == NULL || *secretstr == 0) {
1657 fprintf(stderr, "could not read key secret\n");
1658 return (STATUS_SYNTAX);
1659 }
1660 secretlen = strlen(secretstr) * 3 / 4;
1661 secret = isc_mem_allocate(gmctx, secretlen);
1662
1663 isc_buffer_init(&secretbuf, secret, secretlen);
1664 result = isc_base64_decodestring(secretstr, &secretbuf);
1665 if (result != ISC_R_SUCCESS) {
1666 fprintf(stderr, "could not create key from %s: %s\n", secretstr,
1667 isc_result_totext(result));
1668 isc_mem_free(gmctx, secret);
1669 return (STATUS_SYNTAX);
1670 }
1671 secretlen = isc_buffer_usedlength(&secretbuf);
1672
1673 if (tsigkey != NULL) {
1674 dns_tsigkey_detach(&tsigkey);
1675 }
1676 result = dns_tsigkey_create(mykeyname, hmacname, secret, secretlen,
1677 false, NULL, 0, 0, gmctx, NULL, &tsigkey);
1678 isc_mem_free(gmctx, secret);
1679 if (result != ISC_R_SUCCESS) {
1680 fprintf(stderr, "could not create key from %s %s: %s\n",
1681 namestr, secretstr, dns_result_totext(result));
1682 return (STATUS_SYNTAX);
1683 }
1684 dst_key_setbits(tsigkey->key, digestbits);
1685 return (STATUS_MORE);
1686 }
1687
1688 static uint16_t
evaluate_zone(char * cmdline)1689 evaluate_zone(char *cmdline) {
1690 char *word;
1691 isc_buffer_t b;
1692 isc_result_t result;
1693
1694 word = nsu_strsep(&cmdline, " \t\r\n");
1695 if (word == NULL || *word == 0) {
1696 fprintf(stderr, "could not read zone name\n");
1697 return (STATUS_SYNTAX);
1698 }
1699
1700 userzone = dns_fixedname_initname(&fuserzone);
1701 isc_buffer_init(&b, word, strlen(word));
1702 isc_buffer_add(&b, strlen(word));
1703 result = dns_name_fromtext(userzone, &b, dns_rootname, 0, NULL);
1704 if (result != ISC_R_SUCCESS) {
1705 userzone = NULL; /* Lest it point to an invalid name */
1706 fprintf(stderr, "could not parse zone name\n");
1707 return (STATUS_SYNTAX);
1708 }
1709
1710 return (STATUS_MORE);
1711 }
1712
1713 static uint16_t
evaluate_realm(char * cmdline)1714 evaluate_realm(char *cmdline) {
1715 #ifdef GSSAPI
1716 char *word;
1717 char buf[1024];
1718 int n;
1719
1720 if (realm != NULL) {
1721 isc_mem_free(gmctx, realm);
1722 realm = NULL;
1723 }
1724
1725 word = nsu_strsep(&cmdline, " \t\r\n");
1726 if (word == NULL || *word == 0) {
1727 return (STATUS_MORE);
1728 }
1729
1730 n = snprintf(buf, sizeof(buf), "@%s", word);
1731 if (n < 0 || (size_t)n >= sizeof(buf)) {
1732 error("realm is too long");
1733 return (STATUS_SYNTAX);
1734 }
1735 realm = isc_mem_strdup(gmctx, buf);
1736 return (STATUS_MORE);
1737 #else /* ifdef GSSAPI */
1738 UNUSED(cmdline);
1739 return (STATUS_SYNTAX);
1740 #endif /* ifdef GSSAPI */
1741 }
1742
1743 static uint16_t
evaluate_ttl(char * cmdline)1744 evaluate_ttl(char *cmdline) {
1745 char *word;
1746 isc_result_t result;
1747 uint32_t ttl;
1748
1749 word = nsu_strsep(&cmdline, " \t\r\n");
1750 if (word == NULL || *word == 0) {
1751 fprintf(stderr, "could not read ttl\n");
1752 return (STATUS_SYNTAX);
1753 }
1754
1755 if (!strcasecmp(word, "none")) {
1756 default_ttl = 0;
1757 default_ttl_set = false;
1758 return (STATUS_MORE);
1759 }
1760
1761 result = isc_parse_uint32(&ttl, word, 10);
1762 if (result != ISC_R_SUCCESS) {
1763 return (STATUS_SYNTAX);
1764 }
1765
1766 if (ttl > TTL_MAX) {
1767 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
1768 TTL_MAX);
1769 return (STATUS_SYNTAX);
1770 }
1771 default_ttl = ttl;
1772 default_ttl_set = true;
1773
1774 return (STATUS_MORE);
1775 }
1776
1777 static uint16_t
evaluate_class(char * cmdline)1778 evaluate_class(char *cmdline) {
1779 char *word;
1780 isc_textregion_t r;
1781 isc_result_t result;
1782 dns_rdataclass_t rdclass;
1783
1784 word = nsu_strsep(&cmdline, " \t\r\n");
1785 if (word == NULL || *word == 0) {
1786 fprintf(stderr, "could not read class name\n");
1787 return (STATUS_SYNTAX);
1788 }
1789
1790 r.base = word;
1791 r.length = strlen(word);
1792 result = dns_rdataclass_fromtext(&rdclass, &r);
1793 if (result != ISC_R_SUCCESS) {
1794 fprintf(stderr, "could not parse class name: %s\n", word);
1795 return (STATUS_SYNTAX);
1796 }
1797 switch (rdclass) {
1798 case dns_rdataclass_none:
1799 case dns_rdataclass_any:
1800 case dns_rdataclass_reserved0:
1801 fprintf(stderr, "bad default class: %s\n", word);
1802 return (STATUS_SYNTAX);
1803 default:
1804 defaultclass = rdclass;
1805 }
1806
1807 return (STATUS_MORE);
1808 }
1809
1810 static uint16_t
update_addordelete(char * cmdline,bool isdelete)1811 update_addordelete(char *cmdline, bool isdelete) {
1812 isc_result_t result;
1813 dns_name_t *name = NULL;
1814 uint32_t ttl;
1815 char *word;
1816 dns_rdataclass_t rdataclass;
1817 dns_rdatatype_t rdatatype;
1818 dns_rdata_t *rdata = NULL;
1819 dns_rdatalist_t *rdatalist = NULL;
1820 dns_rdataset_t *rdataset = NULL;
1821 isc_textregion_t region;
1822 uint16_t retval;
1823
1824 ddebug("update_addordelete()");
1825
1826 /*
1827 * Read the owner name.
1828 */
1829 retval = parse_name(&cmdline, updatemsg, &name);
1830 if (retval != STATUS_MORE) {
1831 return (retval);
1832 }
1833
1834 result = dns_message_gettemprdata(updatemsg, &rdata);
1835 check_result(result, "dns_message_gettemprdata");
1836
1837 dns_rdata_init(rdata);
1838
1839 /*
1840 * If this is an add, read the TTL and verify that it's in range.
1841 * If it's a delete, ignore a TTL if present (for compatibility).
1842 */
1843 word = nsu_strsep(&cmdline, " \t\r\n");
1844 if (word == NULL || *word == 0) {
1845 if (!isdelete) {
1846 fprintf(stderr, "could not read owner ttl\n");
1847 goto failure;
1848 } else {
1849 ttl = 0;
1850 rdataclass = dns_rdataclass_any;
1851 rdatatype = dns_rdatatype_any;
1852 rdata->flags = DNS_RDATA_UPDATE;
1853 goto doneparsing;
1854 }
1855 }
1856 result = isc_parse_uint32(&ttl, word, 10);
1857 if (result != ISC_R_SUCCESS) {
1858 if (isdelete) {
1859 ttl = 0;
1860 goto parseclass;
1861 } else if (default_ttl_set) {
1862 ttl = default_ttl;
1863 goto parseclass;
1864 } else {
1865 fprintf(stderr, "ttl '%s': %s\n", word,
1866 isc_result_totext(result));
1867 goto failure;
1868 }
1869 }
1870
1871 if (isdelete) {
1872 ttl = 0;
1873 } else if (ttl > TTL_MAX) {
1874 fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n", word,
1875 TTL_MAX);
1876 goto failure;
1877 }
1878
1879 /*
1880 * Read the class or type.
1881 */
1882 word = nsu_strsep(&cmdline, " \t\r\n");
1883 parseclass:
1884 if (word == NULL || *word == 0) {
1885 if (isdelete) {
1886 rdataclass = dns_rdataclass_any;
1887 rdatatype = dns_rdatatype_any;
1888 rdata->flags = DNS_RDATA_UPDATE;
1889 goto doneparsing;
1890 } else {
1891 fprintf(stderr, "could not read class or type\n");
1892 goto failure;
1893 }
1894 }
1895 region.base = word;
1896 region.length = strlen(word);
1897 rdataclass = dns_rdataclass_any;
1898 result = dns_rdataclass_fromtext(&rdataclass, ®ion);
1899 if (result == ISC_R_SUCCESS && rdataclass != dns_rdataclass_any) {
1900 if (!setzoneclass(rdataclass)) {
1901 fprintf(stderr, "class mismatch: %s\n", word);
1902 goto failure;
1903 }
1904 /*
1905 * Now read the type.
1906 */
1907 word = nsu_strsep(&cmdline, " \t\r\n");
1908 if (word == NULL || *word == 0) {
1909 if (isdelete) {
1910 rdataclass = dns_rdataclass_any;
1911 rdatatype = dns_rdatatype_any;
1912 rdata->flags = DNS_RDATA_UPDATE;
1913 goto doneparsing;
1914 } else {
1915 fprintf(stderr, "could not read type\n");
1916 goto failure;
1917 }
1918 }
1919 region.base = word;
1920 region.length = strlen(word);
1921 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1922 if (result != ISC_R_SUCCESS) {
1923 fprintf(stderr, "'%s' is not a valid type: %s\n", word,
1924 isc_result_totext(result));
1925 goto failure;
1926 }
1927 } else {
1928 rdataclass = getzoneclass();
1929 result = dns_rdatatype_fromtext(&rdatatype, ®ion);
1930 if (result != ISC_R_SUCCESS) {
1931 fprintf(stderr,
1932 "'%s' is not a valid class or type: "
1933 "%s\n",
1934 word, isc_result_totext(result));
1935 goto failure;
1936 }
1937 }
1938
1939 retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg, rdata);
1940 if (retval != STATUS_MORE) {
1941 goto failure;
1942 }
1943
1944 if (isdelete) {
1945 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1946 rdataclass = dns_rdataclass_any;
1947 } else {
1948 rdataclass = dns_rdataclass_none;
1949 }
1950 } else {
1951 if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
1952 fprintf(stderr, "could not read rdata\n");
1953 goto failure;
1954 }
1955 }
1956
1957 if (!isdelete && checknames) {
1958 dns_fixedname_t fixed;
1959 dns_name_t *bad;
1960
1961 if (!dns_rdata_checkowner(name, rdata->rdclass, rdata->type,
1962 true)) {
1963 char namebuf[DNS_NAME_FORMATSIZE];
1964
1965 dns_name_format(name, namebuf, sizeof(namebuf));
1966 fprintf(stderr, "check-names failed: bad owner '%s'\n",
1967 namebuf);
1968 goto failure;
1969 }
1970
1971 bad = dns_fixedname_initname(&fixed);
1972 if (!dns_rdata_checknames(rdata, name, bad)) {
1973 char namebuf[DNS_NAME_FORMATSIZE];
1974
1975 dns_name_format(bad, namebuf, sizeof(namebuf));
1976 fprintf(stderr, "check-names failed: bad name '%s'\n",
1977 namebuf);
1978 goto failure;
1979 }
1980 }
1981
1982 if (!isdelete && rdata->type == dns_rdatatype_nsec3param) {
1983 dns_rdata_nsec3param_t nsec3param;
1984
1985 result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
1986 check_result(result, "dns_rdata_tostruct");
1987 if (nsec3param.iterations > dns_nsec3_maxiterations()) {
1988 fprintf(stderr,
1989 "NSEC3PARAM has excessive iterations (> %u)\n",
1990 dns_nsec3_maxiterations());
1991 goto failure;
1992 }
1993 }
1994
1995 doneparsing:
1996
1997 result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
1998 check_result(result, "dns_message_gettemprdatalist");
1999 result = dns_message_gettemprdataset(updatemsg, &rdataset);
2000 check_result(result, "dns_message_gettemprdataset");
2001 rdatalist->type = rdatatype;
2002 rdatalist->rdclass = rdataclass;
2003 rdatalist->covers = rdatatype;
2004 rdatalist->ttl = (dns_ttl_t)ttl;
2005 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2006 dns_rdatalist_tordataset(rdatalist, rdataset);
2007 ISC_LIST_INIT(name->list);
2008 ISC_LIST_APPEND(name->list, rdataset, link);
2009 dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
2010 return (STATUS_MORE);
2011
2012 failure:
2013 if (name != NULL) {
2014 dns_message_puttempname(updatemsg, &name);
2015 }
2016 dns_message_puttemprdata(updatemsg, &rdata);
2017 return (STATUS_SYNTAX);
2018 }
2019
2020 static uint16_t
evaluate_update(char * cmdline)2021 evaluate_update(char *cmdline) {
2022 char *word;
2023 bool isdelete;
2024
2025 ddebug("evaluate_update()");
2026 word = nsu_strsep(&cmdline, " \t\r\n");
2027 if (word == NULL || *word == 0) {
2028 fprintf(stderr, "could not read operation code\n");
2029 return (STATUS_SYNTAX);
2030 }
2031 if (strcasecmp(word, "delete") == 0) {
2032 isdelete = true;
2033 } else if (strcasecmp(word, "del") == 0) {
2034 isdelete = true;
2035 } else if (strcasecmp(word, "add") == 0) {
2036 isdelete = false;
2037 } else {
2038 fprintf(stderr, "incorrect operation code: %s\n", word);
2039 return (STATUS_SYNTAX);
2040 }
2041 return (update_addordelete(cmdline, isdelete));
2042 }
2043
2044 static uint16_t
evaluate_checknames(char * cmdline)2045 evaluate_checknames(char *cmdline) {
2046 char *word;
2047
2048 ddebug("evaluate_checknames()");
2049 word = nsu_strsep(&cmdline, " \t\r\n");
2050 if (word == NULL || *word == 0) {
2051 fprintf(stderr, "could not read check-names directive\n");
2052 return (STATUS_SYNTAX);
2053 }
2054 if (strcasecmp(word, "yes") == 0 || strcasecmp(word, "true") == 0 ||
2055 strcasecmp(word, "on") == 0)
2056 {
2057 checknames = true;
2058 } else if (strcasecmp(word, "no") == 0 ||
2059 strcasecmp(word, "false") == 0 ||
2060 strcasecmp(word, "off") == 0)
2061 {
2062 checknames = false;
2063 } else {
2064 fprintf(stderr, "incorrect check-names directive: %s\n", word);
2065 return (STATUS_SYNTAX);
2066 }
2067 return (STATUS_MORE);
2068 }
2069
2070 static void
setzone(dns_name_t * zonename)2071 setzone(dns_name_t *zonename) {
2072 isc_result_t result;
2073 dns_name_t *name = NULL;
2074 dns_rdataset_t *rdataset = NULL;
2075
2076 result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
2077 if (result == ISC_R_SUCCESS) {
2078 dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
2079 dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
2080 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
2081 rdataset = ISC_LIST_HEAD(name->list))
2082 {
2083 ISC_LIST_UNLINK(name->list, rdataset, link);
2084 dns_rdataset_disassociate(rdataset);
2085 dns_message_puttemprdataset(updatemsg, &rdataset);
2086 }
2087 dns_message_puttempname(updatemsg, &name);
2088 }
2089
2090 if (zonename != NULL) {
2091 result = dns_message_gettempname(updatemsg, &name);
2092 check_result(result, "dns_message_gettempname");
2093 dns_name_clone(zonename, name);
2094 result = dns_message_gettemprdataset(updatemsg, &rdataset);
2095 check_result(result, "dns_message_gettemprdataset");
2096 dns_rdataset_makequestion(rdataset, getzoneclass(),
2097 dns_rdatatype_soa);
2098 ISC_LIST_INIT(name->list);
2099 ISC_LIST_APPEND(name->list, rdataset, link);
2100 dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
2101 }
2102 }
2103
2104 static void
show_message(FILE * stream,dns_message_t * msg,const char * description)2105 show_message(FILE *stream, dns_message_t *msg, const char *description) {
2106 isc_result_t result;
2107 isc_buffer_t *buf = NULL;
2108 int bufsz;
2109
2110 ddebug("show_message()");
2111
2112 setzone(userzone);
2113
2114 bufsz = INITTEXT;
2115 do {
2116 if (bufsz > MAXTEXT) {
2117 fprintf(stderr, "could not allocate large enough "
2118 "buffer to display message\n");
2119 exit(1);
2120 }
2121 if (buf != NULL) {
2122 isc_buffer_free(&buf);
2123 }
2124 isc_buffer_allocate(gmctx, &buf, bufsz);
2125 result = dns_message_totext(msg, style, 0, buf);
2126 bufsz *= 2;
2127 } while (result == ISC_R_NOSPACE);
2128 if (result != ISC_R_SUCCESS) {
2129 fprintf(stderr, "could not convert message to text format.\n");
2130 isc_buffer_free(&buf);
2131 return;
2132 }
2133 fprintf(stream, "%s\n%.*s", description,
2134 (int)isc_buffer_usedlength(buf), (char *)isc_buffer_base(buf));
2135 fflush(stream);
2136 isc_buffer_free(&buf);
2137 }
2138
2139 static uint16_t
do_next_command(char * cmdline)2140 do_next_command(char *cmdline) {
2141 char *word;
2142
2143 ddebug("do_next_command()");
2144 word = nsu_strsep(&cmdline, " \t\r\n");
2145
2146 if (word == NULL || *word == 0) {
2147 return (STATUS_SEND);
2148 }
2149 if (word[0] == ';') {
2150 return (STATUS_MORE);
2151 }
2152 if (strcasecmp(word, "quit") == 0) {
2153 return (STATUS_QUIT);
2154 }
2155 if (strcasecmp(word, "prereq") == 0) {
2156 return (evaluate_prereq(cmdline));
2157 }
2158 if (strcasecmp(word, "nxdomain") == 0) {
2159 return (make_prereq(cmdline, false, false));
2160 }
2161 if (strcasecmp(word, "yxdomain") == 0) {
2162 return (make_prereq(cmdline, true, false));
2163 }
2164 if (strcasecmp(word, "nxrrset") == 0) {
2165 return (make_prereq(cmdline, false, true));
2166 }
2167 if (strcasecmp(word, "yxrrset") == 0) {
2168 return (make_prereq(cmdline, true, true));
2169 }
2170 if (strcasecmp(word, "update") == 0) {
2171 return (evaluate_update(cmdline));
2172 }
2173 if (strcasecmp(word, "delete") == 0) {
2174 return (update_addordelete(cmdline, true));
2175 }
2176 if (strcasecmp(word, "del") == 0) {
2177 return (update_addordelete(cmdline, true));
2178 }
2179 if (strcasecmp(word, "add") == 0) {
2180 return (update_addordelete(cmdline, false));
2181 }
2182 if (strcasecmp(word, "server") == 0) {
2183 return (evaluate_server(cmdline));
2184 }
2185 if (strcasecmp(word, "local") == 0) {
2186 return (evaluate_local(cmdline));
2187 }
2188 if (strcasecmp(word, "zone") == 0) {
2189 return (evaluate_zone(cmdline));
2190 }
2191 if (strcasecmp(word, "class") == 0) {
2192 return (evaluate_class(cmdline));
2193 }
2194 if (strcasecmp(word, "send") == 0) {
2195 return (STATUS_SEND);
2196 }
2197 if (strcasecmp(word, "debug") == 0) {
2198 if (debugging) {
2199 ddebugging = true;
2200 } else {
2201 debugging = true;
2202 }
2203 return (STATUS_MORE);
2204 }
2205 if (strcasecmp(word, "ttl") == 0) {
2206 return (evaluate_ttl(cmdline));
2207 }
2208 if (strcasecmp(word, "show") == 0) {
2209 show_message(stdout, updatemsg, "Outgoing update query:");
2210 return (STATUS_MORE);
2211 }
2212 if (strcasecmp(word, "answer") == 0) {
2213 LOCK(&answer_lock);
2214 if (answer != NULL) {
2215 show_message(stdout, answer, "Answer:");
2216 }
2217 UNLOCK(&answer_lock);
2218 return (STATUS_MORE);
2219 }
2220 if (strcasecmp(word, "key") == 0) {
2221 usegsstsig = false;
2222 return (evaluate_key(cmdline));
2223 }
2224 if (strcasecmp(word, "realm") == 0) {
2225 return (evaluate_realm(cmdline));
2226 }
2227 if (strcasecmp(word, "check-names") == 0 ||
2228 strcasecmp(word, "checknames") == 0) {
2229 return (evaluate_checknames(cmdline));
2230 }
2231 if (strcasecmp(word, "gsstsig") == 0) {
2232 #ifdef GSSAPI
2233 usegsstsig = true;
2234 use_win2k_gsstsig = false;
2235 #else /* ifdef GSSAPI */
2236 fprintf(stderr, "gsstsig not supported\n");
2237 #endif /* ifdef GSSAPI */
2238 return (STATUS_MORE);
2239 }
2240 if (strcasecmp(word, "oldgsstsig") == 0) {
2241 #ifdef GSSAPI
2242 usegsstsig = true;
2243 use_win2k_gsstsig = true;
2244 #else /* ifdef GSSAPI */
2245 fprintf(stderr, "gsstsig not supported\n");
2246 #endif /* ifdef GSSAPI */
2247 return (STATUS_MORE);
2248 }
2249 if (strcasecmp(word, "help") == 0) {
2250 fprintf(stdout, "nsupdate " VERSION ":\n"
2251 "local address [port] (set local "
2252 "resolver)\n"
2253 "server address [port] (set master server "
2254 "for zone)\n"
2255 "send (send the update "
2256 "request)\n"
2257 "show (show the update "
2258 "request)\n"
2259 "answer (show the answer to "
2260 "the last request)\n"
2261 "quit (quit, any pending "
2262 "update is not sent)\n"
2263 "help (display this "
2264 "message)\n"
2265 "key [hmac:]keyname secret (use TSIG to sign "
2266 "the request)\n"
2267 "gsstsig (use GSS_TSIG to "
2268 "sign the request)\n"
2269 "oldgsstsig (use Microsoft's "
2270 "GSS_TSIG to sign the request)\n"
2271 "zone name (set the zone to be "
2272 "updated)\n"
2273 "class CLASS (set the zone's DNS "
2274 "class, e.g. IN (default), CH)\n"
2275 "check-names { on | off } (enable / disable "
2276 "check-names)\n"
2277 "[prereq] nxdomain name (require that this "
2278 "name does not exist)\n"
2279 "[prereq] yxdomain name (require that this "
2280 "name exists)\n"
2281 "[prereq] nxrrset .... (require that this "
2282 "RRset does not exist)\n"
2283 "[prereq] yxrrset .... (require that this "
2284 "RRset exists)\n"
2285 "[update] add .... (add the given "
2286 "record to the zone)\n"
2287 "[update] del[ete] .... (remove the given "
2288 "record(s) from the zone)\n");
2289 return (STATUS_MORE);
2290 }
2291 if (strcasecmp(word, "version") == 0) {
2292 fprintf(stdout, "nsupdate " VERSION "\n");
2293 return (STATUS_MORE);
2294 }
2295 fprintf(stderr, "incorrect section name: %s\n", word);
2296 return (STATUS_SYNTAX);
2297 }
2298
2299 static uint16_t
get_next_command(void)2300 get_next_command(void) {
2301 uint16_t result = STATUS_QUIT;
2302 char cmdlinebuf[MAXCMD];
2303 char *cmdline;
2304
2305 isc_app_block();
2306 if (interactive) {
2307 #ifdef HAVE_READLINE
2308 cmdline = readline("> ");
2309 if (cmdline != NULL) {
2310 add_history(cmdline);
2311 }
2312 #else /* ifdef HAVE_READLINE */
2313 fprintf(stdout, "> ");
2314 fflush(stdout);
2315 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2316 #endif /* ifdef HAVE_READLINE */
2317 } else {
2318 cmdline = fgets(cmdlinebuf, MAXCMD, input);
2319 }
2320 isc_app_unblock();
2321
2322 if (cmdline != NULL) {
2323 char *tmp = cmdline;
2324
2325 /*
2326 * Normalize input by removing any eol as readline()
2327 * removes eol but fgets doesn't.
2328 */
2329 (void)nsu_strsep(&tmp, "\r\n");
2330 result = do_next_command(cmdline);
2331 }
2332 #ifdef HAVE_READLINE
2333 if (interactive) {
2334 free(cmdline);
2335 }
2336 #endif /* ifdef HAVE_READLINE */
2337 return (result);
2338 }
2339
2340 static bool
user_interaction(void)2341 user_interaction(void) {
2342 uint16_t result = STATUS_MORE;
2343
2344 ddebug("user_interaction()");
2345 while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
2346 result = get_next_command();
2347 if (!interactive && result == STATUS_SYNTAX) {
2348 fatal("syntax error");
2349 }
2350 }
2351 if (result == STATUS_SEND) {
2352 return (true);
2353 }
2354 return (false);
2355 }
2356
2357 static void
done_update(void)2358 done_update(void) {
2359 isc_event_t *event = global_event;
2360 ddebug("done_update()");
2361 isc_task_send(global_task, &event);
2362 }
2363
2364 static void
check_tsig_error(dns_rdataset_t * rdataset,isc_buffer_t * b)2365 check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
2366 isc_result_t result;
2367 dns_rdata_t rdata = DNS_RDATA_INIT;
2368 dns_rdata_any_tsig_t tsig;
2369
2370 result = dns_rdataset_first(rdataset);
2371 check_result(result, "dns_rdataset_first");
2372 dns_rdataset_current(rdataset, &rdata);
2373 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
2374 check_result(result, "dns_rdata_tostruct");
2375 if (tsig.error != 0) {
2376 if (isc_buffer_remaininglength(b) < 1) {
2377 check_result(ISC_R_NOSPACE, "isc_buffer_"
2378 "remaininglength");
2379 }
2380 isc_buffer_putstr(b, "(" /*)*/);
2381 result = dns_tsigrcode_totext(tsig.error, b);
2382 check_result(result, "dns_tsigrcode_totext");
2383 if (isc_buffer_remaininglength(b) < 1) {
2384 check_result(ISC_R_NOSPACE, "isc_buffer_"
2385 "remaininglength");
2386 }
2387 isc_buffer_putstr(b, /*(*/ ")");
2388 }
2389 }
2390
2391 static bool
next_master(const char * caller,isc_sockaddr_t * addr,isc_result_t eresult)2392 next_master(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2393 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2394
2395 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2396 fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
2397 isc_result_totext(eresult));
2398 if (++master_inuse >= master_total) {
2399 return (false);
2400 }
2401 ddebug("%s: trying next server", caller);
2402 return (true);
2403 }
2404
2405 static void
update_completed(isc_task_t * task,isc_event_t * event)2406 update_completed(isc_task_t *task, isc_event_t *event) {
2407 dns_requestevent_t *reqev = NULL;
2408 isc_result_t result;
2409 dns_request_t *request;
2410
2411 UNUSED(task);
2412
2413 ddebug("update_completed()");
2414
2415 requests--;
2416
2417 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2418 reqev = (dns_requestevent_t *)event;
2419 request = reqev->request;
2420
2421 if (shuttingdown) {
2422 dns_request_destroy(&request);
2423 isc_event_free(&event);
2424 maybeshutdown();
2425 return;
2426 }
2427
2428 if (reqev->result != ISC_R_SUCCESS) {
2429 if (!next_master("update_completed",
2430 &master_servers[master_inuse], reqev->result))
2431 {
2432 seenerror = true;
2433 goto done;
2434 }
2435
2436 ddebug("Destroying request [%p]", request);
2437 dns_request_destroy(&request);
2438 dns_message_renderreset(updatemsg);
2439 dns_message_settsigkey(updatemsg, NULL);
2440 send_update(zname, &master_servers[master_inuse]);
2441 isc_event_free(&event);
2442 return;
2443 }
2444
2445 LOCK(&answer_lock);
2446 dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &answer);
2447 result = dns_request_getresponse(request, answer,
2448 DNS_MESSAGEPARSE_PRESERVEORDER);
2449 switch (result) {
2450 case ISC_R_SUCCESS:
2451 if (answer->verify_attempted) {
2452 ddebug("tsig verification successful");
2453 }
2454 break;
2455 case DNS_R_CLOCKSKEW:
2456 case DNS_R_EXPECTEDTSIG:
2457 case DNS_R_TSIGERRORSET:
2458 case DNS_R_TSIGVERIFYFAILURE:
2459 case DNS_R_UNEXPECTEDTSIG:
2460 case ISC_R_FAILURE:
2461 #if 0
2462 if (usegsstsig && answer->rcode == dns_rcode_noerror) {
2463 /*
2464 * For MS DNS that violates RFC 2845, section 4.2
2465 */
2466 break;
2467 }
2468 #endif /* if 0 */
2469 fprintf(stderr, "; TSIG error with server: %s\n",
2470 isc_result_totext(result));
2471 seenerror = true;
2472 break;
2473 default:
2474 check_result(result, "dns_request_getresponse");
2475 }
2476
2477 if (answer->opcode != dns_opcode_update) {
2478 fatal("invalid OPCODE in response to UPDATE request");
2479 }
2480
2481 if (answer->rcode != dns_rcode_noerror) {
2482 seenerror = true;
2483 if (!debugging) {
2484 char buf[64];
2485 isc_buffer_t b;
2486 dns_rdataset_t *rds;
2487
2488 isc_buffer_init(&b, buf, sizeof(buf) - 1);
2489 result = dns_rcode_totext(answer->rcode, &b);
2490 check_result(result, "dns_rcode_totext");
2491 rds = dns_message_gettsig(answer, NULL);
2492 if (rds != NULL) {
2493 check_tsig_error(rds, &b);
2494 }
2495 fprintf(stderr, "update failed: %.*s\n",
2496 (int)isc_buffer_usedlength(&b), buf);
2497 }
2498 }
2499 if (debugging) {
2500 show_message(stderr, answer, "\nReply from update query:");
2501 }
2502 UNLOCK(&answer_lock);
2503
2504 done:
2505 dns_request_destroy(&request);
2506 if (usegsstsig) {
2507 dns_name_free(&tmpzonename, gmctx);
2508 dns_name_free(&restart_master, gmctx);
2509 dns_name_init(&tmpzonename, 0);
2510 dns_name_init(&restart_master, 0);
2511 }
2512 isc_event_free(&event);
2513 done_update();
2514 }
2515
2516 static void
send_update(dns_name_t * zone,isc_sockaddr_t * master)2517 send_update(dns_name_t *zone, isc_sockaddr_t *master) {
2518 isc_result_t result;
2519 dns_request_t *request = NULL;
2520 unsigned int options = DNS_REQUESTOPT_CASE;
2521 isc_sockaddr_t *srcaddr;
2522
2523 ddebug("send_update()");
2524
2525 setzone(zone);
2526
2527 if (usevc) {
2528 options |= DNS_REQUESTOPT_TCP;
2529 }
2530 if (tsigkey == NULL && sig0key != NULL) {
2531 result = dns_message_setsig0key(updatemsg, sig0key);
2532 check_result(result, "dns_message_setsig0key");
2533 }
2534 if (debugging) {
2535 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2536
2537 isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
2538 fprintf(stderr, "Sending update to %s\n", addrbuf);
2539 }
2540
2541 if (isc_sockaddr_pf(master) == AF_INET6) {
2542 srcaddr = localaddr6;
2543 } else {
2544 srcaddr = localaddr4;
2545 }
2546
2547 /* Windows doesn't like the tsig name to be compressed. */
2548 if (updatemsg->tsigname) {
2549 updatemsg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
2550 }
2551
2552 result = dns_request_createvia(requestmgr, updatemsg, srcaddr, master,
2553 -1, options, tsigkey, timeout,
2554 udp_timeout, udp_retries, global_task,
2555 update_completed, NULL, &request);
2556 check_result(result, "dns_request_createvia");
2557
2558 if (debugging) {
2559 show_message(stdout, updatemsg, "Outgoing update query:");
2560 }
2561
2562 requests++;
2563 }
2564
2565 static void
next_server(const char * caller,isc_sockaddr_t * addr,isc_result_t eresult)2566 next_server(const char *caller, isc_sockaddr_t *addr, isc_result_t eresult) {
2567 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
2568
2569 isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
2570 fprintf(stderr, "; Communication with %s failed: %s\n", addrbuf,
2571 isc_result_totext(eresult));
2572 if (++ns_inuse >= ns_total) {
2573 fatal("could not reach any name server");
2574 } else {
2575 ddebug("%s: trying next server", caller);
2576 }
2577 }
2578
2579 static void
recvsoa(isc_task_t * task,isc_event_t * event)2580 recvsoa(isc_task_t *task, isc_event_t *event) {
2581 dns_requestevent_t *reqev = NULL;
2582 dns_request_t *request = NULL;
2583 isc_result_t result, eresult;
2584 dns_message_t *rcvmsg = NULL;
2585 dns_section_t section;
2586 dns_name_t *name = NULL;
2587 dns_rdataset_t *soaset = NULL;
2588 dns_rdata_soa_t soa;
2589 dns_rdata_t soarr = DNS_RDATA_INIT;
2590 int pass = 0;
2591 dns_name_t master;
2592 nsu_requestinfo_t *reqinfo;
2593 dns_message_t *soaquery = NULL;
2594 isc_sockaddr_t *addr;
2595 isc_sockaddr_t *srcaddr;
2596 bool seencname = false;
2597 dns_name_t tname;
2598 unsigned int nlabels;
2599
2600 UNUSED(task);
2601
2602 ddebug("recvsoa()");
2603
2604 requests--;
2605
2606 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
2607 reqev = (dns_requestevent_t *)event;
2608 request = reqev->request;
2609 eresult = reqev->result;
2610 reqinfo = reqev->ev_arg;
2611 soaquery = reqinfo->msg;
2612 addr = reqinfo->addr;
2613
2614 if (shuttingdown) {
2615 dns_request_destroy(&request);
2616 dns_message_detach(&soaquery);
2617 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2618 isc_event_free(&event);
2619 maybeshutdown();
2620 return;
2621 }
2622
2623 if (eresult != ISC_R_SUCCESS) {
2624 next_server("recvsoa", addr, eresult);
2625 ddebug("Destroying request [%p]", request);
2626 dns_request_destroy(&request);
2627 dns_message_renderreset(soaquery);
2628 dns_message_settsigkey(soaquery, NULL);
2629 sendrequest(&servers[ns_inuse], soaquery, &request);
2630 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2631 isc_event_free(&event);
2632 setzoneclass(dns_rdataclass_none);
2633 return;
2634 }
2635
2636 isc_mem_put(gmctx, reqinfo, sizeof(nsu_requestinfo_t));
2637 reqinfo = NULL;
2638 isc_event_free(&event);
2639 reqev = NULL;
2640
2641 ddebug("About to create rcvmsg");
2642 dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
2643 result = dns_request_getresponse(request, rcvmsg,
2644 DNS_MESSAGEPARSE_PRESERVEORDER);
2645 if (result == DNS_R_TSIGERRORSET && servers != NULL) {
2646 dns_message_detach(&rcvmsg);
2647 ddebug("Destroying request [%p]", request);
2648 dns_request_destroy(&request);
2649 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
2650 reqinfo->msg = soaquery;
2651 reqinfo->addr = addr;
2652 dns_message_renderreset(soaquery);
2653 ddebug("retrying soa request without TSIG");
2654
2655 if (isc_sockaddr_pf(addr) == AF_INET6) {
2656 srcaddr = localaddr6;
2657 } else {
2658 srcaddr = localaddr4;
2659 }
2660
2661 result = dns_request_createvia(
2662 requestmgr, soaquery, srcaddr, addr, -1, 0, NULL,
2663 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3, global_task,
2664 recvsoa, reqinfo, &request);
2665 check_result(result, "dns_request_createvia");
2666 requests++;
2667 return;
2668 }
2669 check_result(result, "dns_request_getresponse");
2670
2671 if (rcvmsg->rcode == dns_rcode_refused) {
2672 next_server("recvsoa", addr, DNS_R_REFUSED);
2673 dns_message_detach(&rcvmsg);
2674 dns_request_destroy(&request);
2675 dns_message_renderreset(soaquery);
2676 dns_message_settsigkey(soaquery, NULL);
2677 sendrequest(&servers[ns_inuse], soaquery, &request);
2678 return;
2679 }
2680
2681 section = DNS_SECTION_ANSWER;
2682 POST(section);
2683 if (debugging) {
2684 show_message(stderr, rcvmsg, "Reply from SOA query:");
2685 }
2686
2687 if (rcvmsg->opcode != dns_opcode_query) {
2688 fatal("invalid OPCODE in response to SOA query");
2689 }
2690
2691 if (rcvmsg->rcode != dns_rcode_noerror &&
2692 rcvmsg->rcode != dns_rcode_nxdomain) {
2693 fatal("response to SOA query was unsuccessful");
2694 }
2695
2696 if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
2697 char namebuf[DNS_NAME_FORMATSIZE];
2698 dns_name_format(userzone, namebuf, sizeof(namebuf));
2699 error("specified zone '%s' does not exist (NXDOMAIN)", namebuf);
2700 dns_message_detach(&rcvmsg);
2701 dns_request_destroy(&request);
2702 dns_message_detach(&soaquery);
2703 ddebug("Out of recvsoa");
2704 done_update();
2705 seenerror = true;
2706 return;
2707 }
2708
2709 lookforsoa:
2710 if (pass == 0) {
2711 section = DNS_SECTION_ANSWER;
2712 } else if (pass == 1) {
2713 section = DNS_SECTION_AUTHORITY;
2714 } else {
2715 goto droplabel;
2716 }
2717
2718 result = dns_message_firstname(rcvmsg, section);
2719 if (result != ISC_R_SUCCESS) {
2720 pass++;
2721 goto lookforsoa;
2722 }
2723 while (result == ISC_R_SUCCESS) {
2724 name = NULL;
2725 dns_message_currentname(rcvmsg, section, &name);
2726 soaset = NULL;
2727 result = dns_message_findtype(name, dns_rdatatype_soa, 0,
2728 &soaset);
2729 if (result == ISC_R_SUCCESS) {
2730 break;
2731 }
2732 if (section == DNS_SECTION_ANSWER) {
2733 dns_rdataset_t *tset = NULL;
2734 if (dns_message_findtype(name, dns_rdatatype_cname, 0,
2735 &tset) == ISC_R_SUCCESS ||
2736 dns_message_findtype(name, dns_rdatatype_dname, 0,
2737 &tset) == ISC_R_SUCCESS)
2738 {
2739 seencname = true;
2740 break;
2741 }
2742 }
2743
2744 result = dns_message_nextname(rcvmsg, section);
2745 }
2746
2747 if (soaset == NULL && !seencname) {
2748 pass++;
2749 goto lookforsoa;
2750 }
2751
2752 if (seencname) {
2753 goto droplabel;
2754 }
2755
2756 if (debugging) {
2757 char namestr[DNS_NAME_FORMATSIZE];
2758 dns_name_format(name, namestr, sizeof(namestr));
2759 fprintf(stderr, "Found zone name: %s\n", namestr);
2760 }
2761
2762 result = dns_rdataset_first(soaset);
2763 check_result(result, "dns_rdataset_first");
2764
2765 dns_rdata_init(&soarr);
2766 dns_rdataset_current(soaset, &soarr);
2767 result = dns_rdata_tostruct(&soarr, &soa, NULL);
2768 check_result(result, "dns_rdata_tostruct");
2769
2770 dns_name_init(&master, NULL);
2771 dns_name_clone(&soa.origin, &master);
2772
2773 if (userzone != NULL) {
2774 zname = userzone;
2775 } else {
2776 /*
2777 * Save the zone name in case we need to try a second
2778 * address.
2779 */
2780 zname = dns_fixedname_initname(&fzname);
2781 dns_name_copynf(name, zname);
2782 }
2783
2784 if (debugging) {
2785 char namestr[DNS_NAME_FORMATSIZE];
2786 dns_name_format(&master, namestr, sizeof(namestr));
2787 fprintf(stderr, "The master is: %s\n", namestr);
2788 }
2789
2790 if (default_servers) {
2791 char serverstr[DNS_NAME_MAXTEXT + 1];
2792 isc_buffer_t buf;
2793 size_t size;
2794
2795 isc_buffer_init(&buf, serverstr, sizeof(serverstr));
2796 result = dns_name_totext(&master, true, &buf);
2797 check_result(result, "dns_name_totext");
2798 serverstr[isc_buffer_usedlength(&buf)] = 0;
2799
2800 if (master_servers != NULL && master_servers != servers) {
2801 isc_mem_put(gmctx, master_servers,
2802 master_alloc * sizeof(isc_sockaddr_t));
2803 }
2804 master_alloc = MAX_SERVERADDRS;
2805 size = master_alloc * sizeof(isc_sockaddr_t);
2806 master_servers = isc_mem_get(gmctx, size);
2807
2808 memset(master_servers, 0, size);
2809 master_total = get_addresses(serverstr, dnsport, master_servers,
2810 master_alloc);
2811 if (master_total == 0) {
2812 exit(1);
2813 }
2814 master_inuse = 0;
2815 } else {
2816 master_from_servers();
2817 }
2818 dns_rdata_freestruct(&soa);
2819
2820 #ifdef GSSAPI
2821 if (usegsstsig) {
2822 dns_name_init(&tmpzonename, NULL);
2823 dns_name_dup(zname, gmctx, &tmpzonename);
2824 dns_name_init(&restart_master, NULL);
2825 dns_name_dup(&master, gmctx, &restart_master);
2826 start_gssrequest(&master);
2827 } else {
2828 send_update(zname, &master_servers[master_inuse]);
2829 setzoneclass(dns_rdataclass_none);
2830 }
2831 #else /* ifdef GSSAPI */
2832 send_update(zname, &master_servers[master_inuse]);
2833 setzoneclass(dns_rdataclass_none);
2834 #endif /* ifdef GSSAPI */
2835
2836 dns_message_detach(&soaquery);
2837 dns_request_destroy(&request);
2838
2839 out:
2840 dns_message_detach(&rcvmsg);
2841 ddebug("Out of recvsoa");
2842 return;
2843
2844 droplabel:
2845 result = dns_message_firstname(soaquery, DNS_SECTION_QUESTION);
2846 INSIST(result == ISC_R_SUCCESS);
2847 name = NULL;
2848 dns_message_currentname(soaquery, DNS_SECTION_QUESTION, &name);
2849 nlabels = dns_name_countlabels(name);
2850 if (nlabels == 1) {
2851 fatal("could not find enclosing zone");
2852 }
2853 dns_name_init(&tname, NULL);
2854 dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
2855 dns_name_clone(&tname, name);
2856 dns_request_destroy(&request);
2857 dns_message_renderreset(soaquery);
2858 dns_message_settsigkey(soaquery, NULL);
2859 sendrequest(&servers[ns_inuse], soaquery, &request);
2860 goto out;
2861 }
2862
2863 static void
sendrequest(isc_sockaddr_t * destaddr,dns_message_t * msg,dns_request_t ** request)2864 sendrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
2865 dns_request_t **request) {
2866 isc_result_t result;
2867 nsu_requestinfo_t *reqinfo;
2868 isc_sockaddr_t *srcaddr;
2869
2870 reqinfo = isc_mem_get(gmctx, sizeof(nsu_requestinfo_t));
2871 reqinfo->msg = msg;
2872 reqinfo->addr = destaddr;
2873
2874 if (isc_sockaddr_pf(destaddr) == AF_INET6) {
2875 srcaddr = localaddr6;
2876 } else {
2877 srcaddr = localaddr4;
2878 }
2879
2880 result = dns_request_createvia(requestmgr, msg, srcaddr, destaddr, -1,
2881 0, default_servers ? NULL : tsigkey,
2882 FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
2883 global_task, recvsoa, reqinfo, request);
2884 check_result(result, "dns_request_createvia");
2885 requests++;
2886 }
2887
2888 #ifdef GSSAPI
2889
2890 /*
2891 * Get the realm from the users kerberos ticket if possible
2892 */
2893 static void
get_ticket_realm(isc_mem_t * mctx)2894 get_ticket_realm(isc_mem_t *mctx) {
2895 krb5_context ctx;
2896 krb5_error_code rc;
2897 krb5_ccache ccache;
2898 krb5_principal princ;
2899 char *name;
2900 const char *ticket_realm;
2901
2902 rc = krb5_init_context(&ctx);
2903 if (rc != 0) {
2904 return;
2905 }
2906
2907 rc = krb5_cc_default(ctx, &ccache);
2908 if (rc != 0) {
2909 krb5_free_context(ctx);
2910 return;
2911 }
2912
2913 rc = krb5_cc_get_principal(ctx, ccache, &princ);
2914 if (rc != 0) {
2915 krb5_cc_close(ctx, ccache);
2916 krb5_free_context(ctx);
2917 return;
2918 }
2919
2920 rc = krb5_unparse_name(ctx, princ, &name);
2921 if (rc != 0) {
2922 krb5_free_principal(ctx, princ);
2923 krb5_cc_close(ctx, ccache);
2924 krb5_free_context(ctx);
2925 return;
2926 }
2927
2928 ticket_realm = strrchr(name, '@');
2929 if (ticket_realm != NULL) {
2930 realm = isc_mem_strdup(mctx, ticket_realm);
2931 }
2932
2933 free(name);
2934 krb5_free_principal(ctx, princ);
2935 krb5_cc_close(ctx, ccache);
2936 krb5_free_context(ctx);
2937 if (realm != NULL && debugging) {
2938 fprintf(stderr, "Found realm from ticket: %s\n", realm + 1);
2939 }
2940 }
2941
2942 static void
failed_gssrequest()2943 failed_gssrequest() {
2944 seenerror = true;
2945
2946 dns_name_free(&tmpzonename, gmctx);
2947 dns_name_free(&restart_master, gmctx);
2948 dns_name_init(&tmpzonename, NULL);
2949 dns_name_init(&restart_master, NULL);
2950
2951 done_update();
2952 }
2953
2954 static void
start_gssrequest(dns_name_t * master)2955 start_gssrequest(dns_name_t *master) {
2956 dns_gss_ctx_id_t context;
2957 isc_buffer_t buf;
2958 isc_result_t result;
2959 uint32_t val = 0;
2960 dns_message_t *rmsg = NULL;
2961 dns_request_t *request = NULL;
2962 dns_name_t *servname;
2963 dns_fixedname_t fname;
2964 char namestr[DNS_NAME_FORMATSIZE];
2965 char mykeystr[DNS_NAME_FORMATSIZE];
2966 char *err_message = NULL;
2967
2968 debug("start_gssrequest");
2969 usevc = true;
2970
2971 if (gssring != NULL) {
2972 dns_tsigkeyring_detach(&gssring);
2973 }
2974 gssring = NULL;
2975 result = dns_tsigkeyring_create(gmctx, &gssring);
2976
2977 if (result != ISC_R_SUCCESS) {
2978 fatal("dns_tsigkeyring_create failed: %s",
2979 isc_result_totext(result));
2980 }
2981
2982 dns_name_format(master, namestr, sizeof(namestr));
2983 if (kserver == NULL) {
2984 kserver = isc_mem_get(gmctx, sizeof(isc_sockaddr_t));
2985 }
2986
2987 memmove(kserver, &master_servers[master_inuse], sizeof(isc_sockaddr_t));
2988
2989 servname = dns_fixedname_initname(&fname);
2990
2991 if (realm == NULL) {
2992 get_ticket_realm(gmctx);
2993 }
2994
2995 result = snprintf(servicename, sizeof(servicename), "DNS/%s%s", namestr,
2996 realm ? realm : "");
2997 RUNTIME_CHECK(result < sizeof(servicename));
2998 isc_buffer_init(&buf, servicename, strlen(servicename));
2999 isc_buffer_add(&buf, strlen(servicename));
3000 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
3001 if (result != ISC_R_SUCCESS) {
3002 fatal("dns_name_fromtext(servname) failed: %s",
3003 isc_result_totext(result));
3004 }
3005
3006 keyname = dns_fixedname_initname(&fkname);
3007
3008 isc_nonce_buf(&val, sizeof(val));
3009
3010 result = snprintf(mykeystr, sizeof(mykeystr), "%u.sig-%s", val,
3011 namestr);
3012 RUNTIME_CHECK(result <= sizeof(mykeystr));
3013
3014 isc_buffer_init(&buf, mykeystr, strlen(mykeystr));
3015 isc_buffer_add(&buf, strlen(mykeystr));
3016
3017 result = dns_name_fromtext(keyname, &buf, dns_rootname, 0, NULL);
3018 if (result != ISC_R_SUCCESS) {
3019 fatal("dns_name_fromtext(keyname) failed: %s",
3020 isc_result_totext(result));
3021 }
3022
3023 /* Windows doesn't recognize name compression in the key name. */
3024 keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
3025
3026 rmsg = NULL;
3027 dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
3028
3029 /* Build first request. */
3030 context = GSS_C_NO_CONTEXT;
3031 result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
3032 &context, use_win2k_gsstsig, gmctx,
3033 &err_message);
3034 if (result == ISC_R_FAILURE) {
3035 fprintf(stderr, "tkey query failed: %s\n",
3036 err_message != NULL ? err_message : "unknown error");
3037 goto failure;
3038 }
3039 if (result != ISC_R_SUCCESS) {
3040 fatal("dns_tkey_buildgssquery failed: %s",
3041 isc_result_totext(result));
3042 }
3043
3044 send_gssrequest(kserver, rmsg, &request, context);
3045 return;
3046
3047 failure:
3048 if (rmsg != NULL) {
3049 dns_message_detach(&rmsg);
3050 }
3051 if (err_message != NULL) {
3052 isc_mem_free(gmctx, err_message);
3053 }
3054 failed_gssrequest();
3055 }
3056
3057 static void
send_gssrequest(isc_sockaddr_t * destaddr,dns_message_t * msg,dns_request_t ** request,dns_gss_ctx_id_t context)3058 send_gssrequest(isc_sockaddr_t *destaddr, dns_message_t *msg,
3059 dns_request_t **request, dns_gss_ctx_id_t context) {
3060 isc_result_t result;
3061 nsu_gssinfo_t *reqinfo;
3062 unsigned int options = 0;
3063 isc_sockaddr_t *srcaddr;
3064
3065 debug("send_gssrequest");
3066 REQUIRE(destaddr != NULL);
3067
3068 reqinfo = isc_mem_get(gmctx, sizeof(nsu_gssinfo_t));
3069 reqinfo->msg = msg;
3070 reqinfo->addr = destaddr;
3071 reqinfo->context = context;
3072
3073 options |= DNS_REQUESTOPT_TCP;
3074
3075 if (isc_sockaddr_pf(destaddr) == AF_INET6) {
3076 srcaddr = localaddr6;
3077 } else {
3078 srcaddr = localaddr4;
3079 }
3080
3081 result = dns_request_createvia(requestmgr, msg, srcaddr, destaddr, -1,
3082 options, tsigkey, FIND_TIMEOUT * 20,
3083 FIND_TIMEOUT, 3, global_task, recvgss,
3084 reqinfo, request);
3085 check_result(result, "dns_request_createvia");
3086 if (debugging) {
3087 show_message(stdout, msg, "Outgoing update query:");
3088 }
3089 requests++;
3090 }
3091
3092 static void
recvgss(isc_task_t * task,isc_event_t * event)3093 recvgss(isc_task_t *task, isc_event_t *event) {
3094 dns_requestevent_t *reqev = NULL;
3095 dns_request_t *request = NULL;
3096 isc_result_t result, eresult;
3097 dns_message_t *rcvmsg = NULL;
3098 nsu_gssinfo_t *reqinfo;
3099 dns_message_t *tsigquery = NULL;
3100 isc_sockaddr_t *addr;
3101 dns_gss_ctx_id_t context;
3102 isc_buffer_t buf;
3103 dns_name_t *servname;
3104 dns_fixedname_t fname;
3105 char *err_message = NULL;
3106
3107 UNUSED(task);
3108
3109 ddebug("recvgss()");
3110
3111 requests--;
3112
3113 REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
3114 reqev = (dns_requestevent_t *)event;
3115 request = reqev->request;
3116 eresult = reqev->result;
3117 reqinfo = reqev->ev_arg;
3118 tsigquery = reqinfo->msg;
3119 context = reqinfo->context;
3120 addr = reqinfo->addr;
3121
3122 if (shuttingdown) {
3123 dns_request_destroy(&request);
3124 dns_message_detach(&tsigquery);
3125 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3126 isc_event_free(&event);
3127 maybeshutdown();
3128 return;
3129 }
3130
3131 if (eresult != ISC_R_SUCCESS) {
3132 ddebug("Destroying request [%p]", request);
3133 dns_request_destroy(&request);
3134 if (!next_master("recvgss", addr, eresult)) {
3135 dns_message_detach(&tsigquery);
3136 failed_gssrequest();
3137 } else {
3138 dns_message_renderreset(tsigquery);
3139 memmove(kserver, &master_servers[master_inuse],
3140 sizeof(isc_sockaddr_t));
3141 send_gssrequest(kserver, tsigquery, &request, context);
3142 }
3143 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3144 isc_event_free(&event);
3145 return;
3146 }
3147 isc_mem_put(gmctx, reqinfo, sizeof(nsu_gssinfo_t));
3148
3149 isc_event_free(&event);
3150 reqev = NULL;
3151
3152 ddebug("recvgss creating rcvmsg");
3153 dns_message_create(gmctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
3154
3155 result = dns_request_getresponse(request, rcvmsg,
3156 DNS_MESSAGEPARSE_PRESERVEORDER);
3157 check_result(result, "dns_request_getresponse");
3158
3159 if (debugging) {
3160 show_message(stderr, rcvmsg,
3161 "recvmsg reply from GSS-TSIG query");
3162 }
3163
3164 if (rcvmsg->opcode != dns_opcode_query) {
3165 fatal("invalid OPCODE in response to GSS-TSIG query");
3166 }
3167
3168 if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
3169 ddebug("recvgss trying %s GSS-TSIG",
3170 use_win2k_gsstsig ? "Standard" : "Win2k");
3171 if (use_win2k_gsstsig) {
3172 use_win2k_gsstsig = false;
3173 } else {
3174 use_win2k_gsstsig = true;
3175 }
3176 tried_other_gsstsig = true;
3177 start_gssrequest(&restart_master);
3178 goto done;
3179 }
3180
3181 if (rcvmsg->rcode != dns_rcode_noerror &&
3182 rcvmsg->rcode != dns_rcode_nxdomain) {
3183 fatal("response to GSS-TSIG query was unsuccessful");
3184 }
3185
3186 servname = dns_fixedname_initname(&fname);
3187 isc_buffer_init(&buf, servicename, strlen(servicename));
3188 isc_buffer_add(&buf, strlen(servicename));
3189 result = dns_name_fromtext(servname, &buf, dns_rootname, 0, NULL);
3190 check_result(result, "dns_name_fromtext");
3191
3192 tsigkey = NULL;
3193 result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname, &context,
3194 &tsigkey, gssring, use_win2k_gsstsig,
3195 &err_message);
3196 switch (result) {
3197 case DNS_R_CONTINUE:
3198 dns_message_detach(&rcvmsg);
3199 dns_request_destroy(&request);
3200 send_gssrequest(kserver, tsigquery, &request, context);
3201 ddebug("Out of recvgss");
3202 return;
3203
3204 case ISC_R_SUCCESS:
3205 /*
3206 * XXXSRA Waaay too much fun here. There's no good
3207 * reason why we need a TSIG here (the people who put
3208 * it into the spec admitted at the time that it was
3209 * not a security issue), and Windows clients don't
3210 * seem to work if named complies with the spec and
3211 * includes the gratuitous TSIG. So we're in the
3212 * bizarre situation of having to choose between
3213 * complying with a useless requirement in the spec
3214 * and interoperating. This is nuts. If we can
3215 * confirm this behavior, we should ask the WG to
3216 * consider removing the requirement for the
3217 * gratuitous TSIG here. For the moment, we ignore
3218 * the TSIG -- this too is a spec violation, but it's
3219 * the least insane thing to do.
3220 */
3221 #if 0
3222 /*
3223 * Verify the signature.
3224 */
3225 rcvmsg->state = DNS_SECTION_ANY;
3226 dns_message_setquerytsig(rcvmsg, NULL);
3227 result = dns_message_settsigkey(rcvmsg, tsigkey);
3228 check_result(result, "dns_message_settsigkey");
3229 result = dns_message_checksig(rcvmsg, NULL);
3230 ddebug("tsig verification: %s", dns_result_totext(result));
3231 check_result(result, "dns_message_checksig");
3232 #endif /* 0 */
3233
3234 send_update(&tmpzonename, &master_servers[master_inuse]);
3235 setzoneclass(dns_rdataclass_none);
3236 break;
3237
3238 default:
3239 fatal("dns_tkey_gssnegotiate: %s %s", isc_result_totext(result),
3240 err_message != NULL ? err_message : "");
3241 }
3242
3243 done:
3244 dns_request_destroy(&request);
3245 dns_message_detach(&tsigquery);
3246
3247 dns_message_detach(&rcvmsg);
3248 ddebug("Out of recvgss");
3249 }
3250 #endif /* ifdef GSSAPI */
3251
3252 static void
start_update(void)3253 start_update(void) {
3254 isc_result_t result;
3255 dns_rdataset_t *rdataset = NULL;
3256 dns_name_t *name = NULL;
3257 dns_request_t *request = NULL;
3258 dns_message_t *soaquery = NULL;
3259 dns_name_t *firstname;
3260 dns_section_t section = DNS_SECTION_UPDATE;
3261
3262 ddebug("start_update()");
3263
3264 LOCK(&answer_lock);
3265 if (answer != NULL) {
3266 dns_message_detach(&answer);
3267 }
3268 UNLOCK(&answer_lock);
3269
3270 /*
3271 * If we have both the zone and the servers we have enough information
3272 * to send the update straight away otherwise we need to discover
3273 * the zone and / or the master server.
3274 */
3275 if (userzone != NULL && !default_servers && !usegsstsig) {
3276 master_from_servers();
3277 send_update(userzone, &master_servers[master_inuse]);
3278 setzoneclass(dns_rdataclass_none);
3279 return;
3280 }
3281
3282 dns_message_create(gmctx, DNS_MESSAGE_INTENTRENDER, &soaquery);
3283
3284 if (default_servers) {
3285 soaquery->flags |= DNS_MESSAGEFLAG_RD;
3286 }
3287
3288 result = dns_message_gettempname(soaquery, &name);
3289 check_result(result, "dns_message_gettempname");
3290
3291 result = dns_message_gettemprdataset(soaquery, &rdataset);
3292 check_result(result, "dns_message_gettemprdataset");
3293
3294 dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
3295
3296 if (userzone != NULL) {
3297 dns_name_clone(userzone, name);
3298 } else {
3299 dns_rdataset_t *tmprdataset;
3300 result = dns_message_firstname(updatemsg, section);
3301 if (result == ISC_R_NOMORE) {
3302 section = DNS_SECTION_PREREQUISITE;
3303 result = dns_message_firstname(updatemsg, section);
3304 }
3305 if (result != ISC_R_SUCCESS) {
3306 dns_message_puttempname(soaquery, &name);
3307 dns_rdataset_disassociate(rdataset);
3308 dns_message_puttemprdataset(soaquery, &rdataset);
3309 dns_message_detach(&soaquery);
3310 done_update();
3311 return;
3312 }
3313 firstname = NULL;
3314 dns_message_currentname(updatemsg, section, &firstname);
3315 dns_name_clone(firstname, name);
3316 /*
3317 * Looks to see if the first name references a DS record
3318 * and if that name is not the root remove a label as DS
3319 * records live in the parent zone so we need to start our
3320 * search one label up.
3321 */
3322 tmprdataset = ISC_LIST_HEAD(firstname->list);
3323 if (section == DNS_SECTION_UPDATE &&
3324 !dns_name_equal(firstname, dns_rootname) &&
3325 tmprdataset->type == dns_rdatatype_ds)
3326 {
3327 unsigned int labels = dns_name_countlabels(name);
3328 dns_name_getlabelsequence(name, 1, labels - 1, name);
3329 }
3330 }
3331
3332 ISC_LIST_INIT(name->list);
3333 ISC_LIST_APPEND(name->list, rdataset, link);
3334 dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
3335
3336 ns_inuse = 0;
3337 sendrequest(&servers[ns_inuse], soaquery, &request);
3338 }
3339
3340 static void
cleanup(void)3341 cleanup(void) {
3342 ddebug("cleanup()");
3343
3344 LOCK(&answer_lock);
3345 if (answer != NULL) {
3346 dns_message_detach(&answer);
3347 }
3348 UNLOCK(&answer_lock);
3349
3350 #ifdef GSSAPI
3351 if (tsigkey != NULL) {
3352 ddebug("detach tsigkey x%p", tsigkey);
3353 dns_tsigkey_detach(&tsigkey);
3354 }
3355 if (gssring != NULL) {
3356 ddebug("Detaching GSS-TSIG keyring");
3357 dns_tsigkeyring_detach(&gssring);
3358 }
3359 #endif /* ifdef GSSAPI */
3360
3361 if (sig0key != NULL) {
3362 dst_key_free(&sig0key);
3363 }
3364
3365 ddebug("Shutting down task manager");
3366 isc_managers_destroy(&netmgr, &taskmgr);
3367
3368 ddebug("Destroying event");
3369 isc_event_free(&global_event);
3370
3371 ddebug("Shutting down socket manager");
3372 isc_socketmgr_destroy(&socketmgr);
3373
3374 ddebug("Shutting down timer manager");
3375 isc_timermgr_destroy(&timermgr);
3376
3377 #ifdef GSSAPI
3378 /*
3379 * Cleanup GSSAPI resources after taskmgr has been destroyed.
3380 */
3381 if (kserver != NULL) {
3382 isc_mem_put(gmctx, kserver, sizeof(isc_sockaddr_t));
3383 kserver = NULL;
3384 }
3385 if (realm != NULL) {
3386 isc_mem_free(gmctx, realm);
3387 realm = NULL;
3388 }
3389 if (dns_name_dynamic(&tmpzonename)) {
3390 dns_name_free(&tmpzonename, gmctx);
3391 }
3392 if (dns_name_dynamic(&restart_master)) {
3393 dns_name_free(&restart_master, gmctx);
3394 }
3395 #endif /* ifdef GSSAPI */
3396
3397 ddebug("Removing log context");
3398 isc_log_destroy(&glctx);
3399
3400 ddebug("Destroying memory context");
3401 if (memdebugging) {
3402 isc_mem_stats(gmctx, stderr);
3403 }
3404 isc_mem_destroy(&gmctx);
3405
3406 isc_mutex_destroy(&answer_lock);
3407 }
3408
3409 static void
getinput(isc_task_t * task,isc_event_t * event)3410 getinput(isc_task_t *task, isc_event_t *event) {
3411 bool more;
3412
3413 UNUSED(task);
3414
3415 if (shuttingdown) {
3416 maybeshutdown();
3417 return;
3418 }
3419
3420 if (global_event == NULL) {
3421 global_event = event;
3422 }
3423
3424 reset_system();
3425 more = user_interaction();
3426 if (!more) {
3427 isc_app_shutdown();
3428 return;
3429 }
3430 start_update();
3431 return;
3432 }
3433
3434 int
main(int argc,char ** argv)3435 main(int argc, char **argv) {
3436 isc_result_t result;
3437 style = &dns_master_style_debug;
3438
3439 input = stdin;
3440
3441 interactive = isatty(0);
3442
3443 isc_app_start();
3444
3445 if (isc_net_probeipv4() == ISC_R_SUCCESS) {
3446 have_ipv4 = true;
3447 }
3448 if (isc_net_probeipv6() == ISC_R_SUCCESS) {
3449 have_ipv6 = true;
3450 }
3451 if (!have_ipv4 && !have_ipv6) {
3452 fatal("could not find either IPv4 or IPv6");
3453 }
3454
3455 pre_parse_args(argc, argv);
3456
3457 isc_mem_create(&gmctx);
3458
3459 parse_args(argc, argv);
3460
3461 setup_system();
3462
3463 result = isc_app_onrun(gmctx, global_task, getinput, NULL);
3464 check_result(result, "isc_app_onrun");
3465
3466 (void)isc_app_run();
3467
3468 cleanup();
3469
3470 isc_app_finish();
3471
3472 if (seenerror) {
3473 return (2);
3474 } else {
3475 return (0);
3476 }
3477 }
3478