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