Coverage Report

Created: 2025-11-24 06:17

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