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