1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #include <inttypes.h>
15 #include <stdbool.h>
16
17 #include <isc/atomic.h>
18 #include <isc/event.h>
19 #include <isc/lex.h>
20 #include <isc/magic.h>
21 #include <isc/mem.h>
22 #include <isc/print.h>
23 #include <isc/refcount.h>
24 #include <isc/serial.h>
25 #include <isc/stdio.h>
26 #include <isc/stdtime.h>
27 #include <isc/string.h>
28 #include <isc/task.h>
29 #include <isc/util.h>
30
31 #include <dns/callbacks.h>
32 #include <dns/events.h>
33 #include <dns/fixedname.h>
34 #include <dns/master.h>
35 #include <dns/name.h>
36 #include <dns/rdata.h>
37 #include <dns/rdataclass.h>
38 #include <dns/rdatalist.h>
39 #include <dns/rdataset.h>
40 #include <dns/rdatastruct.h>
41 #include <dns/rdatatype.h>
42 #include <dns/result.h>
43 #include <dns/soa.h>
44 #include <dns/time.h>
45 #include <dns/ttl.h>
46
47 /*!
48 * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ)
49 * structures by these sizes when we need to.
50 *
51 */
52 /*% RDLSZ reflects the number of different types with the same name expected. */
53 #define RDLSZ 32
54 /*%
55 * RDSZ reflects the number of rdata expected at a give name that can fit into
56 * 64k.
57 */
58 #define RDSZ 512
59
60 #define NBUFS 4
61 #define MAXWIRESZ 255
62
63 /*%
64 * Target buffer size and minimum target size.
65 * MINTSIZ must be big enough to hold the largest rdata record.
66 * \brief
67 * TSIZ >= MINTSIZ
68 */
69 #define TSIZ (128 * 1024)
70 /*%
71 * max message size - header - root - type - class - ttl - rdlen
72 */
73 #define MINTSIZ DNS_RDATA_MAXLENGTH
74 /*%
75 * Size for tokens in the presentation format,
76 * The largest tokens are the base64 blocks in KEY and CERT records,
77 * Largest key allowed is about 1372 bytes but
78 * there is no fixed upper bound on CERT records.
79 * 2K is too small for some X.509s, 8K is overkill.
80 */
81 #define TOKENSIZ (8 * 1024)
82
83 /*%
84 * Buffers sizes for $GENERATE.
85 */
86 #define DNS_MASTER_LHS 2048
87 #define DNS_MASTER_RHS MINTSIZ
88
89 #define CHECKNAMESFAIL(x) (((x)&DNS_MASTER_CHECKNAMESFAIL) != 0)
90
91 typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
92
93 typedef struct dns_incctx dns_incctx_t;
94
95 /*%
96 * Master file load state.
97 */
98
99 struct dns_loadctx {
100 unsigned int magic;
101 isc_mem_t *mctx;
102 dns_masterformat_t format;
103
104 dns_rdatacallbacks_t *callbacks;
105 isc_task_t *task;
106 dns_loaddonefunc_t done;
107 void *done_arg;
108
109 /* Common methods */
110 isc_result_t (*openfile)(dns_loadctx_t *lctx, const char *filename);
111 isc_result_t (*load)(dns_loadctx_t *lctx);
112
113 /* Members used by all formats */
114 uint32_t maxttl;
115
116 /* Members specific to the text format: */
117 isc_lex_t *lex;
118 bool keep_lex;
119 unsigned int options;
120 bool ttl_known;
121 bool default_ttl_known;
122 bool warn_1035;
123 bool warn_tcr;
124 bool warn_sigexpired;
125 bool seen_include;
126 uint32_t ttl;
127 uint32_t default_ttl;
128 dns_rdataclass_t zclass;
129 dns_fixedname_t fixed_top;
130 dns_name_t *top; /*%< top of zone */
131
132 /* Members specific to the raw format: */
133 FILE *f;
134 bool first;
135 dns_masterrawheader_t header;
136
137 /* Which fixed buffers we are using? */
138 unsigned int loop_cnt; /*% records per quantum,
139 * 0 => all. */
140 isc_result_t result;
141
142 /* Atomic */
143 isc_refcount_t references;
144 atomic_bool canceled;
145
146 /* locked by lock */
147 dns_incctx_t *inc;
148 uint32_t resign;
149 isc_stdtime_t now;
150
151 dns_masterincludecb_t include_cb;
152 void *include_arg;
153 };
154
155 struct dns_incctx {
156 dns_incctx_t *parent;
157 dns_name_t *origin;
158 dns_name_t *current;
159 dns_name_t *glue;
160 dns_fixedname_t fixed[NBUFS]; /* working buffers */
161 unsigned int in_use[NBUFS]; /* covert to bitmap? */
162 int glue_in_use;
163 int current_in_use;
164 int origin_in_use;
165 bool origin_changed;
166 bool drop;
167 unsigned int glue_line;
168 unsigned int current_line;
169 };
170
171 #define DNS_LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
172 #define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
173
174 #define DNS_AS_STR(t) ((t).value.as_textregion.base)
175
176 static isc_result_t
177 openfile_text(dns_loadctx_t *lctx, const char *master_file);
178
179 static isc_result_t
180 load_text(dns_loadctx_t *lctx);
181
182 static isc_result_t
183 openfile_raw(dns_loadctx_t *lctx, const char *master_file);
184
185 static isc_result_t
186 load_raw(dns_loadctx_t *lctx);
187
188 static isc_result_t
189 openfile_map(dns_loadctx_t *lctx, const char *master_file);
190
191 static isc_result_t
192 load_map(dns_loadctx_t *lctx);
193
194 static isc_result_t
195 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
196
197 static isc_result_t
198 commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
199 dns_name_t *, const char *, unsigned int);
200
201 static bool
202 is_glue(rdatalist_head_t *, dns_name_t *);
203
204 static dns_rdatalist_t *
205 grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
206 rdatalist_head_t *, isc_mem_t *mctx);
207
208 static dns_rdata_t *
209 grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
210 isc_mem_t *);
211
212 static void
213 load_quantum(isc_task_t *task, isc_event_t *event);
214
215 static isc_result_t
216 task_send(dns_loadctx_t *lctx);
217
218 static void
219 loadctx_destroy(dns_loadctx_t *lctx);
220
221 #define GETTOKENERR(lexer, options, token, eol, err) \
222 do { \
223 result = gettoken(lexer, options, token, eol, callbacks); \
224 switch (result) { \
225 case ISC_R_SUCCESS: \
226 break; \
227 case ISC_R_UNEXPECTED: \
228 goto insist_and_cleanup; \
229 default: \
230 if (MANYERRS(lctx, result)) { \
231 SETRESULT(lctx, result); \
232 LOGIT(result); \
233 read_till_eol = true; \
234 err goto next_line; \
235 } else \
236 goto log_and_cleanup; \
237 } \
238 if ((token)->type == isc_tokentype_special) { \
239 result = DNS_R_SYNTAX; \
240 if (MANYERRS(lctx, result)) { \
241 SETRESULT(lctx, result); \
242 LOGIT(result); \
243 read_till_eol = true; \
244 goto next_line; \
245 } else \
246 goto log_and_cleanup; \
247 } \
248 } while (0)
249 #define GETTOKEN(lexer, options, token, eol) \
250 GETTOKENERR(lexer, options, token, eol, {})
251
252 #define COMMITALL \
253 do { \
254 result = commit(callbacks, lctx, ¤t_list, ictx->current, \
255 source, ictx->current_line); \
256 if (MANYERRS(lctx, result)) { \
257 SETRESULT(lctx, result); \
258 } else if (result != ISC_R_SUCCESS) \
259 goto insist_and_cleanup; \
260 result = commit(callbacks, lctx, &glue_list, ictx->glue, \
261 source, ictx->glue_line); \
262 if (MANYERRS(lctx, result)) { \
263 SETRESULT(lctx, result); \
264 } else if (result != ISC_R_SUCCESS) \
265 goto insist_and_cleanup; \
266 rdcount = 0; \
267 rdlcount = 0; \
268 isc_buffer_init(&target, target_mem, target_size); \
269 rdcount_save = rdcount; \
270 rdlcount_save = rdlcount; \
271 } while (0)
272
273 #define WARNUNEXPECTEDEOF(lexer) \
274 do { \
275 if (isc_lex_isfile(lexer)) \
276 (*callbacks->warn)(callbacks, \
277 "%s: file does not end with " \
278 "newline", \
279 source); \
280 } while (0)
281
282 #define EXPECTEOL \
283 do { \
284 GETTOKEN(lctx->lex, 0, &token, true); \
285 if (token.type != isc_tokentype_eol) { \
286 isc_lex_ungettoken(lctx->lex, &token); \
287 result = DNS_R_EXTRATOKEN; \
288 if (MANYERRS(lctx, result)) { \
289 SETRESULT(lctx, result); \
290 LOGIT(result); \
291 read_till_eol = true; \
292 break; \
293 } else if (result != ISC_R_SUCCESS) \
294 goto log_and_cleanup; \
295 } \
296 } while (0)
297
298 #define MANYERRS(lctx, result) \
299 ((result != ISC_R_SUCCESS) && (result != ISC_R_IOERROR) && \
300 ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
301
302 #define SETRESULT(lctx, r) \
303 do { \
304 if ((lctx)->result == ISC_R_SUCCESS) \
305 (lctx)->result = r; \
306 } while (0)
307
308 #define LOGITFILE(result, filename) \
309 if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
310 result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
311 result == ISC_R_NOPERM) \
312 (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
313 "dns_master_load", source, line, filename, \
314 dns_result_totext(result)); \
315 else \
316 LOGIT(result)
317
318 #define LOGIT(result) \
319 if (result == ISC_R_NOMEMORY) \
320 (*callbacks->error)(callbacks, "dns_master_load: %s", \
321 dns_result_totext(result)); \
322 else \
323 (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
324 "dns_master_load", source, line, \
325 dns_result_totext(result))
326
327 static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
328 static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
329 static dns_name_t const in_addr_arpa =
330 DNS_NAME_INITABSOLUTE(in_addr_arpa_data, in_addr_arpa_offsets);
331
332 static unsigned char ip6_int_data[] = "\003IP6\003INT";
333 static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
334 static dns_name_t const ip6_int = DNS_NAME_INITABSOLUTE(ip6_int_data,
335 ip6_int_offsets);
336
337 static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
338 static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
339 static dns_name_t const ip6_arpa = DNS_NAME_INITABSOLUTE(ip6_arpa_data,
340 ip6_arpa_offsets);
341
342 static inline bool
dns_master_isprimary(dns_loadctx_t * lctx)343 dns_master_isprimary(dns_loadctx_t *lctx) {
344 return ((lctx->options & DNS_MASTER_ZONE) != 0 &&
345 (lctx->options & DNS_MASTER_SLAVE) == 0 &&
346 (lctx->options & DNS_MASTER_KEY) == 0);
347 }
348
349 static inline isc_result_t
gettoken(isc_lex_t * lex,unsigned int options,isc_token_t * token,bool eol,dns_rdatacallbacks_t * callbacks)350 gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, bool eol,
351 dns_rdatacallbacks_t *callbacks) {
352 isc_result_t result;
353
354 options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
355 ISC_LEXOPT_ESCAPE;
356 result = isc_lex_gettoken(lex, options, token);
357 if (result != ISC_R_SUCCESS) {
358 switch (result) {
359 case ISC_R_NOMEMORY:
360 return (ISC_R_NOMEMORY);
361 default:
362 (*callbacks->error)(callbacks,
363 "dns_master_load: %s:%lu:"
364 " isc_lex_gettoken() failed: %s",
365 isc_lex_getsourcename(lex),
366 isc_lex_getsourceline(lex),
367 isc_result_totext(result));
368 return (result);
369 }
370 /*NOTREACHED*/
371 }
372 if (eol != true) {
373 if (token->type == isc_tokentype_eol ||
374 token->type == isc_tokentype_eof) {
375 {
376 unsigned long int line;
377 const char *what;
378 const char *file;
379 file = isc_lex_getsourcename(lex);
380 line = isc_lex_getsourceline(lex);
381 if (token->type == isc_tokentype_eol) {
382 line--;
383 what = "line";
384 } else {
385 what = "file";
386 }
387 (*callbacks->error)(callbacks,
388 "dns_master_load: %s:%lu: "
389 "unexpected end of %s",
390 file, line, what);
391 return (ISC_R_UNEXPECTEDEND);
392 }
393 }
394 }
395 return (ISC_R_SUCCESS);
396 }
397
398 void
dns_loadctx_attach(dns_loadctx_t * source,dns_loadctx_t ** target)399 dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
400 REQUIRE(target != NULL && *target == NULL);
401 REQUIRE(DNS_LCTX_VALID(source));
402
403 isc_refcount_increment(&source->references);
404
405 *target = source;
406 }
407
408 void
dns_loadctx_detach(dns_loadctx_t ** lctxp)409 dns_loadctx_detach(dns_loadctx_t **lctxp) {
410 dns_loadctx_t *lctx;
411
412 REQUIRE(lctxp != NULL);
413 lctx = *lctxp;
414 *lctxp = NULL;
415 REQUIRE(DNS_LCTX_VALID(lctx));
416
417 if (isc_refcount_decrement(&lctx->references) == 1) {
418 loadctx_destroy(lctx);
419 }
420 }
421
422 static void
incctx_destroy(isc_mem_t * mctx,dns_incctx_t * ictx)423 incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
424 dns_incctx_t *parent;
425
426 again:
427 parent = ictx->parent;
428 ictx->parent = NULL;
429
430 isc_mem_put(mctx, ictx, sizeof(*ictx));
431
432 if (parent != NULL) {
433 ictx = parent;
434 goto again;
435 }
436 }
437
438 static void
loadctx_destroy(dns_loadctx_t * lctx)439 loadctx_destroy(dns_loadctx_t *lctx) {
440 REQUIRE(DNS_LCTX_VALID(lctx));
441
442 isc_refcount_destroy(&lctx->references);
443
444 lctx->magic = 0;
445 if (lctx->inc != NULL) {
446 incctx_destroy(lctx->mctx, lctx->inc);
447 }
448
449 if (lctx->f != NULL) {
450 isc_result_t result = isc_stdio_close(lctx->f);
451 if (result != ISC_R_SUCCESS) {
452 UNEXPECTED_ERROR(__FILE__, __LINE__,
453 "isc_stdio_close() failed: %s",
454 isc_result_totext(result));
455 }
456 }
457
458 /* isc_lex_destroy() will close all open streams */
459 if (lctx->lex != NULL && !lctx->keep_lex) {
460 isc_lex_destroy(&lctx->lex);
461 }
462
463 if (lctx->task != NULL) {
464 isc_task_detach(&lctx->task);
465 }
466
467 isc_mem_putanddetach(&lctx->mctx, lctx, sizeof(*lctx));
468 }
469
470 static isc_result_t
incctx_create(isc_mem_t * mctx,dns_name_t * origin,dns_incctx_t ** ictxp)471 incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
472 dns_incctx_t *ictx;
473 isc_region_t r;
474 int i;
475
476 ictx = isc_mem_get(mctx, sizeof(*ictx));
477
478 for (i = 0; i < NBUFS; i++) {
479 dns_fixedname_init(&ictx->fixed[i]);
480 ictx->in_use[i] = false;
481 }
482
483 ictx->origin_in_use = 0;
484 ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
485 ictx->in_use[ictx->origin_in_use] = true;
486 dns_name_toregion(origin, &r);
487 dns_name_fromregion(ictx->origin, &r);
488
489 ictx->glue = NULL;
490 ictx->current = NULL;
491 ictx->glue_in_use = -1;
492 ictx->current_in_use = -1;
493 ictx->parent = NULL;
494 ictx->drop = false;
495 ictx->glue_line = 0;
496 ictx->current_line = 0;
497 ictx->origin_changed = true;
498
499 *ictxp = ictx;
500 return (ISC_R_SUCCESS);
501 }
502
503 static isc_result_t
loadctx_create(dns_masterformat_t format,isc_mem_t * mctx,unsigned int options,uint32_t resign,dns_name_t * top,dns_rdataclass_t zclass,dns_name_t * origin,dns_rdatacallbacks_t * callbacks,isc_task_t * task,dns_loaddonefunc_t done,void * done_arg,dns_masterincludecb_t include_cb,void * include_arg,isc_lex_t * lex,dns_loadctx_t ** lctxp)504 loadctx_create(dns_masterformat_t format, isc_mem_t *mctx, unsigned int options,
505 uint32_t resign, dns_name_t *top, dns_rdataclass_t zclass,
506 dns_name_t *origin, dns_rdatacallbacks_t *callbacks,
507 isc_task_t *task, dns_loaddonefunc_t done, void *done_arg,
508 dns_masterincludecb_t include_cb, void *include_arg,
509 isc_lex_t *lex, dns_loadctx_t **lctxp) {
510 dns_loadctx_t *lctx;
511 isc_result_t result;
512 isc_region_t r;
513 isc_lexspecials_t specials;
514
515 REQUIRE(lctxp != NULL && *lctxp == NULL);
516 REQUIRE(callbacks != NULL);
517 REQUIRE(callbacks->add != NULL);
518 REQUIRE(callbacks->error != NULL);
519 REQUIRE(callbacks->warn != NULL);
520 REQUIRE(mctx != NULL);
521 REQUIRE(dns_name_isabsolute(top));
522 REQUIRE(dns_name_isabsolute(origin));
523 REQUIRE((task == NULL && done == NULL) ||
524 (task != NULL && done != NULL));
525
526 lctx = isc_mem_get(mctx, sizeof(*lctx));
527
528 lctx->inc = NULL;
529 result = incctx_create(mctx, origin, &lctx->inc);
530 if (result != ISC_R_SUCCESS) {
531 goto cleanup_ctx;
532 }
533
534 lctx->maxttl = 0;
535
536 lctx->format = format;
537 switch (format) {
538 case dns_masterformat_text:
539 lctx->openfile = openfile_text;
540 lctx->load = load_text;
541 break;
542 case dns_masterformat_raw:
543 lctx->openfile = openfile_raw;
544 lctx->load = load_raw;
545 break;
546 case dns_masterformat_map:
547 lctx->openfile = openfile_map;
548 lctx->load = load_map;
549 break;
550 default:
551 INSIST(0);
552 ISC_UNREACHABLE();
553 }
554
555 if (lex != NULL) {
556 lctx->lex = lex;
557 lctx->keep_lex = true;
558 } else {
559 lctx->lex = NULL;
560 result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
561 if (result != ISC_R_SUCCESS) {
562 goto cleanup_inc;
563 }
564 lctx->keep_lex = false;
565 /*
566 * If specials change update dns_test_rdatafromstring()
567 * in lib/dns/tests/dnstest.c.
568 */
569 memset(specials, 0, sizeof(specials));
570 specials[0] = 1;
571 specials['('] = 1;
572 specials[')'] = 1;
573 specials['"'] = 1;
574 isc_lex_setspecials(lctx->lex, specials);
575 isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
576 }
577
578 lctx->ttl_known = ((options & DNS_MASTER_NOTTL) != 0);
579 lctx->ttl = 0;
580 lctx->default_ttl_known = lctx->ttl_known;
581 lctx->default_ttl = 0;
582 lctx->warn_1035 = true; /* XXX Argument? */
583 lctx->warn_tcr = true; /* XXX Argument? */
584 lctx->warn_sigexpired = true; /* XXX Argument? */
585 lctx->options = options;
586 lctx->seen_include = false;
587 lctx->zclass = zclass;
588 lctx->resign = resign;
589 lctx->result = ISC_R_SUCCESS;
590 lctx->include_cb = include_cb;
591 lctx->include_arg = include_arg;
592 isc_stdtime_get(&lctx->now);
593
594 lctx->top = dns_fixedname_initname(&lctx->fixed_top);
595 dns_name_toregion(top, &r);
596 dns_name_fromregion(lctx->top, &r);
597
598 lctx->f = NULL;
599 lctx->first = true;
600 dns_master_initrawheader(&lctx->header);
601
602 lctx->loop_cnt = (done != NULL) ? 100 : 0;
603 lctx->callbacks = callbacks;
604 lctx->task = NULL;
605 if (task != NULL) {
606 isc_task_attach(task, &lctx->task);
607 }
608 lctx->done = done;
609 lctx->done_arg = done_arg;
610 atomic_init(&lctx->canceled, false);
611 lctx->mctx = NULL;
612 isc_mem_attach(mctx, &lctx->mctx);
613
614 isc_refcount_init(&lctx->references, 1); /* Implicit attach. */
615
616 lctx->magic = DNS_LCTX_MAGIC;
617 *lctxp = lctx;
618 return (ISC_R_SUCCESS);
619
620 cleanup_inc:
621 incctx_destroy(mctx, lctx->inc);
622 cleanup_ctx:
623 isc_mem_put(mctx, lctx, sizeof(*lctx));
624 return (result);
625 }
626
627 static const char *hex = "0123456789abcdef0123456789ABCDEF";
628
629 /*%
630 * Convert value into a nibble sequence from least significant to most
631 * significant nibble. Zero fill upper most significant nibbles if
632 * required to make the width.
633 *
634 * Returns the number of characters that should have been written without
635 * counting the terminating NUL.
636 */
637 static unsigned int
nibbles(char * numbuf,size_t length,unsigned int width,char mode,int value)638 nibbles(char *numbuf, size_t length, unsigned int width, char mode, int value) {
639 unsigned int count = 0;
640
641 /*
642 * This reserve space for the NUL string terminator.
643 */
644 if (length > 0U) {
645 *numbuf = '\0';
646 length--;
647 }
648 do {
649 char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
650 value >>= 4;
651 if (length > 0U) {
652 *numbuf++ = val;
653 *numbuf = '\0';
654 length--;
655 }
656 if (width > 0) {
657 width--;
658 }
659 count++;
660 /*
661 * If width is non zero then we need to add a label separator.
662 * If value is non zero then we need to add another label and
663 * that requires a label separator.
664 */
665 if (width > 0 || value != 0) {
666 if (length > 0U) {
667 *numbuf++ = '.';
668 *numbuf = '\0';
669 length--;
670 }
671 if (width > 0) {
672 width--;
673 }
674 count++;
675 }
676 } while (value != 0 || width > 0);
677 return (count);
678 }
679
680 static isc_result_t
genname(char * name,int it,char * buffer,size_t length)681 genname(char *name, int it, char *buffer, size_t length) {
682 char fmt[sizeof("%04000000000d")];
683 char numbuf[128];
684 char *cp;
685 char mode[2];
686 int delta = 0;
687 isc_textregion_t r;
688 unsigned int n;
689 unsigned int width;
690 bool nibblemode;
691
692 r.base = buffer;
693 r.length = (unsigned int)length;
694
695 while (*name != '\0') {
696 if (*name == '$') {
697 name++;
698 if (*name == '$') {
699 if (r.length == 0) {
700 return (ISC_R_NOSPACE);
701 }
702 r.base[0] = *name++;
703 isc_textregion_consume(&r, 1);
704 continue;
705 }
706 nibblemode = false;
707 strlcpy(fmt, "%d", sizeof(fmt));
708 /* Get format specifier. */
709 if (*name == '{') {
710 n = sscanf(name, "{%d,%u,%1[doxXnN]}", &delta,
711 &width, mode);
712 switch (n) {
713 case 1:
714 break;
715 case 2:
716 n = snprintf(fmt, sizeof(fmt), "%%0%ud",
717 width);
718 break;
719 case 3:
720 if (mode[0] == 'n' || mode[0] == 'N') {
721 nibblemode = true;
722 }
723 n = snprintf(fmt, sizeof(fmt),
724 "%%0%u%c", width, mode[0]);
725 break;
726 default:
727 return (DNS_R_SYNTAX);
728 }
729 if (n >= sizeof(fmt)) {
730 return (ISC_R_NOSPACE);
731 }
732 /* Skip past closing brace. */
733 while (*name != '\0' && *name++ != '}') {
734 continue;
735 }
736 }
737 if (nibblemode) {
738 n = nibbles(numbuf, sizeof(numbuf), width,
739 mode[0], it + delta);
740 } else {
741 n = snprintf(numbuf, sizeof(numbuf), fmt,
742 it + delta);
743 }
744 if (n >= sizeof(numbuf)) {
745 return (ISC_R_NOSPACE);
746 }
747 cp = numbuf;
748 while (*cp != '\0') {
749 if (r.length == 0) {
750 return (ISC_R_NOSPACE);
751 }
752 r.base[0] = *cp++;
753 isc_textregion_consume(&r, 1);
754 }
755 } else if (*name == '\\') {
756 if (r.length == 0) {
757 return (ISC_R_NOSPACE);
758 }
759 r.base[0] = *name++;
760 isc_textregion_consume(&r, 1);
761 if (*name == '\0') {
762 continue;
763 }
764 if (r.length == 0) {
765 return (ISC_R_NOSPACE);
766 }
767 r.base[0] = *name++;
768 isc_textregion_consume(&r, 1);
769 } else {
770 if (r.length == 0) {
771 return (ISC_R_NOSPACE);
772 }
773 r.base[0] = *name++;
774 isc_textregion_consume(&r, 1);
775 }
776 }
777 if (r.length == 0) {
778 return (ISC_R_NOSPACE);
779 }
780 r.base[0] = '\0';
781 return (ISC_R_SUCCESS);
782 }
783
784 static isc_result_t
generate(dns_loadctx_t * lctx,char * range,char * lhs,char * gtype,char * rhs,const char * source,unsigned int line)785 generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
786 const char *source, unsigned int line) {
787 char *target_mem = NULL;
788 char *lhsbuf = NULL;
789 char *rhsbuf = NULL;
790 dns_fixedname_t ownerfixed;
791 dns_name_t *owner;
792 dns_rdata_t rdata = DNS_RDATA_INIT;
793 dns_rdatacallbacks_t *callbacks;
794 dns_rdatalist_t rdatalist;
795 dns_rdatatype_t type;
796 rdatalist_head_t head;
797 int target_size = MINTSIZ; /* only one rdata at a time */
798 isc_buffer_t buffer;
799 isc_buffer_t target;
800 isc_result_t result;
801 isc_textregion_t r;
802 int i, n, start, stop, step = 0;
803 dns_incctx_t *ictx;
804 char dummy[2];
805
806 ictx = lctx->inc;
807 callbacks = lctx->callbacks;
808 owner = dns_fixedname_initname(&ownerfixed);
809 ISC_LIST_INIT(head);
810
811 target_mem = isc_mem_get(lctx->mctx, target_size);
812 rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
813 lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
814 if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
815 result = ISC_R_NOMEMORY;
816 goto error_cleanup;
817 }
818 isc_buffer_init(&target, target_mem, target_size);
819
820 n = sscanf(range, "%d-%d%1[/]%d", &start, &stop, dummy, &step);
821 if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
822 (n == 4 && step < 1) || (stop < start))
823 {
824 (*callbacks->error)(callbacks, "%s: %s:%lu: invalid range '%s'",
825 "$GENERATE", source, line, range);
826 result = DNS_R_SYNTAX;
827 goto insist_cleanup;
828 }
829 if (n == 2) {
830 step = 1;
831 }
832
833 /*
834 * Get type.
835 */
836 r.base = gtype;
837 r.length = strlen(gtype);
838 result = dns_rdatatype_fromtext(&type, &r);
839 if (result != ISC_R_SUCCESS) {
840 (*callbacks->error)(callbacks,
841 "%s: %s:%lu: unknown RR type '%s'",
842 "$GENERATE", source, line, gtype);
843 goto insist_cleanup;
844 }
845
846 /*
847 * RFC2930: TKEY and TSIG are not allowed to be loaded
848 * from master files.
849 */
850 if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
851 (*callbacks->error)(callbacks, "%s: %s:%lu: meta RR type '%s'",
852 "$GENERATE", source, line, gtype);
853 result = DNS_R_METATYPE;
854 goto insist_cleanup;
855 }
856
857 for (i = start; i <= stop; i += step) {
858 result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
859 if (result != ISC_R_SUCCESS) {
860 goto error_cleanup;
861 }
862 result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
863 if (result != ISC_R_SUCCESS) {
864 goto error_cleanup;
865 }
866
867 isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
868 isc_buffer_add(&buffer, strlen(lhsbuf));
869 isc_buffer_setactive(&buffer, strlen(lhsbuf));
870 result = dns_name_fromtext(owner, &buffer, ictx->origin, 0,
871 NULL);
872 if (result != ISC_R_SUCCESS) {
873 goto error_cleanup;
874 }
875
876 if (dns_master_isprimary(lctx) &&
877 !dns_name_issubdomain(owner, lctx->top)) {
878 char namebuf[DNS_NAME_FORMATSIZE];
879 dns_name_format(owner, namebuf, sizeof(namebuf));
880 /*
881 * Ignore out-of-zone data.
882 */
883 (*callbacks->warn)(callbacks,
884 "%s:%lu: "
885 "ignoring out-of-zone data (%s)",
886 source, line, namebuf);
887 continue;
888 }
889
890 isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
891 isc_buffer_add(&buffer, strlen(rhsbuf));
892 isc_buffer_setactive(&buffer, strlen(rhsbuf));
893
894 result = isc_lex_openbuffer(lctx->lex, &buffer);
895 if (result != ISC_R_SUCCESS) {
896 goto error_cleanup;
897 }
898
899 isc_buffer_init(&target, target_mem, target_size);
900 result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
901 lctx->lex, ictx->origin, 0,
902 lctx->mctx, &target, callbacks);
903 RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
904 if (result != ISC_R_SUCCESS) {
905 goto error_cleanup;
906 }
907
908 dns_rdatalist_init(&rdatalist);
909 rdatalist.type = type;
910 rdatalist.rdclass = lctx->zclass;
911 rdatalist.ttl = lctx->ttl;
912 ISC_LIST_PREPEND(head, &rdatalist, link);
913 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
914 result = commit(callbacks, lctx, &head, owner, source, line);
915 ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
916 if (result != ISC_R_SUCCESS) {
917 goto error_cleanup;
918 }
919 dns_rdata_reset(&rdata);
920 }
921 result = ISC_R_SUCCESS;
922 goto cleanup;
923
924 error_cleanup:
925 if (result == ISC_R_NOMEMORY) {
926 (*callbacks->error)(callbacks, "$GENERATE: %s",
927 dns_result_totext(result));
928 } else {
929 (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s", source,
930 line, dns_result_totext(result));
931 }
932
933 insist_cleanup:
934 INSIST(result != ISC_R_SUCCESS);
935
936 cleanup:
937 if (target_mem != NULL) {
938 isc_mem_put(lctx->mctx, target_mem, target_size);
939 }
940 if (lhsbuf != NULL) {
941 isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
942 }
943 if (rhsbuf != NULL) {
944 isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
945 }
946 return (result);
947 }
948
949 static void
limit_ttl(dns_rdatacallbacks_t * callbacks,const char * source,unsigned int line,uint32_t * ttlp)950 limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source,
951 unsigned int line, uint32_t *ttlp) {
952 if (*ttlp > 0x7fffffffUL) {
953 (callbacks->warn)(callbacks,
954 "%s: %s:%lu: "
955 "$TTL %lu > MAXTTL, "
956 "setting $TTL to 0",
957 "dns_master_load", source, line, *ttlp);
958 *ttlp = 0;
959 }
960 }
961
962 static isc_result_t
check_ns(dns_loadctx_t * lctx,isc_token_t * token,const char * source,unsigned long line)963 check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
964 unsigned long line) {
965 char *tmp = NULL;
966 isc_result_t result = ISC_R_SUCCESS;
967 void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
968
969 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
970 callback = lctx->callbacks->error;
971 } else {
972 callback = lctx->callbacks->warn;
973 }
974
975 if (token->type == isc_tokentype_string) {
976 struct in_addr addr;
977 struct in6_addr addr6;
978
979 tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
980 /*
981 * Catch both "1.2.3.4" and "1.2.3.4."
982 */
983 if (tmp[strlen(tmp) - 1] == '.') {
984 tmp[strlen(tmp) - 1] = '\0';
985 }
986 if (inet_pton(AF_INET, tmp, &addr) == 1 ||
987 inet_pton(AF_INET6, tmp, &addr6) == 1)
988 {
989 result = DNS_R_NSISADDRESS;
990 }
991 }
992 if (result != ISC_R_SUCCESS) {
993 (*callback)(lctx->callbacks,
994 "%s:%lu: NS record '%s' "
995 "appears to be an address",
996 source, line, DNS_AS_STR(*token));
997 }
998 if (tmp != NULL) {
999 isc_mem_free(lctx->mctx, tmp);
1000 }
1001 return (result);
1002 }
1003
1004 static void
check_wildcard(dns_incctx_t * ictx,const char * source,unsigned long line,dns_rdatacallbacks_t * callbacks)1005 check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
1006 dns_rdatacallbacks_t *callbacks) {
1007 dns_name_t *name;
1008
1009 name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
1010 if (dns_name_internalwildcard(name)) {
1011 char namebuf[DNS_NAME_FORMATSIZE];
1012
1013 dns_name_format(name, namebuf, sizeof(namebuf));
1014 (*callbacks->warn)(callbacks,
1015 "%s:%lu: warning: ownername "
1016 "'%s' contains an non-terminal wildcard",
1017 source, line, namebuf);
1018 }
1019 }
1020
1021 static isc_result_t
openfile_text(dns_loadctx_t * lctx,const char * master_file)1022 openfile_text(dns_loadctx_t *lctx, const char *master_file) {
1023 return (isc_lex_openfile(lctx->lex, master_file));
1024 }
1025
1026 static int
find_free_name(dns_incctx_t * incctx)1027 find_free_name(dns_incctx_t *incctx) {
1028 int i;
1029
1030 for (i = 0; i < (NBUFS - 1); i++) {
1031 if (!incctx->in_use[i]) {
1032 break;
1033 }
1034 }
1035 INSIST(!incctx->in_use[i]);
1036 return (i);
1037 }
1038
1039 static isc_result_t
load_text(dns_loadctx_t * lctx)1040 load_text(dns_loadctx_t *lctx) {
1041 dns_rdataclass_t rdclass;
1042 dns_rdatatype_t type, covers;
1043 uint32_t ttl_offset = 0;
1044 dns_name_t *new_name;
1045 bool current_has_delegation = false;
1046 bool done = false;
1047 bool finish_origin = false;
1048 bool finish_include = false;
1049 bool read_till_eol = false;
1050 bool initialws;
1051 char *include_file = NULL;
1052 isc_token_t token;
1053 isc_result_t result = ISC_R_UNEXPECTED;
1054 rdatalist_head_t glue_list;
1055 rdatalist_head_t current_list;
1056 dns_rdatalist_t *this;
1057 dns_rdatalist_t *rdatalist = NULL;
1058 dns_rdatalist_t *new_rdatalist;
1059 int rdlcount = 0;
1060 int rdlcount_save = 0;
1061 int rdatalist_size = 0;
1062 isc_buffer_t buffer;
1063 isc_buffer_t target;
1064 isc_buffer_t target_ft;
1065 isc_buffer_t target_save;
1066 dns_rdata_t *rdata = NULL;
1067 dns_rdata_t *new_rdata;
1068 int rdcount = 0;
1069 int rdcount_save = 0;
1070 int rdata_size = 0;
1071 unsigned char *target_mem = NULL;
1072 int target_size = TSIZ;
1073 int new_in_use;
1074 unsigned int loop_cnt = 0;
1075 isc_mem_t *mctx;
1076 dns_rdatacallbacks_t *callbacks;
1077 dns_incctx_t *ictx;
1078 char *range = NULL;
1079 char *lhs = NULL;
1080 char *gtype = NULL;
1081 char *rhs = NULL;
1082 const char *source = "";
1083 unsigned long line = 0;
1084 bool explicit_ttl;
1085 char classname1[DNS_RDATACLASS_FORMATSIZE];
1086 char classname2[DNS_RDATACLASS_FORMATSIZE];
1087 unsigned int options = 0;
1088
1089 REQUIRE(DNS_LCTX_VALID(lctx));
1090 callbacks = lctx->callbacks;
1091 mctx = lctx->mctx;
1092 ictx = lctx->inc;
1093
1094 ISC_LIST_INIT(glue_list);
1095 ISC_LIST_INIT(current_list);
1096
1097 /*
1098 * Allocate target_size of buffer space. This is greater than twice
1099 * the maximum individual RR data size.
1100 */
1101 target_mem = isc_mem_get(mctx, target_size);
1102 isc_buffer_init(&target, target_mem, target_size);
1103 target_save = target;
1104
1105 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1106 options |= DNS_RDATA_CHECKNAMES;
1107 }
1108 if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1109 options |= DNS_RDATA_CHECKNAMESFAIL;
1110 }
1111 if ((lctx->options & DNS_MASTER_CHECKMX) != 0) {
1112 options |= DNS_RDATA_CHECKMX;
1113 }
1114 if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0) {
1115 options |= DNS_RDATA_CHECKMXFAIL;
1116 }
1117 source = isc_lex_getsourcename(lctx->lex);
1118 do {
1119 initialws = false;
1120 line = isc_lex_getsourceline(lctx->lex);
1121 GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1122 &token, true);
1123 line = isc_lex_getsourceline(lctx->lex);
1124
1125 if (token.type == isc_tokentype_eof) {
1126 if (read_till_eol) {
1127 WARNUNEXPECTEDEOF(lctx->lex);
1128 }
1129 /* Pop the include stack? */
1130 if (ictx->parent != NULL) {
1131 COMMITALL;
1132 lctx->inc = ictx->parent;
1133 ictx->parent = NULL;
1134 incctx_destroy(lctx->mctx, ictx);
1135 RUNTIME_CHECK(isc_lex_close(lctx->lex) ==
1136 ISC_R_SUCCESS);
1137 line = isc_lex_getsourceline(lctx->lex);
1138 POST(line);
1139 source = isc_lex_getsourcename(lctx->lex);
1140 ictx = lctx->inc;
1141 continue;
1142 }
1143 done = true;
1144 continue;
1145 }
1146
1147 if (token.type == isc_tokentype_eol) {
1148 read_till_eol = false;
1149 continue; /* blank line */
1150 }
1151
1152 if (read_till_eol) {
1153 continue;
1154 }
1155
1156 if (token.type == isc_tokentype_initialws) {
1157 /*
1158 * Still working on the same name.
1159 */
1160 initialws = true;
1161 } else if (token.type == isc_tokentype_string ||
1162 token.type == isc_tokentype_qstring)
1163 {
1164 /*
1165 * "$" Support.
1166 *
1167 * "$ORIGIN" and "$INCLUDE" can both take domain names.
1168 * The processing of "$ORIGIN" and "$INCLUDE" extends
1169 * across the normal domain name processing.
1170 */
1171
1172 if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1173 GETTOKEN(lctx->lex, 0, &token, false);
1174 finish_origin = true;
1175 } else if (strcasecmp(DNS_AS_STR(token), "$TTL") == 0) {
1176 GETTOKENERR(lctx->lex, 0, &token, false,
1177 lctx->ttl = 0;
1178 lctx->default_ttl_known = true;);
1179 result = dns_ttl_fromtext(
1180 &token.value.as_textregion, &lctx->ttl);
1181 if (MANYERRS(lctx, result)) {
1182 SETRESULT(lctx, result);
1183 lctx->ttl = 0;
1184 } else if (result != ISC_R_SUCCESS) {
1185 goto insist_and_cleanup;
1186 }
1187 limit_ttl(callbacks, source, line, &lctx->ttl);
1188 lctx->default_ttl = lctx->ttl;
1189 lctx->default_ttl_known = true;
1190 EXPECTEOL;
1191 continue;
1192 } else if (strcasecmp(DNS_AS_STR(token), "$INCLUDE") ==
1193 0) {
1194 COMMITALL;
1195 if ((lctx->options & DNS_MASTER_NOINCLUDE) != 0)
1196 {
1197 (callbacks->error)(callbacks,
1198 "%s: %s:%lu: "
1199 "$INCLUDE not "
1200 "allowed",
1201 "dns_master_load",
1202 source, line);
1203 result = DNS_R_REFUSED;
1204 goto insist_and_cleanup;
1205 }
1206 if (ttl_offset != 0) {
1207 (callbacks->error)(callbacks,
1208 "%s: %s:%lu: "
1209 "$INCLUDE "
1210 "may not be used "
1211 "with $DATE",
1212 "dns_master_load",
1213 source, line);
1214 result = DNS_R_SYNTAX;
1215 goto insist_and_cleanup;
1216 }
1217 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1218 false);
1219 if (include_file != NULL) {
1220 isc_mem_free(mctx, include_file);
1221 }
1222 include_file =
1223 isc_mem_strdup(mctx, DNS_AS_STR(token));
1224 GETTOKEN(lctx->lex, 0, &token, true);
1225
1226 if (token.type == isc_tokentype_eol ||
1227 token.type == isc_tokentype_eof) {
1228 if (token.type == isc_tokentype_eof) {
1229 WARNUNEXPECTEDEOF(lctx->lex);
1230 }
1231 /*
1232 * No origin field.
1233 */
1234 result = pushfile(include_file,
1235 ictx->origin, lctx);
1236 if (MANYERRS(lctx, result)) {
1237 SETRESULT(lctx, result);
1238 LOGITFILE(result, include_file);
1239 continue;
1240 } else if (result != ISC_R_SUCCESS) {
1241 LOGITFILE(result, include_file);
1242 goto insist_and_cleanup;
1243 }
1244 ictx = lctx->inc;
1245 source = isc_lex_getsourcename(
1246 lctx->lex);
1247 line = isc_lex_getsourceline(lctx->lex);
1248 POST(line);
1249 continue;
1250 }
1251 /*
1252 * There is an origin field. Fall through
1253 * to domain name processing code and do
1254 * the actual inclusion later.
1255 */
1256 finish_include = true;
1257 } else if (strcasecmp(DNS_AS_STR(token), "$DATE") == 0)
1258 {
1259 int64_t dump_time64;
1260 isc_stdtime_t dump_time, current_time;
1261 GETTOKEN(lctx->lex, 0, &token, false);
1262 isc_stdtime_get(¤t_time);
1263 result = dns_time64_fromtext(DNS_AS_STR(token),
1264 &dump_time64);
1265 if (MANYERRS(lctx, result)) {
1266 SETRESULT(lctx, result);
1267 LOGIT(result);
1268 dump_time64 = 0;
1269 } else if (result != ISC_R_SUCCESS) {
1270 goto log_and_cleanup;
1271 }
1272 dump_time = (isc_stdtime_t)dump_time64;
1273 if (dump_time != dump_time64) {
1274 UNEXPECTED_ERROR(__FILE__, __LINE__,
1275 "%s: %s:%lu: $DATE "
1276 "outside epoch",
1277 "dns_master_load",
1278 source, line);
1279 result = ISC_R_UNEXPECTED;
1280 goto insist_and_cleanup;
1281 }
1282 if (dump_time > current_time) {
1283 UNEXPECTED_ERROR(__FILE__, __LINE__,
1284 "%s: %s:%lu: "
1285 "$DATE in future, "
1286 "using current date",
1287 "dns_master_load",
1288 source, line);
1289 dump_time = current_time;
1290 }
1291 ttl_offset = current_time - dump_time;
1292 EXPECTEOL;
1293 continue;
1294 } else if (strcasecmp(DNS_AS_STR(token), "$GENERATE") ==
1295 0) {
1296 /*
1297 * Lazy cleanup.
1298 */
1299 if (range != NULL) {
1300 isc_mem_free(mctx, range);
1301 }
1302 if (lhs != NULL) {
1303 isc_mem_free(mctx, lhs);
1304 }
1305 if (gtype != NULL) {
1306 isc_mem_free(mctx, gtype);
1307 }
1308 if (rhs != NULL) {
1309 isc_mem_free(mctx, rhs);
1310 }
1311 range = lhs = gtype = rhs = NULL;
1312 /* RANGE */
1313 GETTOKEN(lctx->lex, 0, &token, false);
1314 range = isc_mem_strdup(mctx, DNS_AS_STR(token));
1315 /* LHS */
1316 GETTOKEN(lctx->lex, 0, &token, false);
1317 lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1318 rdclass = 0;
1319 explicit_ttl = false;
1320 /* CLASS? */
1321 GETTOKEN(lctx->lex, 0, &token, false);
1322 if (dns_rdataclass_fromtext(
1323 &rdclass,
1324 &token.value.as_textregion) ==
1325 ISC_R_SUCCESS)
1326 {
1327 GETTOKEN(lctx->lex, 0, &token, false);
1328 }
1329 /* TTL? */
1330 if (dns_ttl_fromtext(&token.value.as_textregion,
1331 &lctx->ttl) ==
1332 ISC_R_SUCCESS) {
1333 limit_ttl(callbacks, source, line,
1334 &lctx->ttl);
1335 lctx->ttl_known = true;
1336 explicit_ttl = true;
1337 GETTOKEN(lctx->lex, 0, &token, false);
1338 }
1339 /* CLASS? */
1340 if (rdclass == 0 &&
1341 dns_rdataclass_fromtext(
1342 &rdclass,
1343 &token.value.as_textregion) ==
1344 ISC_R_SUCCESS)
1345 {
1346 GETTOKEN(lctx->lex, 0, &token, false);
1347 }
1348 /* TYPE */
1349 gtype = isc_mem_strdup(mctx, DNS_AS_STR(token));
1350 /* RHS */
1351 GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1352 false);
1353 rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1354 if (!lctx->ttl_known &&
1355 !lctx->default_ttl_known) {
1356 (*callbacks->error)(callbacks,
1357 "%s: %s:%lu: no "
1358 "TTL specified",
1359 "dns_master_load",
1360 source, line);
1361 result = DNS_R_NOTTL;
1362 if (MANYERRS(lctx, result)) {
1363 SETRESULT(lctx, result);
1364 lctx->ttl = 0;
1365 } else {
1366 goto insist_and_cleanup;
1367 }
1368 } else if (!explicit_ttl &&
1369 lctx->default_ttl_known) {
1370 lctx->ttl = lctx->default_ttl;
1371 }
1372 /*
1373 * If the class specified does not match the
1374 * zone's class print out a error message and
1375 * exit.
1376 */
1377 if (rdclass != 0 && rdclass != lctx->zclass) {
1378 goto bad_class;
1379 }
1380 result = generate(lctx, range, lhs, gtype, rhs,
1381 source, line);
1382 if (MANYERRS(lctx, result)) {
1383 SETRESULT(lctx, result);
1384 } else if (result != ISC_R_SUCCESS) {
1385 goto insist_and_cleanup;
1386 }
1387 EXPECTEOL;
1388 continue;
1389 } else if (strncasecmp(DNS_AS_STR(token), "$", 1) == 0)
1390 {
1391 (callbacks->error)(callbacks,
1392 "%s: %s:%lu: "
1393 "unknown $ directive '%s'",
1394 "dns_master_load", source,
1395 line, DNS_AS_STR(token));
1396 result = DNS_R_SYNTAX;
1397 if (MANYERRS(lctx, result)) {
1398 SETRESULT(lctx, result);
1399 } else {
1400 goto insist_and_cleanup;
1401 }
1402 }
1403
1404 /*
1405 * Normal processing resumes.
1406 */
1407 new_in_use = find_free_name(ictx);
1408 new_name = dns_fixedname_initname(
1409 &ictx->fixed[new_in_use]);
1410 isc_buffer_init(&buffer, token.value.as_region.base,
1411 token.value.as_region.length);
1412 isc_buffer_add(&buffer, token.value.as_region.length);
1413 isc_buffer_setactive(&buffer,
1414 token.value.as_region.length);
1415 result = dns_name_fromtext(new_name, &buffer,
1416 ictx->origin, 0, NULL);
1417 if (MANYERRS(lctx, result)) {
1418 SETRESULT(lctx, result);
1419 LOGIT(result);
1420 read_till_eol = true;
1421 continue;
1422 } else if (result != ISC_R_SUCCESS) {
1423 goto log_and_cleanup;
1424 }
1425
1426 /*
1427 * Finish $ORIGIN / $INCLUDE processing if required.
1428 */
1429 if (finish_origin) {
1430 if (ictx->origin_in_use != -1) {
1431 ictx->in_use[ictx->origin_in_use] =
1432 false;
1433 }
1434 ictx->origin_in_use = new_in_use;
1435 ictx->in_use[ictx->origin_in_use] = true;
1436 ictx->origin = new_name;
1437 ictx->origin_changed = true;
1438 finish_origin = false;
1439 EXPECTEOL;
1440 continue;
1441 }
1442 if (finish_include) {
1443 finish_include = false;
1444 EXPECTEOL;
1445 result = pushfile(include_file, new_name, lctx);
1446 if (MANYERRS(lctx, result)) {
1447 SETRESULT(lctx, result);
1448 LOGITFILE(result, include_file);
1449 continue;
1450 } else if (result != ISC_R_SUCCESS) {
1451 LOGITFILE(result, include_file);
1452 goto insist_and_cleanup;
1453 }
1454 ictx = lctx->inc;
1455 ictx->origin_changed = true;
1456 source = isc_lex_getsourcename(lctx->lex);
1457 line = isc_lex_getsourceline(lctx->lex);
1458 POST(line);
1459 continue;
1460 }
1461
1462 /*
1463 * "$" Processing Finished
1464 */
1465
1466 /*
1467 * If we are processing glue and the new name does
1468 * not match the current glue name, commit the glue
1469 * and pop stacks leaving us in 'normal' processing
1470 * state. Linked lists are undone by commit().
1471 */
1472 if (ictx->glue != NULL &&
1473 !dns_name_caseequal(ictx->glue, new_name)) {
1474 result = commit(callbacks, lctx, &glue_list,
1475 ictx->glue, source,
1476 ictx->glue_line);
1477 if (MANYERRS(lctx, result)) {
1478 SETRESULT(lctx, result);
1479 } else if (result != ISC_R_SUCCESS) {
1480 goto insist_and_cleanup;
1481 }
1482 if (ictx->glue_in_use != -1) {
1483 ictx->in_use[ictx->glue_in_use] = false;
1484 }
1485 ictx->glue_in_use = -1;
1486 ictx->glue = NULL;
1487 rdcount = rdcount_save;
1488 rdlcount = rdlcount_save;
1489 target = target_save;
1490 }
1491
1492 /*
1493 * If we are in 'normal' processing state and the new
1494 * name does not match the current name, see if the
1495 * new name is for glue and treat it as such,
1496 * otherwise we have a new name so commit what we
1497 * have.
1498 */
1499 if ((ictx->glue == NULL) &&
1500 (ictx->current == NULL ||
1501 !dns_name_caseequal(ictx->current, new_name)))
1502 {
1503 if (current_has_delegation &&
1504 is_glue(¤t_list, new_name)) {
1505 rdcount_save = rdcount;
1506 rdlcount_save = rdlcount;
1507 target_save = target;
1508 ictx->glue = new_name;
1509 ictx->glue_in_use = new_in_use;
1510 ictx->in_use[ictx->glue_in_use] = true;
1511 } else {
1512 result = commit(callbacks, lctx,
1513 ¤t_list,
1514 ictx->current, source,
1515 ictx->current_line);
1516 if (MANYERRS(lctx, result)) {
1517 SETRESULT(lctx, result);
1518 } else if (result != ISC_R_SUCCESS) {
1519 goto insist_and_cleanup;
1520 }
1521 rdcount = 0;
1522 rdlcount = 0;
1523 if (ictx->current_in_use != -1) {
1524 ictx->in_use
1525 [ictx->current_in_use] =
1526 false;
1527 }
1528 ictx->current_in_use = new_in_use;
1529 ictx->in_use[ictx->current_in_use] =
1530 true;
1531 ictx->current = new_name;
1532 current_has_delegation = false;
1533 isc_buffer_init(&target, target_mem,
1534 target_size);
1535 }
1536 /*
1537 * Check for internal wildcards.
1538 */
1539 if ((lctx->options &
1540 DNS_MASTER_CHECKWILDCARD) != 0) {
1541 check_wildcard(ictx, source, line,
1542 callbacks);
1543 }
1544 }
1545 if (dns_master_isprimary(lctx) &&
1546 !dns_name_issubdomain(new_name, lctx->top)) {
1547 char namebuf[DNS_NAME_FORMATSIZE];
1548 dns_name_format(new_name, namebuf,
1549 sizeof(namebuf));
1550 /*
1551 * Ignore out-of-zone data.
1552 */
1553 (*callbacks->warn)(callbacks,
1554 "%s:%lu: "
1555 "ignoring out-of-zone data "
1556 "(%s)",
1557 source, line, namebuf);
1558 ictx->drop = true;
1559 } else {
1560 ictx->drop = false;
1561 }
1562 } else {
1563 UNEXPECTED_ERROR(__FILE__, __LINE__,
1564 "%s:%lu: isc_lex_gettoken() returned "
1565 "unexpected token type (%d)",
1566 source, line, token.type);
1567 result = ISC_R_UNEXPECTED;
1568 if (MANYERRS(lctx, result)) {
1569 SETRESULT(lctx, result);
1570 LOGIT(result);
1571 continue;
1572 } else {
1573 goto insist_and_cleanup;
1574 }
1575 }
1576
1577 /*
1578 * Find TTL, class and type. Both TTL and class are optional
1579 * and may occur in any order if they exist. TTL and class
1580 * come before type which must exist.
1581 *
1582 * [<TTL>] [<class>] <type> <RDATA>
1583 * [<class>] [<TTL>] <type> <RDATA>
1584 */
1585
1586 type = 0;
1587 rdclass = 0;
1588
1589 GETTOKEN(lctx->lex, 0, &token, initialws);
1590
1591 if (initialws) {
1592 if (token.type == isc_tokentype_eol) {
1593 read_till_eol = false;
1594 continue; /* blank line */
1595 }
1596
1597 if (token.type == isc_tokentype_eof) {
1598 WARNUNEXPECTEDEOF(lctx->lex);
1599 read_till_eol = false;
1600 isc_lex_ungettoken(lctx->lex, &token);
1601 continue;
1602 }
1603
1604 if (ictx->current == NULL) {
1605 (*callbacks->error)(callbacks,
1606 "%s:%lu: no current owner "
1607 "name",
1608 source, line);
1609 result = DNS_R_NOOWNER;
1610 if (MANYERRS(lctx, result)) {
1611 SETRESULT(lctx, result);
1612 read_till_eol = true;
1613 continue;
1614 } else {
1615 goto insist_and_cleanup;
1616 }
1617 }
1618
1619 if (ictx->origin_changed) {
1620 char cbuf[DNS_NAME_FORMATSIZE];
1621 char obuf[DNS_NAME_FORMATSIZE];
1622 dns_name_format(ictx->current, cbuf,
1623 sizeof(cbuf));
1624 dns_name_format(ictx->origin, obuf,
1625 sizeof(obuf));
1626 (*callbacks->warn)(callbacks,
1627 "%s:%lu: record with "
1628 "inherited "
1629 "owner (%s) immediately "
1630 "after "
1631 "$ORIGIN (%s)",
1632 source, line, cbuf, obuf);
1633 }
1634 }
1635
1636 ictx->origin_changed = false;
1637
1638 if (dns_rdataclass_fromtext(&rdclass,
1639 &token.value.as_textregion) ==
1640 ISC_R_SUCCESS)
1641 {
1642 GETTOKEN(lctx->lex, 0, &token, false);
1643 }
1644
1645 explicit_ttl = false;
1646 result = dns_ttl_fromtext(&token.value.as_textregion,
1647 &lctx->ttl);
1648 if (result == ISC_R_SUCCESS) {
1649 limit_ttl(callbacks, source, line, &lctx->ttl);
1650 explicit_ttl = true;
1651 lctx->ttl_known = true;
1652 GETTOKEN(lctx->lex, 0, &token, false);
1653 }
1654
1655 if (token.type != isc_tokentype_string) {
1656 UNEXPECTED_ERROR(__FILE__, __LINE__,
1657 "isc_lex_gettoken() returned "
1658 "unexpected token type");
1659 result = ISC_R_UNEXPECTED;
1660 if (MANYERRS(lctx, result)) {
1661 SETRESULT(lctx, result);
1662 read_till_eol = true;
1663 continue;
1664 } else {
1665 goto insist_and_cleanup;
1666 }
1667 }
1668
1669 if (rdclass == 0 &&
1670 dns_rdataclass_fromtext(&rdclass,
1671 &token.value.as_textregion) ==
1672 ISC_R_SUCCESS)
1673 {
1674 GETTOKEN(lctx->lex, 0, &token, false);
1675 }
1676
1677 if (token.type != isc_tokentype_string) {
1678 UNEXPECTED_ERROR(__FILE__, __LINE__,
1679 "isc_lex_gettoken() returned "
1680 "unexpected token type");
1681 result = ISC_R_UNEXPECTED;
1682 if (MANYERRS(lctx, result)) {
1683 SETRESULT(lctx, result);
1684 read_till_eol = true;
1685 continue;
1686 } else {
1687 goto insist_and_cleanup;
1688 }
1689 }
1690
1691 result = dns_rdatatype_fromtext(&type,
1692 &token.value.as_textregion);
1693 if (result != ISC_R_SUCCESS) {
1694 (*callbacks->warn)(
1695 callbacks, "%s:%lu: unknown RR type '%.*s'",
1696 source, line, token.value.as_textregion.length,
1697 token.value.as_textregion.base);
1698 if (MANYERRS(lctx, result)) {
1699 SETRESULT(lctx, result);
1700 read_till_eol = true;
1701 continue;
1702 } else if (result != ISC_R_SUCCESS) {
1703 goto insist_and_cleanup;
1704 }
1705 }
1706
1707 /*
1708 * If the class specified does not match the zone's class
1709 * print out a error message and exit.
1710 */
1711 if (rdclass != 0 && rdclass != lctx->zclass) {
1712 bad_class:
1713
1714 dns_rdataclass_format(rdclass, classname1,
1715 sizeof(classname1));
1716 dns_rdataclass_format(lctx->zclass, classname2,
1717 sizeof(classname2));
1718 (*callbacks->error)(callbacks,
1719 "%s:%lu: class '%s' != "
1720 "zone class '%s'",
1721 source, line, classname1,
1722 classname2);
1723 result = DNS_R_BADCLASS;
1724 if (MANYERRS(lctx, result)) {
1725 SETRESULT(lctx, result);
1726 read_till_eol = true;
1727 continue;
1728 } else {
1729 goto insist_and_cleanup;
1730 }
1731 }
1732
1733 if (type == dns_rdatatype_ns && ictx->glue == NULL) {
1734 current_has_delegation = true;
1735 }
1736
1737 /*
1738 * RFC1123: MD and MF are not allowed to be loaded from
1739 * master files.
1740 */
1741 if (dns_master_isprimary(lctx) &&
1742 (type == dns_rdatatype_md || type == dns_rdatatype_mf))
1743 {
1744 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1745
1746 result = DNS_R_OBSOLETE;
1747
1748 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1749 (*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1750 source, line, "type", typebuf,
1751 dns_result_totext(result));
1752 if (MANYERRS(lctx, result)) {
1753 SETRESULT(lctx, result);
1754 } else {
1755 goto insist_and_cleanup;
1756 }
1757 }
1758
1759 /*
1760 * RFC2930: TKEY and TSIG are not allowed to be loaded
1761 * from master files.
1762 */
1763 if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
1764 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1765
1766 result = DNS_R_METATYPE;
1767
1768 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1769 (*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1770 source, line, "type", typebuf,
1771 dns_result_totext(result));
1772 if (MANYERRS(lctx, result)) {
1773 SETRESULT(lctx, result);
1774 } else {
1775 goto insist_and_cleanup;
1776 }
1777 }
1778
1779 /*
1780 * Find a rdata structure.
1781 */
1782 if (rdcount == rdata_size) {
1783 new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1784 rdata_size, ¤t_list,
1785 &glue_list, mctx);
1786 if (new_rdata == NULL) {
1787 result = ISC_R_NOMEMORY;
1788 goto log_and_cleanup;
1789 }
1790 rdata_size += RDSZ;
1791 rdata = new_rdata;
1792 }
1793
1794 /*
1795 * Peek at the NS record.
1796 */
1797 if (type == dns_rdatatype_ns &&
1798 lctx->zclass == dns_rdataclass_in &&
1799 (lctx->options & DNS_MASTER_CHECKNS) != 0)
1800 {
1801 GETTOKEN(lctx->lex, 0, &token, false);
1802 result = check_ns(lctx, &token, source, line);
1803 isc_lex_ungettoken(lctx->lex, &token);
1804 if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
1805 if (MANYERRS(lctx, result)) {
1806 SETRESULT(lctx, result);
1807 } else if (result != ISC_R_SUCCESS) {
1808 goto insist_and_cleanup;
1809 }
1810 }
1811 }
1812
1813 /*
1814 * Check owner name.
1815 */
1816 options &= ~DNS_RDATA_CHECKREVERSE;
1817 if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1818 bool ok;
1819 dns_name_t *name;
1820
1821 name = (ictx->glue != NULL) ? ictx->glue
1822 : ictx->current;
1823 ok = dns_rdata_checkowner(name, lctx->zclass, type,
1824 true);
1825 if (!ok) {
1826 char namebuf[DNS_NAME_FORMATSIZE];
1827 const char *desc;
1828 dns_name_format(name, namebuf, sizeof(namebuf));
1829 result = DNS_R_BADOWNERNAME;
1830 desc = dns_result_totext(result);
1831 if (CHECKNAMESFAIL(lctx->options) ||
1832 type == dns_rdatatype_nsec3) {
1833 (*callbacks->error)(
1834 callbacks, "%s:%lu: %s: %s",
1835 source, line, namebuf, desc);
1836 if (MANYERRS(lctx, result)) {
1837 SETRESULT(lctx, result);
1838 } else {
1839 goto cleanup;
1840 }
1841 } else {
1842 (*callbacks->warn)(
1843 callbacks, "%s:%lu: %s: %s",
1844 source, line, namebuf, desc);
1845 }
1846 }
1847 if (type == dns_rdatatype_ptr &&
1848 !dns_name_isdnssd(name) &&
1849 (dns_name_issubdomain(name, &in_addr_arpa) ||
1850 dns_name_issubdomain(name, &ip6_arpa) ||
1851 dns_name_issubdomain(name, &ip6_int)))
1852 {
1853 options |= DNS_RDATA_CHECKREVERSE;
1854 }
1855 }
1856
1857 /*
1858 * Read rdata contents.
1859 */
1860 dns_rdata_init(&rdata[rdcount]);
1861 target_ft = target;
1862 result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass, type,
1863 lctx->lex, ictx->origin, options,
1864 lctx->mctx, &target, callbacks);
1865 if (MANYERRS(lctx, result)) {
1866 SETRESULT(lctx, result);
1867 continue;
1868 } else if (result != ISC_R_SUCCESS) {
1869 goto insist_and_cleanup;
1870 }
1871
1872 if (ictx->drop) {
1873 target = target_ft;
1874 continue;
1875 }
1876
1877 if (type == dns_rdatatype_soa &&
1878 (lctx->options & DNS_MASTER_ZONE) != 0 &&
1879 !dns_name_equal(ictx->current, lctx->top))
1880 {
1881 char namebuf[DNS_NAME_FORMATSIZE];
1882 dns_name_format(ictx->current, namebuf,
1883 sizeof(namebuf));
1884 (*callbacks->error)(callbacks,
1885 "%s:%lu: SOA "
1886 "record not at top of zone (%s)",
1887 source, line, namebuf);
1888 result = DNS_R_NOTZONETOP;
1889 if (MANYERRS(lctx, result)) {
1890 SETRESULT(lctx, result);
1891 read_till_eol = true;
1892 target = target_ft;
1893 continue;
1894 } else {
1895 goto insist_and_cleanup;
1896 }
1897 }
1898
1899 if (dns_rdatatype_atparent(type) &&
1900 dns_master_isprimary(lctx) &&
1901 dns_name_equal(ictx->current, lctx->top))
1902 {
1903 char namebuf[DNS_NAME_FORMATSIZE];
1904 char typebuf[DNS_RDATATYPE_FORMATSIZE];
1905
1906 dns_name_format(ictx->current, namebuf,
1907 sizeof(namebuf));
1908 dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1909 (*callbacks->error)(
1910 callbacks,
1911 "%s:%lu: %s record at top of zone (%s)", source,
1912 line, typebuf, namebuf);
1913 result = DNS_R_ATZONETOP;
1914 if (MANYERRS(lctx, result)) {
1915 SETRESULT(lctx, result);
1916 target = target_ft;
1917 continue;
1918 } else {
1919 goto insist_and_cleanup;
1920 }
1921 }
1922
1923 if (type == dns_rdatatype_rrsig || type == dns_rdatatype_sig) {
1924 covers = dns_rdata_covers(&rdata[rdcount]);
1925 } else {
1926 covers = 0;
1927 }
1928
1929 if (!lctx->ttl_known && !lctx->default_ttl_known) {
1930 if (type == dns_rdatatype_soa) {
1931 (*callbacks->warn)(callbacks,
1932 "%s:%lu: no TTL specified; "
1933 "using SOA MINTTL instead",
1934 source, line);
1935 lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1936 limit_ttl(callbacks, source, line, &lctx->ttl);
1937 lctx->default_ttl = lctx->ttl;
1938 lctx->default_ttl_known = true;
1939 } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
1940 /*
1941 * Zero TTL's are fine for hints.
1942 */
1943 lctx->ttl = 0;
1944 lctx->default_ttl = lctx->ttl;
1945 lctx->default_ttl_known = true;
1946 } else {
1947 (*callbacks->warn)(callbacks,
1948 "%s:%lu: no TTL specified; "
1949 "zone rejected",
1950 source, line);
1951 result = DNS_R_NOTTL;
1952 if (MANYERRS(lctx, result)) {
1953 SETRESULT(lctx, result);
1954 lctx->ttl = 0;
1955 } else {
1956 goto insist_and_cleanup;
1957 }
1958 }
1959 } else if (!explicit_ttl && lctx->default_ttl_known) {
1960 lctx->ttl = lctx->default_ttl;
1961 } else if (!explicit_ttl && lctx->warn_1035) {
1962 (*callbacks->warn)(callbacks,
1963 "%s:%lu: "
1964 "using RFC1035 TTL semantics",
1965 source, line);
1966 lctx->warn_1035 = false;
1967 }
1968
1969 if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1970 dns_rdata_rrsig_t sig;
1971 result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1972 NULL);
1973 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1974 if (isc_serial_lt(sig.timeexpire, lctx->now)) {
1975 (*callbacks->warn)(callbacks,
1976 "%s:%lu: "
1977 "signature has expired",
1978 source, line);
1979 lctx->warn_sigexpired = false;
1980 }
1981 }
1982
1983 if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1984 lctx->warn_tcr && dns_master_isprimary(lctx))
1985 {
1986 (*callbacks->warn)(callbacks,
1987 "%s:%lu: old style DNSSEC "
1988 " zone detected",
1989 source, line);
1990 lctx->warn_tcr = false;
1991 }
1992
1993 if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
1994 /*
1995 * Adjust the TTL for $DATE. If the RR has
1996 * already expired, set its TTL to 0. This
1997 * should be okay even if the TTL stretching
1998 * feature is not in effect, because it will
1999 * just be quickly expired by the cache, and the
2000 * way this was written before the patch it
2001 * could potentially add 0 TTLs anyway.
2002 */
2003 if (lctx->ttl < ttl_offset) {
2004 lctx->ttl = 0;
2005 } else {
2006 lctx->ttl -= ttl_offset;
2007 }
2008 }
2009
2010 /*
2011 * Find type in rdatalist.
2012 * If it does not exist create new one and prepend to list
2013 * as this will minimise list traversal.
2014 */
2015 if (ictx->glue != NULL) {
2016 this = ISC_LIST_HEAD(glue_list);
2017 } else {
2018 this = ISC_LIST_HEAD(current_list);
2019 }
2020
2021 while (this != NULL) {
2022 if (this->type == type && this->covers == covers) {
2023 break;
2024 }
2025 this = ISC_LIST_NEXT(this, link);
2026 }
2027
2028 if (this == NULL) {
2029 if (rdlcount == rdatalist_size) {
2030 new_rdatalist = grow_rdatalist(
2031 rdatalist_size + RDLSZ, rdatalist,
2032 rdatalist_size, ¤t_list,
2033 &glue_list, mctx);
2034 if (new_rdatalist == NULL) {
2035 result = ISC_R_NOMEMORY;
2036 goto log_and_cleanup;
2037 }
2038 rdatalist = new_rdatalist;
2039 rdatalist_size += RDLSZ;
2040 }
2041 this = &rdatalist[rdlcount++];
2042 dns_rdatalist_init(this);
2043 this->type = type;
2044 this->covers = covers;
2045 this->rdclass = lctx->zclass;
2046 this->ttl = lctx->ttl;
2047 if (ictx->glue != NULL) {
2048 ISC_LIST_INITANDPREPEND(glue_list, this, link);
2049 } else {
2050 ISC_LIST_INITANDPREPEND(current_list, this,
2051 link);
2052 }
2053 } else if (this->ttl != lctx->ttl) {
2054 (*callbacks->warn)(callbacks,
2055 "%s:%lu: "
2056 "TTL set to prior TTL (%lu)",
2057 source, line, this->ttl);
2058 lctx->ttl = this->ttl;
2059 }
2060
2061 if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
2062 lctx->ttl > lctx->maxttl) {
2063 (callbacks->error)(callbacks,
2064 "dns_master_load: %s:%lu: "
2065 "TTL %d exceeds configured "
2066 "max-zone-ttl %d",
2067 source, line, lctx->ttl,
2068 lctx->maxttl);
2069 result = ISC_R_RANGE;
2070 goto log_and_cleanup;
2071 }
2072
2073 ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
2074 if (ictx->glue != NULL) {
2075 ictx->glue_line = line;
2076 } else {
2077 ictx->current_line = line;
2078 }
2079 rdcount++;
2080
2081 /*
2082 * We must have at least 64k as rdlen is 16 bits.
2083 * If we don't commit everything we have so far.
2084 */
2085 if ((target.length - target.used) < MINTSIZ) {
2086 COMMITALL;
2087 }
2088 next_line:;
2089 } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
2090
2091 /*
2092 * Commit what has not yet been committed.
2093 */
2094 result = commit(callbacks, lctx, ¤t_list, ictx->current, source,
2095 ictx->current_line);
2096 if (MANYERRS(lctx, result)) {
2097 SETRESULT(lctx, result);
2098 } else if (result != ISC_R_SUCCESS) {
2099 goto insist_and_cleanup;
2100 }
2101 result = commit(callbacks, lctx, &glue_list, ictx->glue, source,
2102 ictx->glue_line);
2103 if (MANYERRS(lctx, result)) {
2104 SETRESULT(lctx, result);
2105 } else if (result != ISC_R_SUCCESS) {
2106 goto insist_and_cleanup;
2107 }
2108
2109 if (!done) {
2110 INSIST(lctx->done != NULL && lctx->task != NULL);
2111 result = DNS_R_CONTINUE;
2112 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2113 result = lctx->result;
2114 } else if (result == ISC_R_SUCCESS && lctx->seen_include) {
2115 result = DNS_R_SEENINCLUDE;
2116 }
2117 goto cleanup;
2118
2119 log_and_cleanup:
2120 LOGIT(result);
2121
2122 insist_and_cleanup:
2123 INSIST(result != ISC_R_SUCCESS);
2124
2125 cleanup:
2126 while ((this = ISC_LIST_HEAD(current_list)) != NULL) {
2127 ISC_LIST_UNLINK(current_list, this, link);
2128 }
2129 while ((this = ISC_LIST_HEAD(glue_list)) != NULL) {
2130 ISC_LIST_UNLINK(glue_list, this, link);
2131 }
2132 if (rdatalist != NULL) {
2133 isc_mem_put(mctx, rdatalist,
2134 rdatalist_size * sizeof(*rdatalist));
2135 }
2136 if (rdata != NULL) {
2137 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2138 }
2139 if (target_mem != NULL) {
2140 isc_mem_put(mctx, target_mem, target_size);
2141 }
2142 if (include_file != NULL) {
2143 isc_mem_free(mctx, include_file);
2144 }
2145 if (range != NULL) {
2146 isc_mem_free(mctx, range);
2147 }
2148 if (lhs != NULL) {
2149 isc_mem_free(mctx, lhs);
2150 }
2151 if (gtype != NULL) {
2152 isc_mem_free(mctx, gtype);
2153 }
2154 if (rhs != NULL) {
2155 isc_mem_free(mctx, rhs);
2156 }
2157 return (result);
2158 }
2159
2160 static isc_result_t
pushfile(const char * master_file,dns_name_t * origin,dns_loadctx_t * lctx)2161 pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
2162 isc_result_t result;
2163 dns_incctx_t *ictx;
2164 dns_incctx_t *newctx = NULL;
2165 isc_region_t r;
2166
2167 REQUIRE(master_file != NULL);
2168 REQUIRE(DNS_LCTX_VALID(lctx));
2169
2170 ictx = lctx->inc;
2171 lctx->seen_include = true;
2172
2173 result = incctx_create(lctx->mctx, origin, &newctx);
2174 if (result != ISC_R_SUCCESS) {
2175 return (result);
2176 }
2177
2178 /*
2179 * Push origin_changed.
2180 */
2181 newctx->origin_changed = ictx->origin_changed;
2182
2183 /* Set current domain. */
2184 if (ictx->glue != NULL || ictx->current != NULL) {
2185 newctx->current_in_use = find_free_name(newctx);
2186 newctx->current = dns_fixedname_name(
2187 &newctx->fixed[newctx->current_in_use]);
2188 newctx->in_use[newctx->current_in_use] = true;
2189 dns_name_toregion(
2190 (ictx->glue != NULL) ? ictx->glue : ictx->current, &r);
2191 dns_name_fromregion(newctx->current, &r);
2192 newctx->drop = ictx->drop;
2193 }
2194
2195 result = (lctx->openfile)(lctx, master_file);
2196 if (result != ISC_R_SUCCESS) {
2197 goto cleanup;
2198 }
2199 newctx->parent = ictx;
2200 lctx->inc = newctx;
2201
2202 if (lctx->include_cb != NULL) {
2203 lctx->include_cb(master_file, lctx->include_arg);
2204 }
2205 return (ISC_R_SUCCESS);
2206
2207 cleanup:
2208 incctx_destroy(lctx->mctx, newctx);
2209 return (result);
2210 }
2211
2212 /*
2213 * Fill/check exists buffer with 'len' bytes. Track remaining bytes to be
2214 * read when incrementally filling the buffer.
2215 */
2216 static inline isc_result_t
read_and_check(bool do_read,isc_buffer_t * buffer,size_t len,FILE * f,uint32_t * totallen)2217 read_and_check(bool do_read, isc_buffer_t *buffer, size_t len, FILE *f,
2218 uint32_t *totallen) {
2219 isc_result_t result;
2220
2221 REQUIRE(totallen != NULL);
2222
2223 if (do_read) {
2224 INSIST(isc_buffer_availablelength(buffer) >= len);
2225 result = isc_stdio_read(isc_buffer_used(buffer), 1, len, f,
2226 NULL);
2227 if (result != ISC_R_SUCCESS) {
2228 return (result);
2229 }
2230 isc_buffer_add(buffer, (unsigned int)len);
2231 if (*totallen < len) {
2232 return (ISC_R_RANGE);
2233 }
2234 *totallen -= (uint32_t)len;
2235 } else if (isc_buffer_remaininglength(buffer) < len) {
2236 return (ISC_R_RANGE);
2237 }
2238
2239 return (ISC_R_SUCCESS);
2240 }
2241
2242 static isc_result_t
load_header(dns_loadctx_t * lctx)2243 load_header(dns_loadctx_t *lctx) {
2244 isc_result_t result = ISC_R_SUCCESS;
2245 dns_masterrawheader_t header;
2246 dns_rdatacallbacks_t *callbacks;
2247 size_t commonlen = sizeof(header.format) + sizeof(header.version);
2248 size_t remainder;
2249 unsigned char data[sizeof(header)];
2250 isc_buffer_t target;
2251
2252 REQUIRE(DNS_LCTX_VALID(lctx));
2253
2254 if (lctx->format != dns_masterformat_raw &&
2255 lctx->format != dns_masterformat_map)
2256 {
2257 return (ISC_R_NOTIMPLEMENTED);
2258 }
2259
2260 callbacks = lctx->callbacks;
2261 dns_master_initrawheader(&header);
2262
2263 INSIST(commonlen <= sizeof(header));
2264 isc_buffer_init(&target, data, sizeof(data));
2265
2266 result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
2267 if (result != ISC_R_SUCCESS) {
2268 UNEXPECTED_ERROR(__FILE__, __LINE__,
2269 "isc_stdio_read failed: %s",
2270 isc_result_totext(result));
2271 return (result);
2272 }
2273
2274 isc_buffer_add(&target, (unsigned int)commonlen);
2275 header.format = isc_buffer_getuint32(&target);
2276 if (header.format != lctx->format) {
2277 (*callbacks->error)(callbacks,
2278 "dns_master_load: "
2279 "file format mismatch (not %s)",
2280 lctx->format == dns_masterformat_map ? "map"
2281 : "ra"
2282 "w");
2283 return (ISC_R_NOTIMPLEMENTED);
2284 }
2285
2286 header.version = isc_buffer_getuint32(&target);
2287
2288 switch (header.version) {
2289 case 0:
2290 remainder = sizeof(header.dumptime);
2291 break;
2292 case DNS_RAWFORMAT_VERSION:
2293 remainder = sizeof(header) - commonlen;
2294 break;
2295 default:
2296 (*callbacks->error)(callbacks, "dns_master_load: "
2297 "unsupported file format "
2298 "version");
2299 return (ISC_R_NOTIMPLEMENTED);
2300 }
2301
2302 result = isc_stdio_read(data + commonlen, 1, remainder, lctx->f, NULL);
2303 if (result != ISC_R_SUCCESS) {
2304 UNEXPECTED_ERROR(__FILE__, __LINE__,
2305 "isc_stdio_read failed: %s",
2306 isc_result_totext(result));
2307 return (result);
2308 }
2309
2310 isc_buffer_add(&target, (unsigned int)remainder);
2311 header.dumptime = isc_buffer_getuint32(&target);
2312 if (header.version == DNS_RAWFORMAT_VERSION) {
2313 header.flags = isc_buffer_getuint32(&target);
2314 header.sourceserial = isc_buffer_getuint32(&target);
2315 header.lastxfrin = isc_buffer_getuint32(&target);
2316 }
2317
2318 lctx->first = false;
2319 lctx->header = header;
2320
2321 return (ISC_R_SUCCESS);
2322 }
2323
2324 static isc_result_t
openfile_map(dns_loadctx_t * lctx,const char * master_file)2325 openfile_map(dns_loadctx_t *lctx, const char *master_file) {
2326 isc_result_t result;
2327
2328 result = isc_stdio_open(master_file, "rb", &lctx->f);
2329 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
2330 UNEXPECTED_ERROR(__FILE__, __LINE__,
2331 "isc_stdio_open() failed: %s",
2332 isc_result_totext(result));
2333 }
2334
2335 return (result);
2336 }
2337
2338 /*
2339 * Load a map format file, using mmap() to access RBT trees directly
2340 */
2341 static isc_result_t
load_map(dns_loadctx_t * lctx)2342 load_map(dns_loadctx_t *lctx) {
2343 isc_result_t result = ISC_R_SUCCESS;
2344 dns_rdatacallbacks_t *callbacks;
2345
2346 REQUIRE(DNS_LCTX_VALID(lctx));
2347
2348 callbacks = lctx->callbacks;
2349
2350 if (lctx->first) {
2351 result = load_header(lctx);
2352 if (result != ISC_R_SUCCESS) {
2353 return (result);
2354 }
2355
2356 result = (*callbacks->deserialize)(
2357 callbacks->deserialize_private, lctx->f,
2358 sizeof(dns_masterrawheader_t));
2359 }
2360
2361 return (result);
2362 }
2363
2364 static isc_result_t
openfile_raw(dns_loadctx_t * lctx,const char * master_file)2365 openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
2366 isc_result_t result;
2367
2368 result = isc_stdio_open(master_file, "rb", &lctx->f);
2369 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
2370 UNEXPECTED_ERROR(__FILE__, __LINE__,
2371 "isc_stdio_open() failed: %s",
2372 isc_result_totext(result));
2373 }
2374
2375 return (result);
2376 }
2377
2378 static isc_result_t
load_raw(dns_loadctx_t * lctx)2379 load_raw(dns_loadctx_t *lctx) {
2380 isc_result_t result = ISC_R_SUCCESS;
2381 bool done = false;
2382 unsigned int loop_cnt = 0;
2383 dns_rdatacallbacks_t *callbacks;
2384 unsigned char namebuf[DNS_NAME_MAXWIRE];
2385 dns_fixedname_t fixed;
2386 dns_name_t *name;
2387 rdatalist_head_t head, dummy;
2388 dns_rdatalist_t rdatalist;
2389 isc_mem_t *mctx = lctx->mctx;
2390 dns_rdata_t *rdata = NULL;
2391 unsigned int rdata_size = 0;
2392 int target_size = TSIZ;
2393 isc_buffer_t target, buf;
2394 unsigned char *target_mem = NULL;
2395 dns_decompress_t dctx;
2396
2397 callbacks = lctx->callbacks;
2398 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
2399
2400 if (lctx->first) {
2401 result = load_header(lctx);
2402 if (result != ISC_R_SUCCESS) {
2403 return (result);
2404 }
2405 }
2406
2407 ISC_LIST_INIT(head);
2408 ISC_LIST_INIT(dummy);
2409
2410 /*
2411 * Allocate target_size of buffer space. This is greater than twice
2412 * the maximum individual RR data size.
2413 */
2414 target_mem = isc_mem_get(mctx, target_size);
2415 isc_buffer_init(&target, target_mem, target_size);
2416
2417 name = dns_fixedname_initname(&fixed);
2418
2419 /*
2420 * In the following loop, we regard any error fatal regardless of
2421 * whether "MANYERRORS" is set in the context option. This is because
2422 * normal errors should already have been checked at creation time.
2423 * Besides, it is very unlikely that we can recover from an error
2424 * in this format, and so trying to continue parsing erroneous data
2425 * does not really make sense.
2426 */
2427 for (loop_cnt = 0; (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
2428 loop_cnt++)
2429 {
2430 unsigned int i, rdcount;
2431 uint16_t namelen;
2432 uint32_t totallen;
2433 size_t minlen, readlen;
2434 bool sequential_read = false;
2435
2436 /* Read the data length */
2437 isc_buffer_clear(&target);
2438 INSIST(isc_buffer_availablelength(&target) >= sizeof(totallen));
2439 result = isc_stdio_read(target.base, 1, sizeof(totallen),
2440 lctx->f, NULL);
2441 if (result == ISC_R_EOF) {
2442 result = ISC_R_SUCCESS;
2443 done = true;
2444 break;
2445 }
2446 if (result != ISC_R_SUCCESS) {
2447 goto cleanup;
2448 }
2449 isc_buffer_add(&target, sizeof(totallen));
2450 totallen = isc_buffer_getuint32(&target);
2451
2452 /*
2453 * Validation: the input data must at least contain the common
2454 * header.
2455 */
2456 minlen = sizeof(totallen) + sizeof(uint16_t) +
2457 sizeof(uint16_t) + sizeof(uint16_t) +
2458 sizeof(uint32_t) + sizeof(uint32_t);
2459 if (totallen < minlen) {
2460 result = ISC_R_RANGE;
2461 goto cleanup;
2462 }
2463 totallen -= sizeof(totallen);
2464
2465 isc_buffer_clear(&target);
2466 if (totallen > isc_buffer_availablelength(&target)) {
2467 /*
2468 * The default buffer size should typically be large
2469 * enough to store the entire RRset. We could try to
2470 * allocate enough space if this is not the case, but
2471 * it might cause a hazardous result when "totallen"
2472 * is forged. Thus, we'd rather take an inefficient
2473 * but robust approach in this atypical case: read
2474 * data step by step, and commit partial data when
2475 * necessary. Note that the buffer must be large
2476 * enough to store the "header part", owner name, and
2477 * at least one rdata (however large it is).
2478 */
2479 sequential_read = true;
2480 readlen = minlen - sizeof(totallen);
2481 } else {
2482 /*
2483 * Typical case. We can read the whole RRset at once
2484 * with the default buffer.
2485 */
2486 readlen = totallen;
2487 }
2488 result = isc_stdio_read(target.base, 1, readlen, lctx->f, NULL);
2489 if (result != ISC_R_SUCCESS) {
2490 goto cleanup;
2491 }
2492 isc_buffer_add(&target, (unsigned int)readlen);
2493 totallen -= (uint32_t)readlen;
2494
2495 /* Construct RRset headers */
2496 dns_rdatalist_init(&rdatalist);
2497 rdatalist.rdclass = isc_buffer_getuint16(&target);
2498 if (lctx->zclass != rdatalist.rdclass) {
2499 result = DNS_R_BADCLASS;
2500 goto cleanup;
2501 }
2502 rdatalist.type = isc_buffer_getuint16(&target);
2503 rdatalist.covers = isc_buffer_getuint16(&target);
2504 rdatalist.ttl = isc_buffer_getuint32(&target);
2505 rdcount = isc_buffer_getuint32(&target);
2506 if (rdcount == 0 || rdcount > 0xffff) {
2507 result = ISC_R_RANGE;
2508 goto cleanup;
2509 }
2510 INSIST(isc_buffer_consumedlength(&target) <= readlen);
2511
2512 /* Owner name: length followed by name */
2513 result = read_and_check(sequential_read, &target,
2514 sizeof(namelen), lctx->f, &totallen);
2515 if (result != ISC_R_SUCCESS) {
2516 goto cleanup;
2517 }
2518 namelen = isc_buffer_getuint16(&target);
2519 if (namelen > sizeof(namebuf)) {
2520 result = ISC_R_RANGE;
2521 goto cleanup;
2522 }
2523
2524 result = read_and_check(sequential_read, &target, namelen,
2525 lctx->f, &totallen);
2526 if (result != ISC_R_SUCCESS) {
2527 goto cleanup;
2528 }
2529
2530 isc_buffer_setactive(&target, (unsigned int)namelen);
2531 result = dns_name_fromwire(name, &target, &dctx, 0, NULL);
2532 if (result != ISC_R_SUCCESS) {
2533 goto cleanup;
2534 }
2535
2536 if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
2537 rdatalist.ttl > lctx->maxttl) {
2538 (callbacks->error)(callbacks,
2539 "dns_master_load: "
2540 "TTL %d exceeds configured "
2541 "max-zone-ttl %d",
2542 rdatalist.ttl, lctx->maxttl);
2543 result = ISC_R_RANGE;
2544 goto cleanup;
2545 }
2546
2547 /* Rdata contents. */
2548 if (rdcount > rdata_size) {
2549 dns_rdata_t *new_rdata = NULL;
2550
2551 new_rdata = grow_rdata(rdcount + RDSZ, rdata,
2552 rdata_size, &head, &dummy, mctx);
2553 if (new_rdata == NULL) {
2554 result = ISC_R_NOMEMORY;
2555 goto cleanup;
2556 }
2557 rdata_size = rdcount + RDSZ;
2558 rdata = new_rdata;
2559 }
2560
2561 continue_read:
2562 for (i = 0; i < rdcount; i++) {
2563 uint16_t rdlen;
2564
2565 dns_rdata_init(&rdata[i]);
2566
2567 if (sequential_read &&
2568 isc_buffer_availablelength(&target) < MINTSIZ) {
2569 unsigned int j;
2570
2571 INSIST(i > 0); /* detect an infinite loop */
2572
2573 /* Partial Commit. */
2574 ISC_LIST_APPEND(head, &rdatalist, link);
2575 result = commit(callbacks, lctx, &head, name,
2576 NULL, 0);
2577 for (j = 0; j < i; j++) {
2578 ISC_LIST_UNLINK(rdatalist.rdata,
2579 &rdata[j], link);
2580 dns_rdata_reset(&rdata[j]);
2581 }
2582 if (result != ISC_R_SUCCESS) {
2583 goto cleanup;
2584 }
2585
2586 /* Rewind the buffer and continue */
2587 isc_buffer_clear(&target);
2588
2589 rdcount -= i;
2590
2591 goto continue_read;
2592 }
2593
2594 /* rdata length */
2595 result = read_and_check(sequential_read, &target,
2596 sizeof(rdlen), lctx->f,
2597 &totallen);
2598 if (result != ISC_R_SUCCESS) {
2599 goto cleanup;
2600 }
2601 rdlen = isc_buffer_getuint16(&target);
2602
2603 /* rdata */
2604 result = read_and_check(sequential_read, &target, rdlen,
2605 lctx->f, &totallen);
2606 if (result != ISC_R_SUCCESS) {
2607 goto cleanup;
2608 }
2609 isc_buffer_setactive(&target, (unsigned int)rdlen);
2610 /*
2611 * It is safe to have the source active region and
2612 * the target available region be the same if
2613 * decompression is disabled (see dctx above) and we
2614 * are not downcasing names (options == 0).
2615 */
2616 isc_buffer_init(&buf, isc_buffer_current(&target),
2617 (unsigned int)rdlen);
2618 result = dns_rdata_fromwire(
2619 &rdata[i], rdatalist.rdclass, rdatalist.type,
2620 &target, &dctx, 0, &buf);
2621 if (result != ISC_R_SUCCESS) {
2622 goto cleanup;
2623 }
2624 ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2625 }
2626
2627 /*
2628 * Sanity check. Still having remaining space is not
2629 * necessarily critical, but it very likely indicates broken
2630 * or malformed data.
2631 */
2632 if (isc_buffer_remaininglength(&target) != 0 || totallen != 0) {
2633 result = ISC_R_RANGE;
2634 goto cleanup;
2635 }
2636
2637 ISC_LIST_APPEND(head, &rdatalist, link);
2638
2639 /* Commit this RRset. rdatalist will be unlinked. */
2640 result = commit(callbacks, lctx, &head, name, NULL, 0);
2641
2642 for (i = 0; i < rdcount; i++) {
2643 ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2644 dns_rdata_reset(&rdata[i]);
2645 }
2646
2647 if (result != ISC_R_SUCCESS) {
2648 goto cleanup;
2649 }
2650 }
2651
2652 if (!done) {
2653 INSIST(lctx->done != NULL && lctx->task != NULL);
2654 result = DNS_R_CONTINUE;
2655 } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2656 result = lctx->result;
2657 }
2658
2659 if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL) {
2660 (*callbacks->rawdata)(callbacks->zone, &lctx->header);
2661 }
2662
2663 cleanup:
2664 if (rdata != NULL) {
2665 isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
2666 }
2667 if (target_mem != NULL) {
2668 isc_mem_put(mctx, target_mem, target_size);
2669 }
2670 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
2671 (*callbacks->error)(callbacks, "dns_master_load: %s",
2672 dns_result_totext(result));
2673 }
2674
2675 return (result);
2676 }
2677
2678 isc_result_t
dns_master_loadfile(const char * master_file,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,uint32_t resign,dns_rdatacallbacks_t * callbacks,dns_masterincludecb_t include_cb,void * include_arg,isc_mem_t * mctx,dns_masterformat_t format,dns_ttl_t maxttl)2679 dns_master_loadfile(const char *master_file, dns_name_t *top,
2680 dns_name_t *origin, dns_rdataclass_t zclass,
2681 unsigned int options, uint32_t resign,
2682 dns_rdatacallbacks_t *callbacks,
2683 dns_masterincludecb_t include_cb, void *include_arg,
2684 isc_mem_t *mctx, dns_masterformat_t format,
2685 dns_ttl_t maxttl) {
2686 dns_loadctx_t *lctx = NULL;
2687 isc_result_t result;
2688
2689 result = loadctx_create(format, mctx, options, resign, top, zclass,
2690 origin, callbacks, NULL, NULL, NULL, include_cb,
2691 include_arg, NULL, &lctx);
2692 if (result != ISC_R_SUCCESS) {
2693 return (result);
2694 }
2695
2696 lctx->maxttl = maxttl;
2697
2698 result = (lctx->openfile)(lctx, master_file);
2699 if (result != ISC_R_SUCCESS) {
2700 goto cleanup;
2701 }
2702
2703 result = (lctx->load)(lctx);
2704 INSIST(result != DNS_R_CONTINUE);
2705
2706 cleanup:
2707 dns_loadctx_detach(&lctx);
2708 return (result);
2709 }
2710
2711 isc_result_t
dns_master_loadfileinc(const char * master_file,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,uint32_t resign,dns_rdatacallbacks_t * callbacks,isc_task_t * task,dns_loaddonefunc_t done,void * done_arg,dns_loadctx_t ** lctxp,dns_masterincludecb_t include_cb,void * include_arg,isc_mem_t * mctx,dns_masterformat_t format,uint32_t maxttl)2712 dns_master_loadfileinc(const char *master_file, dns_name_t *top,
2713 dns_name_t *origin, dns_rdataclass_t zclass,
2714 unsigned int options, uint32_t resign,
2715 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2716 dns_loaddonefunc_t done, void *done_arg,
2717 dns_loadctx_t **lctxp, dns_masterincludecb_t include_cb,
2718 void *include_arg, isc_mem_t *mctx,
2719 dns_masterformat_t format, uint32_t maxttl) {
2720 dns_loadctx_t *lctx = NULL;
2721 isc_result_t result;
2722
2723 REQUIRE(task != NULL);
2724 REQUIRE(done != NULL);
2725
2726 result = loadctx_create(format, mctx, options, resign, top, zclass,
2727 origin, callbacks, task, done, done_arg,
2728 include_cb, include_arg, NULL, &lctx);
2729 if (result != ISC_R_SUCCESS) {
2730 return (result);
2731 }
2732
2733 lctx->maxttl = maxttl;
2734
2735 result = (lctx->openfile)(lctx, master_file);
2736 if (result != ISC_R_SUCCESS) {
2737 goto cleanup;
2738 }
2739
2740 result = task_send(lctx);
2741 if (result == ISC_R_SUCCESS) {
2742 dns_loadctx_attach(lctx, lctxp);
2743 return (DNS_R_CONTINUE);
2744 }
2745
2746 cleanup:
2747 dns_loadctx_detach(&lctx);
2748 return (result);
2749 }
2750
2751 isc_result_t
dns_master_loadstream(FILE * stream,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_mem_t * mctx)2752 dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2753 dns_rdataclass_t zclass, unsigned int options,
2754 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2755 isc_result_t result;
2756 dns_loadctx_t *lctx = NULL;
2757
2758 REQUIRE(stream != NULL);
2759
2760 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2761 zclass, origin, callbacks, NULL, NULL, NULL,
2762 NULL, NULL, NULL, &lctx);
2763 if (result != ISC_R_SUCCESS) {
2764 goto cleanup;
2765 }
2766
2767 result = isc_lex_openstream(lctx->lex, stream);
2768 if (result != ISC_R_SUCCESS) {
2769 goto cleanup;
2770 }
2771
2772 result = (lctx->load)(lctx);
2773 INSIST(result != DNS_R_CONTINUE);
2774
2775 cleanup:
2776 if (lctx != NULL) {
2777 dns_loadctx_detach(&lctx);
2778 }
2779 return (result);
2780 }
2781
2782 isc_result_t
dns_master_loadstreaminc(FILE * stream,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_task_t * task,dns_loaddonefunc_t done,void * done_arg,dns_loadctx_t ** lctxp,isc_mem_t * mctx)2783 dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
2784 dns_rdataclass_t zclass, unsigned int options,
2785 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2786 dns_loaddonefunc_t done, void *done_arg,
2787 dns_loadctx_t **lctxp, isc_mem_t *mctx) {
2788 isc_result_t result;
2789 dns_loadctx_t *lctx = NULL;
2790
2791 REQUIRE(stream != NULL);
2792 REQUIRE(task != NULL);
2793 REQUIRE(done != NULL);
2794
2795 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2796 zclass, origin, callbacks, task, done, done_arg,
2797 NULL, NULL, NULL, &lctx);
2798 if (result != ISC_R_SUCCESS) {
2799 goto cleanup;
2800 }
2801
2802 result = isc_lex_openstream(lctx->lex, stream);
2803 if (result != ISC_R_SUCCESS) {
2804 goto cleanup;
2805 }
2806
2807 result = task_send(lctx);
2808 if (result == ISC_R_SUCCESS) {
2809 dns_loadctx_attach(lctx, lctxp);
2810 return (DNS_R_CONTINUE);
2811 }
2812
2813 cleanup:
2814 if (lctx != NULL) {
2815 dns_loadctx_detach(&lctx);
2816 }
2817 return (result);
2818 }
2819
2820 isc_result_t
dns_master_loadbuffer(isc_buffer_t * buffer,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_mem_t * mctx)2821 dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top, dns_name_t *origin,
2822 dns_rdataclass_t zclass, unsigned int options,
2823 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2824 isc_result_t result;
2825 dns_loadctx_t *lctx = NULL;
2826
2827 REQUIRE(buffer != NULL);
2828
2829 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2830 zclass, origin, callbacks, NULL, NULL, NULL,
2831 NULL, NULL, NULL, &lctx);
2832 if (result != ISC_R_SUCCESS) {
2833 return (result);
2834 }
2835
2836 result = isc_lex_openbuffer(lctx->lex, buffer);
2837 if (result != ISC_R_SUCCESS) {
2838 goto cleanup;
2839 }
2840
2841 result = (lctx->load)(lctx);
2842 INSIST(result != DNS_R_CONTINUE);
2843
2844 cleanup:
2845 dns_loadctx_detach(&lctx);
2846 return (result);
2847 }
2848
2849 isc_result_t
dns_master_loadbufferinc(isc_buffer_t * buffer,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_task_t * task,dns_loaddonefunc_t done,void * done_arg,dns_loadctx_t ** lctxp,isc_mem_t * mctx)2850 dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
2851 dns_name_t *origin, dns_rdataclass_t zclass,
2852 unsigned int options, dns_rdatacallbacks_t *callbacks,
2853 isc_task_t *task, dns_loaddonefunc_t done,
2854 void *done_arg, dns_loadctx_t **lctxp,
2855 isc_mem_t *mctx) {
2856 isc_result_t result;
2857 dns_loadctx_t *lctx = NULL;
2858
2859 REQUIRE(buffer != NULL);
2860 REQUIRE(task != NULL);
2861 REQUIRE(done != NULL);
2862
2863 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2864 zclass, origin, callbacks, task, done, done_arg,
2865 NULL, NULL, NULL, &lctx);
2866 if (result != ISC_R_SUCCESS) {
2867 return (result);
2868 }
2869
2870 result = isc_lex_openbuffer(lctx->lex, buffer);
2871 if (result != ISC_R_SUCCESS) {
2872 goto cleanup;
2873 }
2874
2875 result = task_send(lctx);
2876 if (result == ISC_R_SUCCESS) {
2877 dns_loadctx_attach(lctx, lctxp);
2878 return (DNS_R_CONTINUE);
2879 }
2880
2881 cleanup:
2882 dns_loadctx_detach(&lctx);
2883 return (result);
2884 }
2885
2886 isc_result_t
dns_master_loadlexer(isc_lex_t * lex,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_mem_t * mctx)2887 dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top, dns_name_t *origin,
2888 dns_rdataclass_t zclass, unsigned int options,
2889 dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2890 isc_result_t result;
2891 dns_loadctx_t *lctx = NULL;
2892
2893 REQUIRE(lex != NULL);
2894
2895 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2896 zclass, origin, callbacks, NULL, NULL, NULL,
2897 NULL, NULL, lex, &lctx);
2898 if (result != ISC_R_SUCCESS) {
2899 return (result);
2900 }
2901
2902 result = (lctx->load)(lctx);
2903 INSIST(result != DNS_R_CONTINUE);
2904
2905 dns_loadctx_detach(&lctx);
2906 return (result);
2907 }
2908
2909 isc_result_t
dns_master_loadlexerinc(isc_lex_t * lex,dns_name_t * top,dns_name_t * origin,dns_rdataclass_t zclass,unsigned int options,dns_rdatacallbacks_t * callbacks,isc_task_t * task,dns_loaddonefunc_t done,void * done_arg,dns_loadctx_t ** lctxp,isc_mem_t * mctx)2910 dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top, dns_name_t *origin,
2911 dns_rdataclass_t zclass, unsigned int options,
2912 dns_rdatacallbacks_t *callbacks, isc_task_t *task,
2913 dns_loaddonefunc_t done, void *done_arg,
2914 dns_loadctx_t **lctxp, isc_mem_t *mctx) {
2915 isc_result_t result;
2916 dns_loadctx_t *lctx = NULL;
2917
2918 REQUIRE(lex != NULL);
2919 REQUIRE(task != NULL);
2920 REQUIRE(done != NULL);
2921
2922 result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
2923 zclass, origin, callbacks, task, done, done_arg,
2924 NULL, NULL, lex, &lctx);
2925 if (result != ISC_R_SUCCESS) {
2926 return (result);
2927 }
2928
2929 result = task_send(lctx);
2930 if (result == ISC_R_SUCCESS) {
2931 dns_loadctx_attach(lctx, lctxp);
2932 return (DNS_R_CONTINUE);
2933 }
2934
2935 dns_loadctx_detach(&lctx);
2936 return (result);
2937 }
2938
2939 /*
2940 * Grow the slab of dns_rdatalist_t structures.
2941 * Re-link glue and current list.
2942 */
2943 static dns_rdatalist_t *
grow_rdatalist(int new_len,dns_rdatalist_t * oldlist,int old_len,rdatalist_head_t * current,rdatalist_head_t * glue,isc_mem_t * mctx)2944 grow_rdatalist(int new_len, dns_rdatalist_t *oldlist, int old_len,
2945 rdatalist_head_t *current, rdatalist_head_t *glue,
2946 isc_mem_t *mctx) {
2947 dns_rdatalist_t *newlist;
2948 int rdlcount = 0;
2949 ISC_LIST(dns_rdatalist_t) save;
2950 dns_rdatalist_t *this;
2951
2952 newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
2953 if (newlist == NULL) {
2954 return (NULL);
2955 }
2956
2957 ISC_LIST_INIT(save);
2958 while ((this = ISC_LIST_HEAD(*current)) != NULL) {
2959 ISC_LIST_UNLINK(*current, this, link);
2960 ISC_LIST_APPEND(save, this, link);
2961 }
2962 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2963 ISC_LIST_UNLINK(save, this, link);
2964 INSIST(rdlcount < new_len);
2965 newlist[rdlcount] = *this;
2966 ISC_LIST_APPEND(*current, &newlist[rdlcount], link);
2967 rdlcount++;
2968 }
2969
2970 ISC_LIST_INIT(save);
2971 while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
2972 ISC_LIST_UNLINK(*glue, this, link);
2973 ISC_LIST_APPEND(save, this, link);
2974 }
2975 while ((this = ISC_LIST_HEAD(save)) != NULL) {
2976 ISC_LIST_UNLINK(save, this, link);
2977 INSIST(rdlcount < new_len);
2978 newlist[rdlcount] = *this;
2979 ISC_LIST_APPEND(*glue, &newlist[rdlcount], link);
2980 rdlcount++;
2981 }
2982
2983 INSIST(rdlcount == old_len);
2984 if (oldlist != NULL) {
2985 isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
2986 }
2987 return (newlist);
2988 }
2989
2990 /*
2991 * Grow the slab of rdata structs.
2992 * Re-link the current and glue chains.
2993 */
2994 static dns_rdata_t *
grow_rdata(int new_len,dns_rdata_t * oldlist,int old_len,rdatalist_head_t * current,rdatalist_head_t * glue,isc_mem_t * mctx)2995 grow_rdata(int new_len, dns_rdata_t *oldlist, int old_len,
2996 rdatalist_head_t *current, rdatalist_head_t *glue, isc_mem_t *mctx) {
2997 dns_rdata_t *newlist;
2998 int rdcount = 0;
2999 ISC_LIST(dns_rdata_t) save;
3000 dns_rdatalist_t *this;
3001 dns_rdata_t *rdata;
3002
3003 newlist = isc_mem_get(mctx, new_len * sizeof(*newlist));
3004 if (newlist == NULL) {
3005 return (NULL);
3006 }
3007 memset(newlist, 0, new_len * sizeof(*newlist));
3008
3009 /*
3010 * Copy current relinking.
3011 */
3012 this = ISC_LIST_HEAD(*current);
3013 while (this != NULL) {
3014 ISC_LIST_INIT(save);
3015 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
3016 ISC_LIST_UNLINK(this->rdata, rdata, link);
3017 ISC_LIST_APPEND(save, rdata, link);
3018 }
3019 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
3020 ISC_LIST_UNLINK(save, rdata, link);
3021 INSIST(rdcount < new_len);
3022 newlist[rdcount] = *rdata;
3023 ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
3024 rdcount++;
3025 }
3026 this = ISC_LIST_NEXT(this, link);
3027 }
3028
3029 /*
3030 * Copy glue relinking.
3031 */
3032 this = ISC_LIST_HEAD(*glue);
3033 while (this != NULL) {
3034 ISC_LIST_INIT(save);
3035 while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
3036 ISC_LIST_UNLINK(this->rdata, rdata, link);
3037 ISC_LIST_APPEND(save, rdata, link);
3038 }
3039 while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
3040 ISC_LIST_UNLINK(save, rdata, link);
3041 INSIST(rdcount < new_len);
3042 newlist[rdcount] = *rdata;
3043 ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
3044 rdcount++;
3045 }
3046 this = ISC_LIST_NEXT(this, link);
3047 }
3048 INSIST(rdcount == old_len || rdcount == 0);
3049 if (oldlist != NULL) {
3050 isc_mem_put(mctx, oldlist, old_len * sizeof(*oldlist));
3051 }
3052 return (newlist);
3053 }
3054
3055 static uint32_t
resign_fromlist(dns_rdatalist_t * this,dns_loadctx_t * lctx)3056 resign_fromlist(dns_rdatalist_t *this, dns_loadctx_t *lctx) {
3057 dns_rdata_t *rdata;
3058 dns_rdata_rrsig_t sig;
3059 uint32_t when;
3060
3061 rdata = ISC_LIST_HEAD(this->rdata);
3062 INSIST(rdata != NULL);
3063 (void)dns_rdata_tostruct(rdata, &sig, NULL);
3064 if (isc_serial_gt(sig.timesigned, lctx->now)) {
3065 when = lctx->now;
3066 } else {
3067 when = sig.timeexpire - lctx->resign;
3068 }
3069
3070 rdata = ISC_LIST_NEXT(rdata, link);
3071 while (rdata != NULL) {
3072 (void)dns_rdata_tostruct(rdata, &sig, NULL);
3073 if (isc_serial_gt(sig.timesigned, lctx->now)) {
3074 when = lctx->now;
3075 } else if (sig.timeexpire - lctx->resign < when) {
3076 when = sig.timeexpire - lctx->resign;
3077 }
3078 rdata = ISC_LIST_NEXT(rdata, link);
3079 }
3080 return (when);
3081 }
3082
3083 /*
3084 * Convert each element from a rdatalist_t to rdataset then call commit.
3085 * Unlink each element as we go.
3086 */
3087
3088 static isc_result_t
commit(dns_rdatacallbacks_t * callbacks,dns_loadctx_t * lctx,rdatalist_head_t * head,dns_name_t * owner,const char * source,unsigned int line)3089 commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
3090 rdatalist_head_t *head, dns_name_t *owner, const char *source,
3091 unsigned int line) {
3092 dns_rdatalist_t *this;
3093 dns_rdataset_t dataset;
3094 isc_result_t result;
3095 char namebuf[DNS_NAME_FORMATSIZE];
3096 void (*error)(struct dns_rdatacallbacks *, const char *, ...);
3097
3098 this = ISC_LIST_HEAD(*head);
3099 error = callbacks->error;
3100
3101 if (this == NULL) {
3102 return (ISC_R_SUCCESS);
3103 }
3104 do {
3105 dns_rdataset_init(&dataset);
3106 RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset) ==
3107 ISC_R_SUCCESS);
3108 dataset.trust = dns_trust_ultimate;
3109 /*
3110 * If this is a secure dynamic zone set the re-signing time.
3111 */
3112 if (dataset.type == dns_rdatatype_rrsig &&
3113 (lctx->options & DNS_MASTER_RESIGN) != 0)
3114 {
3115 dataset.attributes |= DNS_RDATASETATTR_RESIGN;
3116 dataset.resign = resign_fromlist(this, lctx);
3117 }
3118 result = ((*callbacks->add)(callbacks->add_private, owner,
3119 &dataset));
3120 if (result == ISC_R_NOMEMORY) {
3121 (*error)(callbacks, "dns_master_load: %s",
3122 dns_result_totext(result));
3123 } else if (result != ISC_R_SUCCESS) {
3124 dns_name_format(owner, namebuf, sizeof(namebuf));
3125 if (source != NULL) {
3126 (*error)(callbacks, "%s: %s:%lu: %s: %s",
3127 "dns_master_load", source, line,
3128 namebuf, dns_result_totext(result));
3129 } else {
3130 (*error)(callbacks, "%s: %s: %s",
3131 "dns_master_load", namebuf,
3132 dns_result_totext(result));
3133 }
3134 }
3135 if (MANYERRS(lctx, result)) {
3136 SETRESULT(lctx, result);
3137 } else if (result != ISC_R_SUCCESS) {
3138 return (result);
3139 }
3140 ISC_LIST_UNLINK(*head, this, link);
3141 this = ISC_LIST_HEAD(*head);
3142 } while (this != NULL);
3143 return (ISC_R_SUCCESS);
3144 }
3145
3146 /*
3147 * Returns true if one of the NS rdata's contains 'owner'.
3148 */
3149
3150 static bool
is_glue(rdatalist_head_t * head,dns_name_t * owner)3151 is_glue(rdatalist_head_t *head, dns_name_t *owner) {
3152 dns_rdatalist_t *this;
3153 dns_rdata_t *rdata;
3154 isc_region_t region;
3155 dns_name_t name;
3156
3157 /*
3158 * Find NS rrset.
3159 */
3160 this = ISC_LIST_HEAD(*head);
3161 while (this != NULL) {
3162 if (this->type == dns_rdatatype_ns) {
3163 break;
3164 }
3165 this = ISC_LIST_NEXT(this, link);
3166 }
3167 if (this == NULL) {
3168 return (false);
3169 }
3170
3171 rdata = ISC_LIST_HEAD(this->rdata);
3172 while (rdata != NULL) {
3173 dns_name_init(&name, NULL);
3174 dns_rdata_toregion(rdata, ®ion);
3175 dns_name_fromregion(&name, ®ion);
3176 if (dns_name_equal(&name, owner)) {
3177 return (true);
3178 }
3179 rdata = ISC_LIST_NEXT(rdata, link);
3180 }
3181 return (false);
3182 }
3183
3184 static void
load_quantum(isc_task_t * task,isc_event_t * event)3185 load_quantum(isc_task_t *task, isc_event_t *event) {
3186 isc_result_t result;
3187 dns_loadctx_t *lctx;
3188
3189 REQUIRE(event != NULL);
3190 lctx = event->ev_arg;
3191 REQUIRE(DNS_LCTX_VALID(lctx));
3192
3193 if (atomic_load_acquire(&lctx->canceled)) {
3194 result = ISC_R_CANCELED;
3195 } else {
3196 result = (lctx->load)(lctx);
3197 }
3198 if (result == DNS_R_CONTINUE) {
3199 event->ev_arg = lctx;
3200 isc_task_send(task, &event);
3201 } else {
3202 (lctx->done)(lctx->done_arg, result);
3203 isc_event_free(&event);
3204 dns_loadctx_detach(&lctx);
3205 }
3206 }
3207
3208 static isc_result_t
task_send(dns_loadctx_t * lctx)3209 task_send(dns_loadctx_t *lctx) {
3210 isc_event_t *event;
3211
3212 event = isc_event_allocate(lctx->mctx, NULL, DNS_EVENT_MASTERQUANTUM,
3213 load_quantum, lctx, sizeof(*event));
3214 isc_task_send(lctx->task, &event);
3215 return (ISC_R_SUCCESS);
3216 }
3217
3218 void
dns_loadctx_cancel(dns_loadctx_t * lctx)3219 dns_loadctx_cancel(dns_loadctx_t *lctx) {
3220 REQUIRE(DNS_LCTX_VALID(lctx));
3221
3222 atomic_store_release(&lctx->canceled, true);
3223 }
3224
3225 void
dns_master_initrawheader(dns_masterrawheader_t * header)3226 dns_master_initrawheader(dns_masterrawheader_t *header) {
3227 memset(header, 0, sizeof(dns_masterrawheader_t));
3228 }
3229