Coverage Report

Created: 2026-01-24 06:24

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
10.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
23.6k
#define RDSZ 512
60
61
399k
#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
17.5k
#define TSIZ (128 * 1024)
71
/*%
72
 * max message size - header - root - type - class - ttl - rdlen
73
 */
74
10.2M
#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
17.5k
#define TOKENSIZ (8 * 1024)
83
84
/*%
85
 * Buffers sizes for $GENERATE.
86
 */
87
9.91M
#define DNS_MASTER_LHS 2048
88
9.91M
#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
17.5k
#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
793k
#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
15.9k
#define LCTX_MANYERRORS(lctx) (((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
208
209
#define GETTOKENERR(lexer, options, token, eol, err)                         \
210
726k
  do {                                                                 \
211
726k
    result = gettoken(lexer, options, token, eol, callbacks);    \
212
726k
    switch (result) {                                            \
213
725k
    case ISC_R_SUCCESS:                                          \
214
725k
      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
953
    default:                                                     \
235
953
      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
953
        goto log_and_cleanup;                        \
242
726k
    }                                                            \
243
726k
    if ((token)->type == isc_tokentype_special) {                \
244
179
      result = DNS_R_SYNTAX;                               \
245
179
      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
179
        goto log_and_cleanup;                        \
252
179
    }                                                            \
253
725k
  } while (0)
254
#define GETTOKEN(lexer, options, token, eol) \
255
723k
  GETTOKENERR(lexer, options, token, eol, {})
256
257
#define COMMITALL                                                              \
258
907
  do {                                                                   \
259
907
    result = commit(callbacks, lctx, &current_list, ictx->current, \
260
907
        source, ictx->current_line);                   \
261
907
    if (MANYERRS(lctx, result)) {                                  \
262
0
      SETRESULT(lctx, result);                               \
263
907
    } else if (result != ISC_R_SUCCESS)                            \
264
907
      goto insist_and_cleanup;                               \
265
907
    result = commit(callbacks, lctx, &glue_list, ictx->glue,       \
266
903
        source, ictx->glue_line);                      \
267
903
    if (MANYERRS(lctx, result)) {                                  \
268
0
      SETRESULT(lctx, result);                               \
269
903
    } else if (result != ISC_R_SUCCESS)                            \
270
903
      goto insist_and_cleanup;                               \
271
903
    rdcount = 0;                                                   \
272
901
    rdlcount = 0;                                                  \
273
901
    isc_buffer_init(&target, target_mem, target_size);             \
274
901
    rdcount_save = rdcount;                                        \
275
901
    rdlcount_save = rdlcount;                                      \
276
901
  } while (0)
277
278
#define WARNUNEXPECTEDEOF(lexer)                                         \
279
53
  do {                                                             \
280
53
    if (isc_lex_isfile(lexer))                               \
281
53
      (*callbacks->warn)(callbacks,                    \
282
0
             "%s: file does not end with " \
283
0
             "newline",                    \
284
0
             source);                      \
285
53
  } while (0)
286
287
#define EXPECTEOL                                              \
288
12.2k
  do {                                                   \
289
12.2k
    GETTOKEN(lctx->lex, 0, &token, true);          \
290
12.2k
    if (token.type != isc_tokentype_eol) {         \
291
1.76k
      isc_lex_ungettoken(lctx->lex, &token); \
292
1.76k
      result = DNS_R_EXTRATOKEN;             \
293
1.76k
      if (MANYERRS(lctx, result)) {          \
294
0
        SETRESULT(lctx, result);       \
295
0
        LOGIT(result);                 \
296
0
        read_till_eol = true;          \
297
0
        break;                         \
298
1.76k
      } else if (result != ISC_R_SUCCESS)    \
299
1.76k
        goto log_and_cleanup;          \
300
1.76k
    }                                              \
301
12.1k
  } while (0)
302
303
#define MANYERRS(lctx, result)                                     \
304
10.4M
  ((result != ISC_R_SUCCESS) && (result != ISC_R_IOERROR) && \
305
10.4M
   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
10
  if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND ||     \
314
10
      result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES ||     \
315
10
      result == ISC_R_NOPERM)                                            \
316
10
    (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s",           \
317
10
            "dns_master_load", source, line, filename, \
318
10
            isc_result_totext(result));                \
319
10
  else                                                                   \
320
10
    LOGIT(result)
321
322
#define LOGIT(result)                                                       \
323
2.99k
  (*callbacks->error)(callbacks, "%s: %s:%lu: %s", "dns_master_load", \
324
2.99k
          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
10.6M
dns_master_isprimary(dns_loadctx_t *lctx) {
337
10.6M
  return (lctx->options & DNS_MASTER_ZONE) != 0 &&
338
10.6M
         (lctx->options & DNS_MASTER_SECONDARY) == 0 &&
339
10.6M
         (lctx->options & DNS_MASTER_KEY) == 0;
340
10.6M
}
341
342
static isc_result_t
343
gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, bool eol,
344
726k
   dns_rdatacallbacks_t *callbacks) {
345
726k
  isc_result_t result;
346
347
726k
  options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
348
726k
       ISC_LEXOPT_ESCAPE;
349
726k
  result = isc_lex_gettoken(lex, options, token);
350
726k
  if (result != ISC_R_SUCCESS) {
351
153
    switch (result) {
352
153
    default:
353
153
      (*callbacks->error)(callbacks,
354
153
              "dns_master_load: %s:%lu:"
355
153
              " isc_lex_gettoken() failed: %s",
356
153
              isc_lex_getsourcename(lex),
357
153
              isc_lex_getsourceline(lex),
358
153
              isc_result_totext(result));
359
153
      return result;
360
153
    }
361
    /*NOTREACHED*/
362
153
  }
363
726k
  if (eol != true) {
364
177k
    if (token->type == isc_tokentype_eol ||
365
177k
        token->type == isc_tokentype_eof)
366
803
    {
367
803
      {
368
803
        unsigned long int line;
369
803
        const char *what;
370
803
        const char *file;
371
803
        file = isc_lex_getsourcename(lex);
372
803
        line = isc_lex_getsourceline(lex);
373
803
        if (token->type == isc_tokentype_eol) {
374
123
          line--;
375
123
          what = "line";
376
680
        } else {
377
680
          what = "file";
378
680
        }
379
803
        (*callbacks->error)(callbacks,
380
803
                "dns_master_load: %s:%lu: "
381
803
                "unexpected end of %s",
382
803
                file, line, what);
383
803
        return ISC_R_UNEXPECTEDEND;
384
803
      }
385
803
    }
386
177k
  }
387
725k
  return ISC_R_SUCCESS;
388
726k
}
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
17.5k
dns_loadctx_detach(dns_loadctx_t **lctxp) {
402
17.5k
  dns_loadctx_t *lctx;
403
404
17.5k
  REQUIRE(lctxp != NULL);
405
17.5k
  lctx = *lctxp;
406
17.5k
  *lctxp = NULL;
407
17.5k
  REQUIRE(DNS_LCTX_VALID(lctx));
408
409
17.5k
  if (isc_refcount_decrement(&lctx->references) == 1) {
410
17.5k
    loadctx_destroy(lctx);
411
17.5k
  }
412
17.5k
}
413
414
static void
415
17.5k
incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
416
17.5k
  dns_incctx_t *parent;
417
418
17.5k
again:
419
17.5k
  parent = ictx->parent;
420
17.5k
  ictx->parent = NULL;
421
422
17.5k
  isc_mem_put(mctx, ictx, sizeof(*ictx));
423
424
17.5k
  if (parent != NULL) {
425
3
    ictx = parent;
426
3
    goto again;
427
3
  }
428
17.5k
}
429
430
static void
431
17.5k
loadctx_destroy(dns_loadctx_t *lctx) {
432
17.5k
  REQUIRE(DNS_LCTX_VALID(lctx));
433
434
17.5k
  isc_refcount_destroy(&lctx->references);
435
436
17.5k
  lctx->magic = 0;
437
17.5k
  if (lctx->inc != NULL) {
438
17.5k
    incctx_destroy(lctx->mctx, lctx->inc);
439
17.5k
  }
440
441
17.5k
  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
17.5k
  if (lctx->lex != NULL && !lctx->keep_lex) {
451
17.5k
    isc_lex_destroy(&lctx->lex);
452
17.5k
  }
453
454
17.5k
  isc_mem_putanddetach(&lctx->mctx, lctx, sizeof(*lctx));
455
17.5k
}
456
457
static void
458
17.5k
incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
459
17.5k
  dns_incctx_t *ictx;
460
17.5k
  isc_region_t r;
461
17.5k
  int i;
462
463
17.5k
  ictx = isc_mem_get(mctx, sizeof(*ictx));
464
465
87.7k
  for (i = 0; i < NBUFS; i++) {
466
70.2k
    dns_fixedname_init(&ictx->fixed[i]);
467
70.2k
    ictx->in_use[i] = false;
468
70.2k
  }
469
470
17.5k
  ictx->origin_in_use = 0;
471
17.5k
  ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
472
17.5k
  ictx->in_use[ictx->origin_in_use] = true;
473
17.5k
  dns_name_toregion(origin, &r);
474
17.5k
  dns_name_fromregion(ictx->origin, &r);
475
476
17.5k
  ictx->glue = NULL;
477
17.5k
  ictx->current = NULL;
478
17.5k
  ictx->glue_in_use = -1;
479
17.5k
  ictx->current_in_use = -1;
480
17.5k
  ictx->parent = NULL;
481
17.5k
  ictx->drop = false;
482
17.5k
  ictx->glue_line = 0;
483
17.5k
  ictx->current_line = 0;
484
17.5k
  ictx->origin_changed = true;
485
486
17.5k
  *ictxp = ictx;
487
17.5k
}
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
17.5k
         isc_lex_t *lex, dns_loadctx_t **lctxp) {
496
17.5k
  dns_loadctx_t *lctx = NULL;
497
17.5k
  isc_region_t r;
498
499
17.5k
  REQUIRE(lctxp != NULL && *lctxp == NULL);
500
17.5k
  REQUIRE(callbacks != NULL);
501
17.5k
  REQUIRE(callbacks->update != NULL);
502
17.5k
  REQUIRE(callbacks->error != NULL);
503
17.5k
  REQUIRE(callbacks->warn != NULL);
504
17.5k
  REQUIRE(mctx != NULL);
505
17.5k
  REQUIRE(dns_name_isabsolute(top));
506
17.5k
  REQUIRE(dns_name_isabsolute(origin));
507
508
17.5k
  lctx = isc_mem_get(mctx, sizeof(*lctx));
509
17.5k
  *lctx = (dns_loadctx_t){
510
17.5k
    .format = format,
511
17.5k
    .ttl_known = ((options & DNS_MASTER_NOTTL) != 0),
512
17.5k
    .default_ttl_known = ((options & DNS_MASTER_NOTTL) != 0),
513
17.5k
    .warn_1035 = true,
514
17.5k
    .warn_tcr = true,
515
17.5k
    .warn_sigexpired = true,
516
17.5k
    .options = options,
517
17.5k
    .zclass = zclass,
518
17.5k
    .resign = resign,
519
17.5k
    .include_cb = include_cb,
520
17.5k
    .include_arg = include_arg,
521
17.5k
    .first = true,
522
17.5k
    .done = done,
523
17.5k
    .callbacks = callbacks,
524
17.5k
    .done_arg = done_arg,
525
17.5k
  };
526
527
17.5k
  incctx_create(mctx, origin, &lctx->inc);
528
529
17.5k
  switch (format) {
530
17.5k
  case dns_masterformat_text:
531
17.5k
    lctx->openfile = openfile_text;
532
17.5k
    lctx->load = load_text;
533
17.5k
    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
17.5k
  }
541
542
17.5k
  if (lex != NULL) {
543
0
    lctx->lex = lex;
544
0
    lctx->keep_lex = true;
545
17.5k
  } else {
546
17.5k
    isc_lexspecials_t specials;
547
17.5k
    lctx->lex = NULL;
548
17.5k
    isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
549
17.5k
    lctx->keep_lex = false;
550
    /*
551
     * If specials change update dns_test_rdatafromstring()
552
     * in lib/dns/tests/dnstest.c.
553
     */
554
17.5k
    memset(specials, 0, sizeof(specials));
555
17.5k
    specials[0] = 1;
556
17.5k
    specials['('] = 1;
557
17.5k
    specials[')'] = 1;
558
17.5k
    specials['"'] = 1;
559
17.5k
    isc_lex_setspecials(lctx->lex, specials);
560
17.5k
    isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
561
17.5k
  }
562
563
17.5k
  lctx->now = isc_stdtime_now();
564
565
17.5k
  lctx->top = dns_fixedname_initname(&lctx->fixed_top);
566
17.5k
  dns_name_toregion(top, &r);
567
17.5k
  dns_name_fromregion(lctx->top, &r);
568
569
17.5k
  dns_master_initrawheader(&lctx->header);
570
571
17.5k
  isc_refcount_init(&lctx->references, 1); /* Implicit attach. */
572
17.5k
  isc_mem_attach(mctx, &lctx->mctx);
573
574
17.5k
  lctx->magic = DNS_LCTX_MAGIC;
575
17.5k
  *lctxp = lctx;
576
17.5k
  return;
577
17.5k
}
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.54M
  unsigned int value) {
592
1.54M
  unsigned int count = 0;
593
594
  /*
595
   * This reserve space for the NUL string terminator.
596
   */
597
1.54M
  if (length > 0U) {
598
1.54M
    *numbuf = '\0';
599
1.54M
    length--;
600
1.54M
  }
601
272M
  do {
602
272M
    char val = hex[(value & 0x0f) + ((mode == 'n') ? 0 : 16)];
603
272M
    value >>= 4;
604
272M
    if (length > 0U) {
605
13.5M
      *numbuf++ = val;
606
13.5M
      *numbuf = '\0';
607
13.5M
      length--;
608
13.5M
    }
609
272M
    if (width > 0) {
610
268M
      width--;
611
268M
    }
612
272M
    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
272M
    if (width > 0 || value != 0) {
619
271M
      if (length > 0U) {
620
12.3M
        *numbuf++ = '.';
621
12.3M
        *numbuf = '\0';
622
12.3M
        length--;
623
12.3M
      }
624
271M
      if (width > 0) {
625
267M
        width--;
626
267M
      }
627
271M
      count++;
628
271M
    }
629
272M
  } while (value != 0 || width > 0);
630
1.54M
  return count;
631
1.54M
}
632
633
static isc_result_t
634
19.8M
genname(char *name, int it, char *buffer, size_t length) {
635
19.8M
  char fmt[sizeof("%04000000000d")];
636
19.8M
  char numbuf[128];
637
19.8M
  char *cp;
638
19.8M
  char mode[2] = { 0 };
639
19.8M
  char brace[2] = { 0 };
640
19.8M
  char comma1[2] = { 0 };
641
19.8M
  char comma2[2] = { 0 };
642
19.8M
  int delta = 0;
643
19.8M
  isc_textregion_t r;
644
19.8M
  unsigned int n;
645
19.8M
  unsigned int width;
646
19.8M
  bool nibblemode;
647
648
19.8M
  r.base = buffer;
649
19.8M
  r.length = (unsigned int)length;
650
651
112M
  while (*name != '\0') {
652
92.5M
    if (*name == '$') {
653
10.5M
      name++;
654
10.5M
      if (*name == '$') {
655
379k
        if (r.length == 0) {
656
1
          return ISC_R_NOSPACE;
657
1
        }
658
379k
        r.base[0] = *name++;
659
379k
        isc_textregion_consume(&r, 1);
660
379k
        continue;
661
379k
      }
662
10.1M
      nibblemode = false;
663
10.1M
      strlcpy(fmt, "%d", sizeof(fmt));
664
      /* Get format specifier. */
665
10.1M
      if (*name == '{') {
666
1.70M
        n = sscanf(name,
667
1.70M
             "{%d%1[,}]%u%1[,}]%1[doxXnN]%1[}]",
668
1.70M
             &delta, comma1, &width, comma2, mode,
669
1.70M
             brace);
670
1.70M
        if (n < 2 || n > 6) {
671
9
          return DNS_R_SYNTAX;
672
9
        }
673
1.70M
        if (comma1[0] == '}') {
674
          /* %{delta} */
675
1.62M
        } else if (comma1[0] == ',' && comma2[0] == '}')
676
79.0k
        {
677
          /* %{delta,width} */
678
79.0k
          n = snprintf(fmt, sizeof(fmt), "%%0%ud",
679
79.0k
                 width);
680
1.54M
        } else if (comma1[0] == ',' &&
681
1.54M
             comma2[0] == ',' && mode[0] != 0 &&
682
1.54M
             brace[0] == '}')
683
1.54M
        {
684
          /* %{delta,width,format} */
685
1.54M
          if (mode[0] == 'n' || mode[0] == 'N') {
686
1.54M
            nibblemode = true;
687
1.54M
          }
688
1.54M
          n = snprintf(fmt, sizeof(fmt),
689
1.54M
                 "%%0%u%c", width, mode[0]);
690
1.54M
        } else {
691
3
          return DNS_R_SYNTAX;
692
3
        }
693
1.70M
        if (n >= sizeof(fmt)) {
694
0
          return ISC_R_NOSPACE;
695
0
        }
696
        /* Skip past closing brace. */
697
17.8M
        while (*name != '\0' && *name++ != '}') {
698
16.1M
          continue;
699
16.1M
        }
700
1.70M
      }
701
      /*
702
       * 'it' is >= 0 so we don't need to check for
703
       * underflow.
704
       */
705
10.1M
      if (it > 0 && delta > INT_MAX - it) {
706
1
        return ISC_R_RANGE;
707
1
      }
708
10.1M
      if (nibblemode) {
709
1.54M
        n = nibbles(numbuf, sizeof(numbuf), width,
710
1.54M
              mode[0], it + delta);
711
8.60M
      } else {
712
8.60M
        n = snprintf(numbuf, sizeof(numbuf), fmt,
713
8.60M
               it + delta);
714
8.60M
      }
715
10.1M
      if (n >= sizeof(numbuf)) {
716
24
        return ISC_R_NOSPACE;
717
24
      }
718
10.1M
      cp = numbuf;
719
82.3M
      while (*cp != '\0') {
720
72.1M
        if (r.length == 0) {
721
1
          return ISC_R_NOSPACE;
722
1
        }
723
72.1M
        r.base[0] = *cp++;
724
72.1M
        isc_textregion_consume(&r, 1);
725
72.1M
      }
726
82.0M
    } else if (*name == '\\') {
727
283k
      if (r.length == 0) {
728
1
        return ISC_R_NOSPACE;
729
1
      }
730
283k
      r.base[0] = *name++;
731
283k
      isc_textregion_consume(&r, 1);
732
283k
      if (*name == '\0') {
733
3.17k
        continue;
734
3.17k
      }
735
280k
      if (r.length == 0) {
736
1
        return ISC_R_NOSPACE;
737
1
      }
738
280k
      r.base[0] = *name++;
739
280k
      isc_textregion_consume(&r, 1);
740
81.7M
    } else {
741
81.7M
      if (r.length == 0) {
742
1
        return ISC_R_NOSPACE;
743
1
      }
744
81.7M
      r.base[0] = *name++;
745
81.7M
      isc_textregion_consume(&r, 1);
746
81.7M
    }
747
92.5M
  }
748
19.8M
  if (r.length == 0) {
749
1
    return ISC_R_NOSPACE;
750
1
  }
751
19.8M
  r.base[0] = '\0';
752
19.8M
  return ISC_R_SUCCESS;
753
19.8M
}
754
755
static isc_result_t
756
generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
757
4.62k
   const char *source, unsigned int line) {
758
4.62k
  char *target_mem = NULL;
759
4.62k
  char *lhsbuf = NULL;
760
4.62k
  char *rhsbuf = NULL;
761
4.62k
  dns_fixedname_t ownerfixed;
762
4.62k
  dns_name_t *owner;
763
4.62k
  dns_rdata_t rdata = DNS_RDATA_INIT;
764
4.62k
  dns_rdatacallbacks_t *callbacks;
765
4.62k
  dns_rdatalist_t rdatalist;
766
4.62k
  dns_rdatatype_t type;
767
4.62k
  rdatalist_head_t head;
768
4.62k
  int target_size = MINTSIZ; /* only one rdata at a time */
769
4.62k
  isc_buffer_t buffer;
770
4.62k
  isc_buffer_t target;
771
4.62k
  isc_result_t result;
772
4.62k
  isc_textregion_t r;
773
4.62k
  int n, start, stop, step = 0;
774
4.62k
  unsigned int i;
775
4.62k
  dns_incctx_t *ictx;
776
4.62k
  char dummy[2];
777
778
4.62k
  ictx = lctx->inc;
779
4.62k
  callbacks = lctx->callbacks;
780
4.62k
  owner = dns_fixedname_initname(&ownerfixed);
781
4.62k
  ISC_LIST_INIT(head);
782
783
4.62k
  target_mem = isc_mem_get(lctx->mctx, target_size);
784
4.62k
  rhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_RHS);
785
4.62k
  lhsbuf = isc_mem_get(lctx->mctx, DNS_MASTER_LHS);
786
4.62k
  isc_buffer_init(&target, target_mem, target_size);
787
788
4.62k
  n = sscanf(range, "%d-%d%1[/]%d", &start, &stop, dummy, &step);
789
4.62k
  if ((n != 2 && n != 4) || (start < 0) || (stop < 0) ||
790
4.55k
      (n == 4 && step < 1) || (stop < start))
791
106
  {
792
106
    (*callbacks->error)(callbacks, "%s: %s:%lu: invalid range '%s'",
793
106
            "$GENERATE", source, line, range);
794
106
    result = DNS_R_SYNTAX;
795
106
    goto insist_cleanup;
796
106
  }
797
4.52k
  if (n == 2) {
798
4.30k
    step = 1;
799
4.30k
  }
800
801
  /*
802
   * Get type.
803
   */
804
4.52k
  r.base = gtype;
805
4.52k
  r.length = strlen(gtype);
806
4.52k
  result = dns_rdatatype_fromtext(&type, &r);
807
4.52k
  if (result != ISC_R_SUCCESS) {
808
32
    (*callbacks->error)(callbacks,
809
32
            "%s: %s:%lu: unknown RR type '%s'",
810
32
            "$GENERATE", source, line, gtype);
811
32
    goto insist_cleanup;
812
32
  }
813
814
  /*
815
   * RFC2930: TKEY and TSIG are not allowed to be loaded
816
   * from master files.
817
   */
818
4.49k
  if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
819
1
    (*callbacks->error)(callbacks, "%s: %s:%lu: meta RR type '%s'",
820
1
            "$GENERATE", source, line, gtype);
821
1
    result = DNS_R_METATYPE;
822
1
    goto insist_cleanup;
823
1
  }
824
825
9.91M
  for (i = start; i <= (unsigned int)stop; i += step) {
826
9.91M
    result = genname(lhs, i, lhsbuf, DNS_MASTER_LHS);
827
9.91M
    if (result != ISC_R_SUCCESS) {
828
35
      goto error_cleanup;
829
35
    }
830
9.91M
    result = genname(rhs, i, rhsbuf, DNS_MASTER_RHS);
831
9.91M
    if (result != ISC_R_SUCCESS) {
832
8
      goto error_cleanup;
833
8
    }
834
835
9.91M
    isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
836
9.91M
    isc_buffer_add(&buffer, strlen(lhsbuf));
837
9.91M
    isc_buffer_setactive(&buffer, strlen(lhsbuf));
838
9.91M
    result = dns_name_fromtext(owner, &buffer, ictx->origin, 0);
839
9.91M
    if (result != ISC_R_SUCCESS) {
840
8
      goto error_cleanup;
841
8
    }
842
843
9.91M
    if (dns_master_isprimary(lctx) &&
844
9.91M
        !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
9.91M
    isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
859
9.91M
    isc_buffer_add(&buffer, strlen(rhsbuf));
860
9.91M
    isc_buffer_setactive(&buffer, strlen(rhsbuf));
861
862
9.91M
    result = isc_lex_openbuffer(lctx->lex, &buffer);
863
9.91M
    if (result != ISC_R_SUCCESS) {
864
0
      goto error_cleanup;
865
0
    }
866
867
9.91M
    isc_buffer_init(&target, target_mem, target_size);
868
9.91M
    result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
869
9.91M
              lctx->lex, ictx->origin, 0,
870
9.91M
              lctx->mctx, &target, callbacks);
871
9.91M
    RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
872
9.91M
    if (result != ISC_R_SUCCESS) {
873
128
      goto error_cleanup;
874
128
    }
875
876
9.91M
    dns_rdatalist_init(&rdatalist);
877
9.91M
    rdatalist.type = type;
878
9.91M
    rdatalist.rdclass = lctx->zclass;
879
9.91M
    rdatalist.ttl = lctx->ttl;
880
9.91M
    ISC_LIST_PREPEND(head, &rdatalist, link);
881
9.91M
    ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
882
9.91M
    result = commit(callbacks, lctx, &head, owner, source, line);
883
9.91M
    ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
884
9.91M
    if (result != ISC_R_SUCCESS) {
885
14
      goto error_cleanup;
886
14
    }
887
9.91M
    dns_rdata_reset(&rdata);
888
9.91M
  }
889
4.29k
  result = ISC_R_SUCCESS;
890
4.29k
  goto cleanup;
891
892
193
error_cleanup:
893
193
  (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s", source, line,
894
193
          isc_result_totext(result));
895
896
332
insist_cleanup:
897
332
  INSIST(result != ISC_R_SUCCESS);
898
899
4.62k
cleanup:
900
4.62k
  if (target_mem != NULL) {
901
4.62k
    isc_mem_put(lctx->mctx, target_mem, target_size);
902
4.62k
  }
903
4.62k
  if (lhsbuf != NULL) {
904
4.62k
    isc_mem_put(lctx->mctx, lhsbuf, DNS_MASTER_LHS);
905
4.62k
  }
906
4.62k
  if (rhsbuf != NULL) {
907
4.62k
    isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_RHS);
908
4.62k
  }
909
4.62k
  return result;
910
332
}
911
912
static void
913
limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source,
914
27.0k
    unsigned int line, uint32_t *ttlp) {
915
27.0k
  if (*ttlp > 0x7fffffffUL) {
916
739
    (callbacks->warn)(callbacks,
917
739
          "%s: %s:%lu: "
918
739
          "$TTL %lu > MAXTTL, "
919
739
          "setting $TTL to 0",
920
739
          "dns_master_load", source, line, *ttlp);
921
739
    *ttlp = 0;
922
739
  }
923
27.0k
}
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
15
openfile_text(dns_loadctx_t *lctx, const char *master_file) {
986
15
  return isc_lex_openfile(lctx->lex, master_file);
987
15
}
988
989
static int
990
127k
find_free_name(dns_incctx_t *incctx) {
991
127k
  int i;
992
993
311k
  for (i = 0; i < (NBUFS - 1); i++) {
994
310k
    if (!incctx->in_use[i]) {
995
126k
      break;
996
126k
    }
997
310k
  }
998
127k
  INSIST(!incctx->in_use[i]);
999
127k
  return i;
1000
127k
}
1001
1002
static isc_result_t
1003
17.5k
load_text(dns_loadctx_t *lctx) {
1004
17.5k
  dns_rdataclass_t rdclass;
1005
17.5k
  dns_rdatatype_t type, covers;
1006
17.5k
  uint32_t ttl_offset = 0;
1007
17.5k
  dns_name_t *new_name = NULL;
1008
17.5k
  bool current_has_delegation = false;
1009
17.5k
  bool finish_origin = false;
1010
17.5k
  bool finish_include = false;
1011
17.5k
  bool read_till_eol = false;
1012
17.5k
  bool initialws;
1013
17.5k
  char *include_file = NULL;
1014
17.5k
  isc_token_t token;
1015
17.5k
  isc_result_t result = ISC_R_UNEXPECTED;
1016
17.5k
  rdatalist_head_t glue_list;
1017
17.5k
  rdatalist_head_t current_list;
1018
17.5k
  dns_rdatalist_t *rdatalist = NULL;
1019
17.5k
  dns_rdatalist_t *new_rdatalist = NULL;
1020
17.5k
  int rdlcount = 0;
1021
17.5k
  int rdlcount_save = 0;
1022
17.5k
  int rdatalist_size = 0;
1023
17.5k
  isc_buffer_t buffer;
1024
17.5k
  isc_buffer_t target;
1025
17.5k
  isc_buffer_t target_ft;
1026
17.5k
  isc_buffer_t target_save;
1027
17.5k
  dns_rdata_t *rdata = NULL;
1028
17.5k
  dns_rdata_t *new_rdata = NULL;
1029
17.5k
  int rdcount = 0;
1030
17.5k
  int rdcount_save = 0;
1031
17.5k
  int rdata_size = 0;
1032
17.5k
  unsigned char *target_mem = NULL;
1033
17.5k
  int target_size = TSIZ;
1034
17.5k
  int new_in_use;
1035
17.5k
  isc_mem_t *mctx = NULL;
1036
17.5k
  dns_rdatacallbacks_t *callbacks = NULL;
1037
17.5k
  dns_incctx_t *ictx = NULL;
1038
17.5k
  char *range = NULL;
1039
17.5k
  char *lhs = NULL;
1040
17.5k
  char *gtype = NULL;
1041
17.5k
  char *rhs = NULL;
1042
17.5k
  const char *source = NULL;
1043
17.5k
  unsigned long line = 0;
1044
17.5k
  bool explicit_ttl;
1045
17.5k
  char classname1[DNS_RDATACLASS_FORMATSIZE];
1046
17.5k
  char classname2[DNS_RDATACLASS_FORMATSIZE];
1047
17.5k
  unsigned int options = 0;
1048
1049
17.5k
  REQUIRE(DNS_LCTX_VALID(lctx));
1050
17.5k
  callbacks = lctx->callbacks;
1051
17.5k
  mctx = lctx->mctx;
1052
17.5k
  ictx = lctx->inc;
1053
1054
17.5k
  ISC_LIST_INIT(glue_list);
1055
17.5k
  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
17.5k
  target_mem = isc_mem_get(mctx, target_size);
1062
17.5k
  isc_buffer_init(&target, target_mem, target_size);
1063
17.5k
  target_save = target;
1064
1065
  /* open a database transaction */
1066
17.5k
  if (callbacks->setup != NULL) {
1067
17.5k
    callbacks->setup(callbacks->add_private);
1068
17.5k
  }
1069
1070
17.5k
  if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
1071
0
    options |= DNS_RDATA_CHECKNAMES;
1072
0
  }
1073
17.5k
  if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
1074
0
    options |= DNS_RDATA_CHECKNAMESFAIL;
1075
0
  }
1076
17.5k
  if ((lctx->options & DNS_MASTER_CHECKMX) != 0) {
1077
0
    options |= DNS_RDATA_CHECKMX;
1078
0
  }
1079
17.5k
  if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0) {
1080
0
    options |= DNS_RDATA_CHECKMXFAIL;
1081
0
  }
1082
17.5k
  source = isc_lex_getsourcename(lctx->lex);
1083
347k
  while (true) {
1084
347k
    dns_rdatalist_t *this = NULL;
1085
1086
347k
    if (atomic_load_acquire(&lctx->canceled)) {
1087
0
      result = ISC_R_CANCELED;
1088
0
      goto log_and_cleanup;
1089
0
    }
1090
1091
347k
    initialws = false;
1092
347k
    line = isc_lex_getsourceline(lctx->lex);
1093
347k
    GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
1094
347k
       &token, true);
1095
347k
    line = isc_lex_getsourceline(lctx->lex);
1096
1097
347k
    if (token.type == isc_tokentype_eof) {
1098
1.96k
      if (read_till_eol) {
1099
0
        WARNUNEXPECTEDEOF(lctx->lex);
1100
0
      }
1101
      /* Pop the include stack? */
1102
1.96k
      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
1.96k
      break;
1116
1.96k
    }
1117
1118
345k
    if (token.type == isc_tokentype_eol) {
1119
18.0k
      read_till_eol = false;
1120
18.0k
      continue; /* blank line */
1121
18.0k
    }
1122
1123
327k
    if (read_till_eol) {
1124
0
      continue;
1125
0
    }
1126
1127
327k
    if (token.type == isc_tokentype_initialws) {
1128
      /*
1129
       * Still working on the same name.
1130
       */
1131
189k
      initialws = true;
1132
189k
    } else if (token.type == isc_tokentype_string ||
1133
200
         token.type == isc_tokentype_qstring)
1134
137k
    {
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
137k
      if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
1144
2.95k
        GETTOKEN(lctx->lex, 0, &token, false);
1145
2.95k
        finish_origin = true;
1146
134k
      } else if (strcasecmp(DNS_AS_STR(token), "$TTL") == 0) {
1147
2.68k
        GETTOKENERR(lctx->lex, 0, &token, false,
1148
2.68k
              lctx->ttl = 0;
1149
2.68k
              lctx->default_ttl_known = true;);
1150
2.68k
        result = dns_ttl_fromtext(
1151
2.68k
          &token.value.as_textregion, &lctx->ttl);
1152
2.68k
        if (MANYERRS(lctx, result)) {
1153
0
          SETRESULT(lctx, result);
1154
0
          lctx->ttl = 0;
1155
2.68k
        } else if (result != ISC_R_SUCCESS) {
1156
12
          goto insist_and_cleanup;
1157
12
        }
1158
2.67k
        limit_ttl(callbacks, source, line, &lctx->ttl);
1159
2.67k
        lctx->default_ttl = lctx->ttl;
1160
2.67k
        lctx->default_ttl_known = true;
1161
2.67k
        EXPECTEOL;
1162
2.61k
        continue;
1163
131k
      } else if (strcasecmp(DNS_AS_STR(token), "$INCLUDE") ==
1164
131k
           0)
1165
25
      {
1166
25
        COMMITALL;
1167
23
        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
23
        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
22
        GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1190
19
           false);
1191
19
        if (include_file != NULL) {
1192
0
          isc_mem_free(mctx, include_file);
1193
0
        }
1194
19
        include_file =
1195
19
          isc_mem_strdup(mctx, DNS_AS_STR(token));
1196
19
        GETTOKEN(lctx->lex, 0, &token, true);
1197
1198
17
        if (token.type == isc_tokentype_eol ||
1199
16
            token.type == isc_tokentype_eof)
1200
7
        {
1201
7
          if (token.type == isc_tokentype_eof) {
1202
6
            WARNUNEXPECTEDEOF(lctx->lex);
1203
6
          }
1204
          /*
1205
           * No origin field.
1206
           */
1207
7
          result = pushfile(include_file,
1208
7
                ictx->origin, lctx);
1209
7
          if (MANYERRS(lctx, result)) {
1210
0
            SETRESULT(lctx, result);
1211
0
            LOGITFILE(result, include_file);
1212
0
            continue;
1213
7
          } else if (result != ISC_R_SUCCESS) {
1214
6
            LOGITFILE(result, include_file);
1215
6
            goto insist_and_cleanup;
1216
6
          }
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
7
        }
1224
        /*
1225
         * There is an origin field.  Fall through
1226
         * to domain name processing code and do
1227
         * the actual inclusion later.
1228
         */
1229
10
        finish_include = true;
1230
131k
      } else if (strcasecmp(DNS_AS_STR(token), "$DATE") == 0)
1231
2.40k
      {
1232
2.40k
        int64_t dump_time64;
1233
2.40k
        isc_stdtime_t dump_time;
1234
2.40k
        isc_stdtime_t current_time = isc_stdtime_now();
1235
2.40k
        GETTOKEN(lctx->lex, 0, &token, false);
1236
2.40k
        result = dns_time64_fromtext(DNS_AS_STR(token),
1237
2.40k
                   &dump_time64);
1238
2.40k
        if (MANYERRS(lctx, result)) {
1239
0
          SETRESULT(lctx, result);
1240
0
          LOGIT(result);
1241
0
          dump_time64 = 0;
1242
2.40k
        } else if (result != ISC_R_SUCCESS) {
1243
52
          goto log_and_cleanup;
1244
52
        }
1245
2.35k
        dump_time = (isc_stdtime_t)dump_time64;
1246
2.35k
        if (dump_time != dump_time64) {
1247
38
          UNEXPECTED_ERROR("%s: %s:%lu: $DATE "
1248
38
               "outside epoch",
1249
38
               "dns_master_load",
1250
38
               source, line);
1251
38
          result = ISC_R_UNEXPECTED;
1252
38
          goto insist_and_cleanup;
1253
38
        }
1254
2.31k
        if (dump_time > current_time) {
1255
413
          UNEXPECTED_ERROR("%s: %s:%lu: "
1256
413
               "$DATE in future, "
1257
413
               "using current date",
1258
413
               "dns_master_load",
1259
413
               source, line);
1260
413
          dump_time = current_time;
1261
413
        }
1262
2.31k
        ttl_offset = current_time - dump_time;
1263
2.31k
        EXPECTEOL;
1264
2.30k
        continue;
1265
129k
      } else if (strcasecmp(DNS_AS_STR(token), "$GENERATE") ==
1266
129k
           0)
1267
4.69k
      {
1268
        /*
1269
         * Lazy cleanup.
1270
         */
1271
4.69k
        if (range != NULL) {
1272
2.31k
          isc_mem_free(mctx, range);
1273
2.31k
        }
1274
4.69k
        if (lhs != NULL) {
1275
2.31k
          isc_mem_free(mctx, lhs);
1276
2.31k
        }
1277
4.69k
        if (gtype != NULL) {
1278
2.31k
          isc_mem_free(mctx, gtype);
1279
2.31k
        }
1280
4.69k
        if (rhs != NULL) {
1281
2.31k
          isc_mem_free(mctx, rhs);
1282
2.31k
        }
1283
4.69k
        range = lhs = gtype = rhs = NULL;
1284
        /* RANGE */
1285
4.69k
        GETTOKEN(lctx->lex, 0, &token, false);
1286
4.69k
        range = isc_mem_strdup(mctx, DNS_AS_STR(token));
1287
        /* LHS */
1288
4.69k
        GETTOKEN(lctx->lex, 0, &token, false);
1289
4.68k
        lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1290
4.68k
        rdclass = 0;
1291
4.68k
        explicit_ttl = false;
1292
        /* CLASS? */
1293
4.68k
        GETTOKEN(lctx->lex, 0, &token, false);
1294
4.68k
        if (dns_rdataclass_fromtext(
1295
4.68k
              &rdclass,
1296
4.68k
              &token.value.as_textregion) ==
1297
4.68k
            ISC_R_SUCCESS)
1298
199
        {
1299
199
          GETTOKEN(lctx->lex, 0, &token, false);
1300
199
        }
1301
        /* TTL? */
1302
4.67k
        if (dns_ttl_fromtext(&token.value.as_textregion,
1303
4.67k
                 &lctx->ttl) ==
1304
4.67k
            ISC_R_SUCCESS)
1305
3.09k
        {
1306
3.09k
          limit_ttl(callbacks, source, line,
1307
3.09k
              &lctx->ttl);
1308
3.09k
          lctx->ttl_known = true;
1309
3.09k
          explicit_ttl = true;
1310
3.09k
          GETTOKEN(lctx->lex, 0, &token, false);
1311
3.09k
        }
1312
        /* CLASS? */
1313
4.66k
        if (rdclass == 0 &&
1314
4.46k
            dns_rdataclass_fromtext(
1315
4.46k
              &rdclass,
1316
4.46k
              &token.value.as_textregion) ==
1317
4.46k
              ISC_R_SUCCESS)
1318
214
        {
1319
214
          GETTOKEN(lctx->lex, 0, &token, false);
1320
214
        }
1321
        /* TYPE */
1322
4.65k
        gtype = isc_mem_strdup(mctx, DNS_AS_STR(token));
1323
        /* RHS */
1324
4.65k
        GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
1325
4.64k
           false);
1326
4.64k
        rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
1327
4.64k
        if (!lctx->ttl_known &&
1328
250
            !lctx->default_ttl_known)
1329
1
        {
1330
1
          (*callbacks->error)(callbacks,
1331
1
                  "%s: %s:%lu: no "
1332
1
                  "TTL specified",
1333
1
                  "dns_master_load",
1334
1
                  source, line);
1335
1
          result = DNS_R_NOTTL;
1336
1
          if (MANYERRS(lctx, result)) {
1337
0
            SETRESULT(lctx, result);
1338
0
            lctx->ttl = 0;
1339
1
          } else {
1340
1
            goto insist_and_cleanup;
1341
1
          }
1342
4.64k
        } else if (!explicit_ttl &&
1343
1.58k
             lctx->default_ttl_known)
1344
347
        {
1345
347
          lctx->ttl = lctx->default_ttl;
1346
347
        }
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.64k
        if (rdclass != 0 && rdclass != lctx->zclass) {
1353
11
          goto bad_class;
1354
11
        }
1355
4.62k
        result = generate(lctx, range, lhs, gtype, rhs,
1356
4.62k
              source, line);
1357
4.62k
        if (MANYERRS(lctx, result)) {
1358
0
          SETRESULT(lctx, result);
1359
4.62k
        } else if (result != ISC_R_SUCCESS) {
1360
332
          goto insist_and_cleanup;
1361
332
        }
1362
4.29k
        EXPECTEOL;
1363
2.50k
        continue;
1364
124k
      } else if (strncasecmp(DNS_AS_STR(token), "$", 1) == 0)
1365
252
      {
1366
252
        (callbacks->error)(callbacks,
1367
252
               "%s: %s:%lu: "
1368
252
               "unknown $ directive '%s'",
1369
252
               "dns_master_load", source,
1370
252
               line, DNS_AS_STR(token));
1371
252
        result = DNS_R_SYNTAX;
1372
252
        if (MANYERRS(lctx, result)) {
1373
0
          SETRESULT(lctx, result);
1374
252
        } else {
1375
252
          goto insist_and_cleanup;
1376
252
        }
1377
252
      }
1378
1379
      /*
1380
       * Normal processing resumes.
1381
       */
1382
127k
      new_in_use = find_free_name(ictx);
1383
127k
      new_name = dns_fixedname_initname(
1384
127k
        &ictx->fixed[new_in_use]);
1385
127k
      isc_buffer_init(&buffer, token.value.as_region.base,
1386
127k
          token.value.as_region.length);
1387
127k
      isc_buffer_add(&buffer, token.value.as_region.length);
1388
127k
      isc_buffer_setactive(&buffer,
1389
127k
               token.value.as_region.length);
1390
127k
      result = dns_name_fromtext(new_name, &buffer,
1391
127k
               ictx->origin, 0);
1392
127k
      if (MANYERRS(lctx, result)) {
1393
0
        SETRESULT(lctx, result);
1394
0
        LOGIT(result);
1395
0
        read_till_eol = true;
1396
0
        continue;
1397
127k
      } else if (result != ISC_R_SUCCESS) {
1398
38
        goto log_and_cleanup;
1399
38
      }
1400
1401
      /*
1402
       * Finish $ORIGIN / $INCLUDE processing if required.
1403
       */
1404
127k
      if (finish_origin) {
1405
2.95k
        if (ictx->origin_in_use != -1) {
1406
2.95k
          ictx->in_use[ictx->origin_in_use] =
1407
2.95k
            false;
1408
2.95k
        }
1409
2.95k
        ictx->origin_in_use = new_in_use;
1410
2.95k
        ictx->in_use[ictx->origin_in_use] = true;
1411
2.95k
        ictx->origin = new_name;
1412
2.95k
        ictx->origin_changed = true;
1413
2.95k
        finish_origin = false;
1414
2.95k
        EXPECTEOL;
1415
2.94k
        continue;
1416
2.95k
      }
1417
124k
      if (finish_include) {
1418
10
        finish_include = false;
1419
10
        EXPECTEOL;
1420
6
        result = pushfile(include_file, new_name, lctx);
1421
6
        if (MANYERRS(lctx, result)) {
1422
0
          SETRESULT(lctx, result);
1423
0
          LOGITFILE(result, include_file);
1424
0
          continue;
1425
6
        } else if (result != ISC_R_SUCCESS) {
1426
4
          LOGITFILE(result, include_file);
1427
4
          goto insist_and_cleanup;
1428
4
        }
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
6
      }
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
124k
      if (ictx->glue != NULL &&
1448
1.57k
          !dns_name_caseequal(ictx->glue, new_name))
1449
1.15k
      {
1450
1.15k
        result = commit(callbacks, lctx, &glue_list,
1451
1.15k
            ictx->glue, source,
1452
1.15k
            ictx->glue_line);
1453
1.15k
        if (MANYERRS(lctx, result)) {
1454
0
          SETRESULT(lctx, result);
1455
1.15k
        } else if (result != ISC_R_SUCCESS) {
1456
1
          goto insist_and_cleanup;
1457
1
        }
1458
1.15k
        if (ictx->glue_in_use != -1) {
1459
1.15k
          ictx->in_use[ictx->glue_in_use] = false;
1460
1.15k
        }
1461
1.15k
        ictx->glue_in_use = -1;
1462
1.15k
        ictx->glue = NULL;
1463
1.15k
        rdcount = rdcount_save;
1464
1.15k
        rdlcount = rdlcount_save;
1465
1.15k
        target = target_save;
1466
1.15k
      }
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
124k
      if ((ictx->glue == NULL) &&
1476
124k
          (ictx->current == NULL ||
1477
109k
           !dns_name_caseequal(ictx->current, new_name)))
1478
48.6k
      {
1479
48.6k
        if (current_has_delegation &&
1480
4.40k
            is_glue(&current_list, new_name))
1481
1.27k
        {
1482
1.27k
          rdcount_save = rdcount;
1483
1.27k
          rdlcount_save = rdlcount;
1484
1.27k
          target_save = target;
1485
1.27k
          ictx->glue = new_name;
1486
1.27k
          ictx->glue_in_use = new_in_use;
1487
1.27k
          ictx->in_use[ictx->glue_in_use] = true;
1488
47.3k
        } else {
1489
47.3k
          result = commit(callbacks, lctx,
1490
47.3k
              &current_list,
1491
47.3k
              ictx->current, source,
1492
47.3k
              ictx->current_line);
1493
47.3k
          if (MANYERRS(lctx, result)) {
1494
0
            SETRESULT(lctx, result);
1495
47.3k
          } else if (result != ISC_R_SUCCESS) {
1496
35
            goto insist_and_cleanup;
1497
35
          }
1498
47.3k
          rdcount = 0;
1499
47.3k
          rdlcount = 0;
1500
47.3k
          if (ictx->current_in_use != -1) {
1501
32.5k
            ictx->in_use
1502
32.5k
              [ictx->current_in_use] =
1503
32.5k
              false;
1504
32.5k
          }
1505
47.3k
          ictx->current_in_use = new_in_use;
1506
47.3k
          ictx->in_use[ictx->current_in_use] =
1507
47.3k
            true;
1508
47.3k
          ictx->current = new_name;
1509
47.3k
          current_has_delegation = false;
1510
47.3k
          isc_buffer_init(&target, target_mem,
1511
47.3k
              target_size);
1512
47.3k
        }
1513
        /*
1514
         * Check for internal wildcards.
1515
         */
1516
48.6k
        if ((lctx->options &
1517
48.6k
             DNS_MASTER_CHECKWILDCARD) != 0)
1518
0
        {
1519
0
          check_wildcard(ictx, source, line,
1520
0
                   callbacks);
1521
0
        }
1522
48.6k
      }
1523
124k
      if (dns_master_isprimary(lctx) &&
1524
124k
          !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
124k
      } else {
1539
124k
        ictx->drop = false;
1540
124k
      }
1541
124k
    } 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
314k
    type = dns_rdatatype_none;
1565
314k
    rdclass = 0;
1566
1567
314k
    GETTOKEN(lctx->lex, 0, &token, initialws);
1568
1569
313k
    if (initialws) {
1570
189k
      if (token.type == isc_tokentype_eol) {
1571
2.87k
        read_till_eol = false;
1572
2.87k
        continue; /* blank line */
1573
2.87k
      }
1574
1575
186k
      if (token.type == isc_tokentype_eof) {
1576
47
        WARNUNEXPECTEDEOF(lctx->lex);
1577
47
        read_till_eol = false;
1578
47
        isc_lex_ungettoken(lctx->lex, &token);
1579
47
        continue;
1580
47
      }
1581
1582
186k
      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
186k
      if (ictx->origin_changed) {
1598
944
        char cbuf[DNS_NAME_FORMATSIZE];
1599
944
        char obuf[DNS_NAME_FORMATSIZE];
1600
944
        dns_name_format(ictx->current, cbuf,
1601
944
            sizeof(cbuf));
1602
944
        dns_name_format(ictx->origin, obuf,
1603
944
            sizeof(obuf));
1604
944
        (*callbacks->warn)(callbacks,
1605
944
               "%s:%lu: record with "
1606
944
               "inherited "
1607
944
               "owner (%s) immediately "
1608
944
               "after "
1609
944
               "$ORIGIN (%s)",
1610
944
               source, line, cbuf, obuf);
1611
944
      }
1612
186k
    }
1613
1614
310k
    ictx->origin_changed = false;
1615
1616
310k
    if (dns_rdataclass_fromtext(&rdclass,
1617
310k
              &token.value.as_textregion) ==
1618
310k
        ISC_R_SUCCESS)
1619
968
    {
1620
968
      GETTOKEN(lctx->lex, 0, &token, false);
1621
968
    }
1622
1623
310k
    explicit_ttl = false;
1624
310k
    result = dns_ttl_fromtext(&token.value.as_textregion,
1625
310k
            &lctx->ttl);
1626
310k
    if (result == ISC_R_SUCCESS) {
1627
21.2k
      limit_ttl(callbacks, source, line, &lctx->ttl);
1628
21.2k
      explicit_ttl = true;
1629
21.2k
      lctx->ttl_known = true;
1630
21.2k
      GETTOKEN(lctx->lex, 0, &token, false);
1631
21.2k
    }
1632
1633
310k
    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
310k
    if (rdclass == 0 &&
1647
309k
        dns_rdataclass_fromtext(&rdclass,
1648
309k
              &token.value.as_textregion) ==
1649
309k
          ISC_R_SUCCESS)
1650
250
    {
1651
250
      GETTOKEN(lctx->lex, 0, &token, false);
1652
250
    }
1653
1654
310k
    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
310k
    result = dns_rdatatype_fromtext(&type,
1668
310k
            &token.value.as_textregion);
1669
310k
    if (result != ISC_R_SUCCESS) {
1670
3.59k
      (*callbacks->warn)(
1671
3.59k
        callbacks, "%s:%lu: unknown RR type '%.*s'",
1672
3.59k
        source, line, token.value.as_textregion.length,
1673
3.59k
        token.value.as_textregion.base);
1674
3.59k
      if (MANYERRS(lctx, result)) {
1675
0
        SETRESULT(lctx, result);
1676
0
        read_till_eol = true;
1677
0
        continue;
1678
3.59k
      } else {
1679
3.59k
        goto insist_and_cleanup;
1680
3.59k
      }
1681
3.59k
    }
1682
1683
    /*
1684
     * If the class specified does not match the zone's class
1685
     * print out a error message and exit.
1686
     */
1687
306k
    if (rdclass != 0 && rdclass != lctx->zclass) {
1688
27
    bad_class:
1689
1690
27
      dns_rdataclass_format(rdclass, classname1,
1691
27
                sizeof(classname1));
1692
27
      dns_rdataclass_format(lctx->zclass, classname2,
1693
27
                sizeof(classname2));
1694
27
      (*callbacks->error)(callbacks,
1695
27
              "%s:%lu: class '%s' != "
1696
27
              "zone class '%s'",
1697
27
              source, line, classname1,
1698
27
              classname2);
1699
27
      result = DNS_R_BADCLASS;
1700
27
      if (MANYERRS(lctx, result)) {
1701
0
        SETRESULT(lctx, result);
1702
0
        read_till_eol = true;
1703
0
        continue;
1704
27
      } else {
1705
27
        goto insist_and_cleanup;
1706
27
      }
1707
27
    }
1708
1709
306k
    if (type == dns_rdatatype_ns && ictx->glue == NULL) {
1710
42.4k
      current_has_delegation = true;
1711
42.4k
    }
1712
1713
    /*
1714
     * RFC1123: MD and MF are not allowed to be loaded from
1715
     * master files.
1716
     */
1717
306k
    if (dns_master_isprimary(lctx) &&
1718
306k
        (type == dns_rdatatype_md || type == dns_rdatatype_mf))
1719
9
    {
1720
9
      char typebuf[DNS_RDATATYPE_FORMATSIZE];
1721
1722
9
      result = DNS_R_OBSOLETE;
1723
1724
9
      dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1725
9
      (*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1726
9
              source, line, "type", typebuf,
1727
9
              isc_result_totext(result));
1728
9
      if (MANYERRS(lctx, result)) {
1729
0
        SETRESULT(lctx, result);
1730
9
      } else {
1731
9
        goto insist_and_cleanup;
1732
9
      }
1733
9
    }
1734
1735
    /*
1736
     * RFC2930: TKEY and TSIG are not allowed to be loaded
1737
     * from master files.
1738
     */
1739
306k
    if (dns_master_isprimary(lctx) && dns_rdatatype_ismeta(type)) {
1740
16
      char typebuf[DNS_RDATATYPE_FORMATSIZE];
1741
1742
16
      result = DNS_R_METATYPE;
1743
1744
16
      dns_rdatatype_format(type, typebuf, sizeof(typebuf));
1745
16
      (*callbacks->error)(callbacks, "%s:%lu: %s '%s': %s",
1746
16
              source, line, "type", typebuf,
1747
16
              isc_result_totext(result));
1748
16
      if (MANYERRS(lctx, result)) {
1749
0
        SETRESULT(lctx, result);
1750
16
      } else {
1751
16
        goto insist_and_cleanup;
1752
16
      }
1753
16
    }
1754
1755
    /*
1756
     * Find a rdata structure.
1757
     */
1758
306k
    if (rdcount == rdata_size) {
1759
11.8k
      new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
1760
11.8k
                 rdata_size, &current_list,
1761
11.8k
                 &glue_list, mctx);
1762
11.8k
      rdata_size += RDSZ;
1763
11.8k
      rdata = new_rdata;
1764
11.8k
    }
1765
1766
    /*
1767
     * Peek at the NS record.
1768
     */
1769
306k
    if (type == dns_rdatatype_ns &&
1770
64.7k
        lctx->zclass == dns_rdataclass_in &&
1771
64.7k
        (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
306k
    options &= ~DNS_RDATA_CHECKREVERSE;
1789
306k
    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
306k
    dns_rdata_init(&rdata[rdcount]);
1834
306k
    target_ft = target;
1835
306k
    result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass, type,
1836
306k
              lctx->lex, ictx->origin, options,
1837
306k
              lctx->mctx, &target, callbacks);
1838
306k
    if (MANYERRS(lctx, result)) {
1839
0
      SETRESULT(lctx, result);
1840
0
      continue;
1841
306k
    } else if (result != ISC_R_SUCCESS) {
1842
7.62k
      goto insist_and_cleanup;
1843
7.62k
    }
1844
1845
299k
    if (ictx->drop) {
1846
0
      target = target_ft;
1847
0
      continue;
1848
0
    }
1849
1850
299k
    if (type == dns_rdatatype_soa &&
1851
1.14k
        (lctx->options & DNS_MASTER_ZONE) != 0 &&
1852
1.14k
        !dns_name_equal(ictx->current, lctx->top))
1853
1
    {
1854
1
      char namebuf[DNS_NAME_FORMATSIZE];
1855
1
      dns_name_format(ictx->current, namebuf,
1856
1
          sizeof(namebuf));
1857
1
      (*callbacks->error)(callbacks,
1858
1
              "%s:%lu: SOA "
1859
1
              "record not at top of zone (%s)",
1860
1
              source, line, namebuf);
1861
1
      result = DNS_R_NOTZONETOP;
1862
1
      if (MANYERRS(lctx, result)) {
1863
0
        SETRESULT(lctx, result);
1864
0
        read_till_eol = true;
1865
0
        target = target_ft;
1866
0
        continue;
1867
1
      } else {
1868
1
        goto insist_and_cleanup;
1869
1
      }
1870
1
    }
1871
1872
299k
    if (type == dns_rdatatype_svcb &&
1873
1.80k
        (lctx->options & DNS_MASTER_ZONE) != 0 &&
1874
1.80k
        (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
299k
    if (dns_rdatatype_atparent(type) &&
1895
688
        dns_master_isprimary(lctx) &&
1896
688
        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
299k
    if (dns_rdatatype_issig(type)) {
1919
22.3k
      covers = dns_rdata_covers(&rdata[rdcount]);
1920
276k
    } else {
1921
276k
      covers = dns_rdatatype_none;
1922
276k
    }
1923
1924
299k
    if (!lctx->ttl_known && !lctx->default_ttl_known) {
1925
661
      if (type == dns_rdatatype_soa) {
1926
55
        (*callbacks->warn)(callbacks,
1927
55
               "%s:%lu: no TTL specified; "
1928
55
               "using SOA MINTTL instead",
1929
55
               source, line);
1930
55
        lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
1931
55
        limit_ttl(callbacks, source, line, &lctx->ttl);
1932
55
        lctx->default_ttl = lctx->ttl;
1933
55
        lctx->default_ttl_known = true;
1934
606
      } 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
606
      } else {
1942
606
        (*callbacks->warn)(callbacks,
1943
606
               "%s:%lu: no TTL specified; "
1944
606
               "zone rejected",
1945
606
               source, line);
1946
606
        result = DNS_R_NOTTL;
1947
606
        if (MANYERRS(lctx, result)) {
1948
0
          SETRESULT(lctx, result);
1949
0
          lctx->ttl = 0;
1950
606
        } else {
1951
606
          goto insist_and_cleanup;
1952
606
        }
1953
606
      }
1954
298k
    } else if (!explicit_ttl && lctx->default_ttl_known) {
1955
21.8k
      lctx->ttl = lctx->default_ttl;
1956
276k
    } else if (!explicit_ttl && lctx->warn_1035) {
1957
3.41k
      (*callbacks->warn)(callbacks,
1958
3.41k
             "%s:%lu: "
1959
3.41k
             "using RFC1035 TTL semantics",
1960
3.41k
             source, line);
1961
3.41k
      lctx->warn_1035 = false;
1962
3.41k
    }
1963
1964
298k
    if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
1965
1.44k
      dns_rdata_rrsig_t sig;
1966
1.44k
      result = dns_rdata_tostruct(&rdata[rdcount], &sig,
1967
1.44k
                NULL);
1968
1.44k
      RUNTIME_CHECK(result == ISC_R_SUCCESS);
1969
1.44k
      if (isc_serial_lt(sig.timeexpire, lctx->now)) {
1970
1.03k
        (*callbacks->warn)(callbacks,
1971
1.03k
               "%s:%lu: "
1972
1.03k
               "signature has expired",
1973
1.03k
               source, line);
1974
1.03k
        lctx->warn_sigexpired = false;
1975
1.03k
      }
1976
1.44k
    }
1977
1978
298k
    if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
1979
2.98k
        lctx->warn_tcr && dns_master_isprimary(lctx))
1980
274
    {
1981
274
      (*callbacks->warn)(callbacks,
1982
274
             "%s:%lu: old style DNSSEC "
1983
274
             " zone detected",
1984
274
             source, line);
1985
274
      lctx->warn_tcr = false;
1986
274
    }
1987
1988
298k
    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
298k
    if (ictx->glue != NULL) {
2011
41.2k
      this = ISC_LIST_HEAD(glue_list);
2012
257k
    } else {
2013
257k
      this = ISC_LIST_HEAD(current_list);
2014
257k
    }
2015
2016
1.28M
    while (this != NULL) {
2017
1.23M
      if (this->type == type && this->covers == covers) {
2018
249k
        break;
2019
249k
      }
2020
990k
      this = ISC_LIST_NEXT(this, link);
2021
990k
    }
2022
2023
298k
    if (this == NULL) {
2024
49.4k
      if (rdlcount == rdatalist_size) {
2025
5.06k
        new_rdatalist = grow_rdatalist(
2026
5.06k
          rdatalist_size + RDLSZ, rdatalist,
2027
5.06k
          rdatalist_size, &current_list,
2028
5.06k
          &glue_list, mctx);
2029
5.06k
        rdatalist = new_rdatalist;
2030
5.06k
        rdatalist_size += RDLSZ;
2031
5.06k
      }
2032
49.4k
      this = &rdatalist[rdlcount++];
2033
49.4k
      dns_rdatalist_init(this);
2034
49.4k
      this->type = type;
2035
49.4k
      this->covers = covers;
2036
49.4k
      this->rdclass = lctx->zclass;
2037
49.4k
      this->ttl = lctx->ttl;
2038
49.4k
      if (ictx->glue != NULL) {
2039
2.79k
        ISC_LIST_INITANDPREPEND(glue_list, this, link);
2040
46.6k
      } else {
2041
46.6k
        ISC_LIST_INITANDPREPEND(current_list, this,
2042
46.6k
              link);
2043
46.6k
      }
2044
249k
    } else if (this->ttl != lctx->ttl) {
2045
2.73k
      (*callbacks->warn)(callbacks,
2046
2.73k
             "%s:%lu: "
2047
2.73k
             "TTL set to prior TTL (%lu)",
2048
2.73k
             source, line, this->ttl);
2049
2.73k
      lctx->ttl = this->ttl;
2050
2.73k
    }
2051
2052
298k
    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
298k
    ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
2066
298k
    if (ictx->glue != NULL) {
2067
41.2k
      ictx->glue_line = line;
2068
257k
    } else {
2069
257k
      ictx->current_line = line;
2070
257k
    }
2071
298k
    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
298k
    if ((target.length - target.used) < MINTSIZ) {
2078
882
      COMMITALL;
2079
882
    }
2080
298k
  next_line:;
2081
298k
  }
2082
2083
  /*
2084
   * Commit what has not yet been committed.
2085
   */
2086
1.96k
  result = commit(callbacks, lctx, &current_list, ictx->current, source,
2087
1.96k
      ictx->current_line);
2088
1.96k
  if (MANYERRS(lctx, result)) {
2089
0
    SETRESULT(lctx, result);
2090
1.96k
  } else if (result != ISC_R_SUCCESS) {
2091
190
    goto insist_and_cleanup;
2092
190
  }
2093
1.77k
  result = commit(callbacks, lctx, &glue_list, ictx->glue, source,
2094
1.77k
      ictx->glue_line);
2095
1.77k
  if (MANYERRS(lctx, result)) {
2096
0
    SETRESULT(lctx, result);
2097
1.77k
  } else if (result != ISC_R_SUCCESS) {
2098
4
    goto insist_and_cleanup;
2099
1.77k
  } else if (lctx->result != ISC_R_SUCCESS) {
2100
0
    result = lctx->result;
2101
1.77k
  } else if (lctx->seen_include) {
2102
0
    result = DNS_R_SEENINCLUDE;
2103
0
  }
2104
2105
1.77k
  goto cleanup;
2106
2107
2.99k
log_and_cleanup:
2108
2.99k
  LOGIT(result);
2109
2110
15.7k
insist_and_cleanup:
2111
15.7k
  INSIST(result != ISC_R_SUCCESS);
2112
2113
17.5k
cleanup:
2114
  /* commit the database transaction */
2115
17.5k
  if (callbacks->commit != NULL) {
2116
17.5k
    callbacks->commit(callbacks->add_private);
2117
17.5k
  }
2118
2119
17.5k
  ISC_LIST_FOREACH(current_list, this, link) {
2120
3.16k
    ISC_LIST_UNLINK(current_list, this, link);
2121
3.16k
  }
2122
17.5k
  ISC_LIST_FOREACH(glue_list, this, link) {
2123
235
    ISC_LIST_UNLINK(glue_list, this, link);
2124
235
  }
2125
17.5k
  if (rdatalist != NULL) {
2126
5.04k
    isc_mem_cput(mctx, rdatalist, rdatalist_size,
2127
5.04k
           sizeof(*rdatalist));
2128
5.04k
  }
2129
17.5k
  if (rdata != NULL) {
2130
11.5k
    isc_mem_cput(mctx, rdata, rdata_size, sizeof(*rdata));
2131
11.5k
  }
2132
17.5k
  if (target_mem != NULL) {
2133
17.5k
    isc_mem_put(mctx, target_mem, target_size);
2134
17.5k
  }
2135
17.5k
  if (include_file != NULL) {
2136
19
    isc_mem_free(mctx, include_file);
2137
19
  }
2138
17.5k
  if (range != NULL) {
2139
2.38k
    isc_mem_free(mctx, range);
2140
2.38k
  }
2141
17.5k
  if (lhs != NULL) {
2142
2.37k
    isc_mem_free(mctx, lhs);
2143
2.37k
  }
2144
17.5k
  if (gtype != NULL) {
2145
2.34k
    isc_mem_free(mctx, gtype);
2146
2.34k
  }
2147
17.5k
  if (rhs != NULL) {
2148
2.32k
    isc_mem_free(mctx, rhs);
2149
2.32k
  }
2150
2151
17.5k
  return result;
2152
15.7k
}
2153
2154
static isc_result_t
2155
13
pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
2156
13
  isc_result_t result;
2157
13
  dns_incctx_t *ictx;
2158
13
  dns_incctx_t *newctx = NULL;
2159
13
  isc_region_t r;
2160
2161
13
  REQUIRE(master_file != NULL);
2162
13
  REQUIRE(DNS_LCTX_VALID(lctx));
2163
2164
13
  ictx = lctx->inc;
2165
13
  lctx->seen_include = true;
2166
2167
13
  incctx_create(lctx->mctx, origin, &newctx);
2168
2169
  /*
2170
   * Push origin_changed.
2171
   */
2172
13
  newctx->origin_changed = ictx->origin_changed;
2173
2174
  /* Set current domain. */
2175
13
  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
13
  CHECK((lctx->openfile)(lctx, master_file));
2187
3
  newctx->parent = ictx;
2188
3
  lctx->inc = newctx;
2189
2190
3
  if (lctx->include_cb != NULL) {
2191
0
    lctx->include_cb(master_file, lctx->include_arg);
2192
0
  }
2193
3
  return ISC_R_SUCCESS;
2194
2195
10
cleanup:
2196
10
  incctx_destroy(lctx->mctx, newctx);
2197
10
  return result;
2198
13
}
2199
2200
/*
2201
 * Fill/check exists buffer with 'len' bytes.  Track remaining bytes to be
2202
 * read when incrementally filling the buffer.
2203
 */
2204
static isc_result_t
2205
read_and_check(bool do_read, isc_buffer_t *buffer, size_t len, FILE *f,
2206
0
         uint32_t *totallen) {
2207
0
  REQUIRE(totallen != NULL);
2208
2209
0
  if (do_read) {
2210
0
    INSIST(isc_buffer_availablelength(buffer) >= len);
2211
0
    RETERR(isc_stdio_read(isc_buffer_used(buffer), 1, len, f,
2212
0
              NULL));
2213
0
    isc_buffer_add(buffer, (unsigned int)len);
2214
0
    if (*totallen < len) {
2215
0
      return ISC_R_RANGE;
2216
0
    }
2217
0
    *totallen -= (uint32_t)len;
2218
0
  } else if (isc_buffer_remaininglength(buffer) < len) {
2219
0
    return ISC_R_RANGE;
2220
0
  }
2221
2222
0
  return ISC_R_SUCCESS;
2223
0
}
2224
2225
static isc_result_t
2226
0
load_header(dns_loadctx_t *lctx) {
2227
0
  isc_result_t result = ISC_R_SUCCESS;
2228
0
  dns_masterrawheader_t header;
2229
0
  dns_rdatacallbacks_t *callbacks;
2230
0
  size_t commonlen = sizeof(header.format) + sizeof(header.version);
2231
0
  size_t remainder;
2232
0
  unsigned char data[sizeof(header)];
2233
0
  isc_buffer_t target;
2234
2235
0
  REQUIRE(DNS_LCTX_VALID(lctx));
2236
2237
0
  if (lctx->format != dns_masterformat_raw) {
2238
0
    return ISC_R_NOTIMPLEMENTED;
2239
0
  }
2240
2241
0
  callbacks = lctx->callbacks;
2242
0
  dns_master_initrawheader(&header);
2243
2244
0
  INSIST(commonlen <= sizeof(header));
2245
0
  isc_buffer_init(&target, data, sizeof(data));
2246
2247
0
  result = isc_stdio_read(data, 1, commonlen, lctx->f, NULL);
2248
0
  if (result != ISC_R_SUCCESS) {
2249
0
    UNEXPECTED_ERROR("isc_stdio_read failed: %s",
2250
0
         isc_result_totext(result));
2251
0
    return result;
2252
0
  }
2253
2254
0
  isc_buffer_add(&target, (unsigned int)commonlen);
2255
0
  header.format = isc_buffer_getuint32(&target);
2256
0
  if (header.format != lctx->format) {
2257
0
    (*callbacks->error)(callbacks,
2258
0
            "dns_master_load: "
2259
0
            "file format mismatch (not raw)");
2260
0
    return ISC_R_NOTIMPLEMENTED;
2261
0
  }
2262
2263
0
  header.version = isc_buffer_getuint32(&target);
2264
2265
0
  switch (header.version) {
2266
0
  case 0:
2267
0
    remainder = sizeof(header.dumptime);
2268
0
    break;
2269
0
  case DNS_RAWFORMAT_VERSION:
2270
0
    remainder = sizeof(header) - commonlen;
2271
0
    break;
2272
0
  default:
2273
0
    (*callbacks->error)(callbacks, "dns_master_load: "
2274
0
                 "unsupported file format "
2275
0
                 "version");
2276
0
    return ISC_R_NOTIMPLEMENTED;
2277
0
  }
2278
2279
0
  result = isc_stdio_read(data + commonlen, 1, remainder, lctx->f, NULL);
2280
0
  if (result != ISC_R_SUCCESS) {
2281
0
    UNEXPECTED_ERROR("isc_stdio_read failed: %s",
2282
0
         isc_result_totext(result));
2283
0
    return result;
2284
0
  }
2285
2286
0
  isc_buffer_add(&target, (unsigned int)remainder);
2287
0
  header.dumptime = isc_buffer_getuint32(&target);
2288
0
  if (header.version == DNS_RAWFORMAT_VERSION) {
2289
0
    header.flags = isc_buffer_getuint32(&target);
2290
0
    header.sourceserial = isc_buffer_getuint32(&target);
2291
0
    header.lastxfrin = isc_buffer_getuint32(&target);
2292
0
  }
2293
2294
0
  lctx->first = false;
2295
0
  lctx->header = header;
2296
2297
0
  return ISC_R_SUCCESS;
2298
0
}
2299
2300
static isc_result_t
2301
0
openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
2302
0
  isc_result_t result;
2303
2304
0
  result = isc_stdio_open(master_file, "rb", &lctx->f);
2305
0
  if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
2306
0
    UNEXPECTED_ERROR("isc_stdio_open() failed: %s",
2307
0
         isc_result_totext(result));
2308
0
  }
2309
2310
0
  return result;
2311
0
}
2312
2313
static isc_result_t
2314
0
load_raw(dns_loadctx_t *lctx) {
2315
0
  isc_result_t result = ISC_R_SUCCESS;
2316
0
  dns_rdatacallbacks_t *callbacks;
2317
0
  unsigned char namebuf[DNS_NAME_MAXWIRE];
2318
0
  dns_fixedname_t fixed;
2319
0
  dns_name_t *name;
2320
0
  rdatalist_head_t head, dummy;
2321
0
  dns_rdatalist_t rdatalist;
2322
0
  isc_mem_t *mctx = lctx->mctx;
2323
0
  dns_rdata_t *rdata = NULL;
2324
0
  unsigned int rdata_size = 0;
2325
0
  int target_size = TSIZ;
2326
0
  isc_buffer_t target, buf;
2327
0
  unsigned char *target_mem = NULL;
2328
0
  dns_decompress_t dctx;
2329
2330
0
  callbacks = lctx->callbacks;
2331
0
  dctx = DNS_DECOMPRESS_NEVER;
2332
2333
0
  if (lctx->first) {
2334
0
    RETERR(load_header(lctx));
2335
0
  }
2336
2337
0
  ISC_LIST_INIT(head);
2338
0
  ISC_LIST_INIT(dummy);
2339
2340
  /*
2341
   * Allocate target_size of buffer space.  This is greater than twice
2342
   * the maximum individual RR data size.
2343
   */
2344
0
  target_mem = isc_mem_get(mctx, target_size);
2345
0
  isc_buffer_init(&target, target_mem, target_size);
2346
2347
0
  name = dns_fixedname_initname(&fixed);
2348
2349
  /* open a database transaction */
2350
0
  if (callbacks->setup != NULL) {
2351
0
    callbacks->setup(callbacks->add_private);
2352
0
  }
2353
2354
  /*
2355
   * In the following loop, we regard any error fatal regardless of
2356
   * whether "MANYERRORS" is set in the context option.  This is because
2357
   * normal errors should already have been checked at creation time.
2358
   * Besides, it is very unlikely that we can recover from an error
2359
   * in this format, and so trying to continue parsing erroneous data
2360
   * does not really make sense.
2361
   */
2362
0
  while (true) {
2363
0
    unsigned int i, rdcount;
2364
0
    uint16_t namelen;
2365
0
    uint32_t totallen;
2366
0
    size_t minlen, readlen;
2367
0
    bool sequential_read = false;
2368
2369
    /* Read the data length */
2370
0
    isc_buffer_clear(&target);
2371
0
    INSIST(isc_buffer_availablelength(&target) >= sizeof(totallen));
2372
0
    result = isc_stdio_read(target.base, 1, sizeof(totallen),
2373
0
          lctx->f, NULL);
2374
0
    if (result == ISC_R_EOF) {
2375
0
      result = ISC_R_SUCCESS;
2376
0
      break;
2377
0
    }
2378
0
    if (result != ISC_R_SUCCESS) {
2379
0
      goto cleanup;
2380
0
    }
2381
0
    isc_buffer_add(&target, sizeof(totallen));
2382
0
    totallen = isc_buffer_getuint32(&target);
2383
2384
    /*
2385
     * Validation: the input data must at least contain the common
2386
     * header.
2387
     */
2388
0
    minlen = sizeof(totallen) + sizeof(uint16_t) +
2389
0
       sizeof(uint16_t) + sizeof(uint16_t) +
2390
0
       sizeof(uint32_t) + sizeof(uint32_t);
2391
0
    if (totallen < minlen) {
2392
0
      CLEANUP(ISC_R_RANGE);
2393
0
    }
2394
0
    totallen -= sizeof(totallen);
2395
2396
0
    isc_buffer_clear(&target);
2397
0
    if (totallen > isc_buffer_availablelength(&target)) {
2398
      /*
2399
       * The default buffer size should typically be large
2400
       * enough to store the entire RRset.  We could try to
2401
       * allocate enough space if this is not the case, but
2402
       * it might cause a hazardous result when "totallen"
2403
       * is forged.  Thus, we'd rather take an inefficient
2404
       * but robust approach in this atypical case: read
2405
       * data step by step, and commit partial data when
2406
       * necessary.  Note that the buffer must be large
2407
       * enough to store the "header part", owner name, and
2408
       * at least one rdata (however large it is).
2409
       */
2410
0
      sequential_read = true;
2411
0
      readlen = minlen - sizeof(totallen);
2412
0
    } else {
2413
      /*
2414
       * Typical case.  We can read the whole RRset at once
2415
       * with the default buffer.
2416
       */
2417
0
      readlen = totallen;
2418
0
    }
2419
0
    CHECK(isc_stdio_read(target.base, 1, readlen, lctx->f, NULL));
2420
0
    isc_buffer_add(&target, (unsigned int)readlen);
2421
0
    totallen -= (uint32_t)readlen;
2422
2423
    /* Construct RRset headers */
2424
0
    dns_rdatalist_init(&rdatalist);
2425
0
    rdatalist.rdclass = isc_buffer_getuint16(&target);
2426
0
    if (lctx->zclass != rdatalist.rdclass) {
2427
0
      CLEANUP(DNS_R_BADCLASS);
2428
0
    }
2429
0
    rdatalist.type = isc_buffer_getuint16(&target);
2430
0
    rdatalist.covers = isc_buffer_getuint16(&target);
2431
0
    rdatalist.ttl = isc_buffer_getuint32(&target);
2432
0
    rdcount = isc_buffer_getuint32(&target);
2433
0
    if (rdcount == 0 || rdcount > 0xffff) {
2434
0
      CLEANUP(ISC_R_RANGE);
2435
0
    }
2436
0
    INSIST(isc_buffer_consumedlength(&target) <= readlen);
2437
2438
    /* Owner name: length followed by name */
2439
0
    CHECK(read_and_check(sequential_read, &target, sizeof(namelen),
2440
0
             lctx->f, &totallen));
2441
0
    namelen = isc_buffer_getuint16(&target);
2442
0
    if (namelen > sizeof(namebuf)) {
2443
0
      CLEANUP(ISC_R_RANGE);
2444
0
    }
2445
2446
0
    CHECK(read_and_check(sequential_read, &target, namelen, lctx->f,
2447
0
             &totallen));
2448
2449
0
    isc_buffer_setactive(&target, (unsigned int)namelen);
2450
0
    CHECK(dns_name_fromwire(name, &target, dctx, NULL));
2451
2452
0
    if ((lctx->options & DNS_MASTER_CHECKTTL) != 0 &&
2453
0
        rdatalist.ttl > lctx->maxttl)
2454
0
    {
2455
0
      (callbacks->error)(callbacks,
2456
0
             "dns_master_load: "
2457
0
             "TTL %d exceeds configured "
2458
0
             "max-zone-ttl %d",
2459
0
             rdatalist.ttl, lctx->maxttl);
2460
0
      CLEANUP(ISC_R_RANGE);
2461
0
    }
2462
2463
    /* Rdata contents. */
2464
0
    if (rdcount > rdata_size) {
2465
0
      dns_rdata_t *new_rdata = NULL;
2466
2467
0
      new_rdata = grow_rdata(rdcount + RDSZ, rdata,
2468
0
                 rdata_size, &head, &dummy, mctx);
2469
0
      rdata_size = rdcount + RDSZ;
2470
0
      rdata = new_rdata;
2471
0
    }
2472
2473
0
  continue_read:
2474
0
    for (i = 0; i < rdcount; i++) {
2475
0
      uint16_t rdlen;
2476
2477
0
      dns_rdata_init(&rdata[i]);
2478
2479
0
      if (sequential_read &&
2480
0
          isc_buffer_availablelength(&target) < MINTSIZ)
2481
0
      {
2482
0
        unsigned int j;
2483
2484
0
        INSIST(i > 0); /* detect an infinite loop */
2485
2486
        /* Partial Commit. */
2487
0
        ISC_LIST_APPEND(head, &rdatalist, link);
2488
0
        result = commit(callbacks, lctx, &head, name,
2489
0
            NULL, 0);
2490
0
        for (j = 0; j < i; j++) {
2491
0
          ISC_LIST_UNLINK(rdatalist.rdata,
2492
0
              &rdata[j], link);
2493
0
          dns_rdata_reset(&rdata[j]);
2494
0
        }
2495
0
        if (result != ISC_R_SUCCESS) {
2496
0
          goto cleanup;
2497
0
        }
2498
2499
        /* Rewind the buffer and continue */
2500
0
        isc_buffer_clear(&target);
2501
2502
0
        rdcount -= i;
2503
2504
0
        goto continue_read;
2505
0
      }
2506
2507
      /* rdata length */
2508
0
      CHECK(read_and_check(sequential_read, &target,
2509
0
               sizeof(rdlen), lctx->f,
2510
0
               &totallen));
2511
0
      rdlen = isc_buffer_getuint16(&target);
2512
2513
      /* rdata */
2514
0
      CHECK(read_and_check(sequential_read, &target, rdlen,
2515
0
               lctx->f, &totallen));
2516
0
      isc_buffer_setactive(&target, (unsigned int)rdlen);
2517
      /*
2518
       * It is safe to have the source active region and
2519
       * the target available region be the same if
2520
       * decompression is disabled (see dctx above) and we
2521
       * are not downcasing names (options == 0).
2522
       */
2523
0
      isc_buffer_init(&buf, isc_buffer_current(&target),
2524
0
          (unsigned int)rdlen);
2525
0
      CHECK(dns_rdata_fromwire(&rdata[i], rdatalist.rdclass,
2526
0
             rdatalist.type, &target, dctx,
2527
0
             &buf));
2528
0
      ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
2529
0
    }
2530
2531
    /*
2532
     * Sanity check.  Still having remaining space is not
2533
     * necessarily critical, but it very likely indicates broken
2534
     * or malformed data.
2535
     */
2536
0
    if (isc_buffer_remaininglength(&target) != 0 || totallen != 0) {
2537
0
      CLEANUP(ISC_R_RANGE);
2538
0
    }
2539
2540
0
    ISC_LIST_APPEND(head, &rdatalist, link);
2541
2542
    /* Commit this RRset.  rdatalist will be unlinked. */
2543
0
    result = commit(callbacks, lctx, &head, name, NULL, 0);
2544
2545
0
    for (i = 0; i < rdcount; i++) {
2546
0
      ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
2547
0
      dns_rdata_reset(&rdata[i]);
2548
0
    }
2549
2550
0
    if (result != ISC_R_SUCCESS) {
2551
0
      goto cleanup;
2552
0
    }
2553
0
  }
2554
2555
0
  if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
2556
0
    result = lctx->result;
2557
0
  }
2558
2559
0
  if (result == ISC_R_SUCCESS && callbacks->rawdata != NULL) {
2560
0
    (*callbacks->rawdata)(callbacks->zone, &lctx->header);
2561
0
  }
2562
2563
0
cleanup:
2564
  /* commit the database transaction */
2565
0
  if (callbacks->commit != NULL) {
2566
0
    callbacks->commit(callbacks->add_private);
2567
0
  }
2568
2569
0
  if (rdata != NULL) {
2570
0
    isc_mem_cput(mctx, rdata, rdata_size, sizeof(*rdata));
2571
0
  }
2572
0
  if (target_mem != NULL) {
2573
0
    isc_mem_put(mctx, target_mem, target_size);
2574
0
  }
2575
0
  if (result != ISC_R_SUCCESS) {
2576
0
    (*callbacks->error)(callbacks, "dns_master_load: %s",
2577
0
            isc_result_totext(result));
2578
0
  }
2579
2580
0
  return result;
2581
0
}
2582
2583
isc_result_t
2584
dns_master_loadfile(const char *master_file, dns_name_t *top,
2585
        dns_name_t *origin, dns_rdataclass_t zclass,
2586
        unsigned int options, uint32_t resign,
2587
        dns_rdatacallbacks_t *callbacks,
2588
        dns_masterincludecb_t include_cb, void *include_arg,
2589
        isc_mem_t *mctx, dns_masterformat_t format,
2590
2
        dns_ttl_t maxttl) {
2591
2
  dns_loadctx_t *lctx = NULL;
2592
2
  isc_result_t result;
2593
2594
2
  loadctx_create(format, mctx, options, resign, top, zclass, origin,
2595
2
           callbacks, NULL, NULL, include_cb, include_arg, NULL,
2596
2
           &lctx);
2597
2598
2
  lctx->maxttl = maxttl;
2599
2600
2
  CHECK((lctx->openfile)(lctx, master_file));
2601
2602
2
  result = (lctx->load)(lctx);
2603
2
  INSIST(result != DNS_R_CONTINUE);
2604
2605
2
cleanup:
2606
2
  dns_loadctx_detach(&lctx);
2607
2
  return result;
2608
2
}
2609
2610
static void
2611
0
load(void *arg) {
2612
0
  dns_loadctx_t *lctx = arg;
2613
0
  lctx->result = (lctx->load)(lctx);
2614
0
}
2615
2616
static void
2617
0
load_done(void *arg) {
2618
0
  dns_loadctx_t *lctx = arg;
2619
2620
0
  (lctx->done)(lctx->done_arg, lctx->result);
2621
0
  dns_loadctx_detach(&lctx);
2622
0
}
2623
2624
isc_result_t
2625
dns_master_loadfileasync(const char *master_file, dns_name_t *top,
2626
       dns_name_t *origin, dns_rdataclass_t zclass,
2627
       unsigned int options, uint32_t resign,
2628
       dns_rdatacallbacks_t *callbacks, isc_loop_t *loop,
2629
       dns_loaddonefunc_t done, void *done_arg,
2630
       dns_loadctx_t **lctxp,
2631
       dns_masterincludecb_t include_cb, void *include_arg,
2632
       isc_mem_t *mctx, dns_masterformat_t format,
2633
0
       uint32_t maxttl) {
2634
0
  dns_loadctx_t *lctx = NULL;
2635
0
  isc_result_t result;
2636
2637
0
  REQUIRE(loop != NULL);
2638
0
  REQUIRE(done != NULL);
2639
2640
0
  loadctx_create(format, mctx, options, resign, top, zclass, origin,
2641
0
           callbacks, done, done_arg, include_cb, include_arg, NULL,
2642
0
           &lctx);
2643
2644
0
  lctx->maxttl = maxttl;
2645
2646
0
  result = (lctx->openfile)(lctx, master_file);
2647
0
  if (result != ISC_R_SUCCESS) {
2648
0
    dns_loadctx_detach(&lctx);
2649
0
    return result;
2650
0
  }
2651
2652
0
  dns_loadctx_attach(lctx, lctxp);
2653
0
  isc_work_enqueue(loop, load, load_done, lctx);
2654
2655
0
  return ISC_R_SUCCESS;
2656
0
}
2657
2658
isc_result_t
2659
dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
2660
          dns_rdataclass_t zclass, unsigned int options,
2661
0
          dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2662
0
  isc_result_t result;
2663
0
  dns_loadctx_t *lctx = NULL;
2664
2665
0
  REQUIRE(stream != NULL);
2666
2667
0
  loadctx_create(dns_masterformat_text, mctx, options, 0, top, zclass,
2668
0
           origin, callbacks, NULL, NULL, NULL, NULL, NULL, &lctx);
2669
2670
0
  isc_lex_openstream(lctx->lex, stream);
2671
2672
0
  result = (lctx->load)(lctx);
2673
0
  INSIST(result != DNS_R_CONTINUE);
2674
2675
0
  dns_loadctx_detach(&lctx);
2676
0
  return result;
2677
0
}
2678
2679
isc_result_t
2680
dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top, dns_name_t *origin,
2681
          dns_rdataclass_t zclass, unsigned int options,
2682
17.5k
          dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) {
2683
17.5k
  isc_result_t result;
2684
17.5k
  dns_loadctx_t *lctx = NULL;
2685
2686
17.5k
  REQUIRE(buffer != NULL);
2687
2688
17.5k
  loadctx_create(dns_masterformat_text, mctx, options, 0, top, zclass,
2689
17.5k
           origin, callbacks, NULL, NULL, NULL, NULL, NULL, &lctx);
2690
2691
17.5k
  CHECK(isc_lex_openbuffer(lctx->lex, buffer));
2692
2693
17.5k
  result = (lctx->load)(lctx);
2694
17.5k
  INSIST(result != DNS_R_CONTINUE);
2695
2696
17.5k
cleanup:
2697
17.5k
  dns_loadctx_detach(&lctx);
2698
17.5k
  return result;
2699
17.5k
}
2700
2701
/*
2702
 * Grow the slab of dns_rdatalist_t structures.
2703
 * Re-link glue and current list.
2704
 */
2705
static dns_rdatalist_t *
2706
grow_rdatalist(int new_len, dns_rdatalist_t *oldlist, int old_len,
2707
         rdatalist_head_t *current, rdatalist_head_t *glue,
2708
5.06k
         isc_mem_t *mctx) {
2709
5.06k
  dns_rdatalist_t *newlist;
2710
5.06k
  int rdlcount = 0;
2711
5.06k
  ISC_LIST(dns_rdatalist_t) save;
2712
2713
5.06k
  newlist = isc_mem_cget(mctx, new_len, sizeof(newlist[0]));
2714
2715
5.06k
  ISC_LIST_INIT(save);
2716
5.06k
  ISC_LIST_FOREACH(*current, this, link) {
2717
328
    ISC_LIST_UNLINK(*current, this, link);
2718
328
    ISC_LIST_APPEND(save, this, link);
2719
328
  }
2720
5.06k
  ISC_LIST_FOREACH(save, this, link) {
2721
328
    ISC_LIST_UNLINK(save, this, link);
2722
328
    INSIST(rdlcount < new_len);
2723
328
    newlist[rdlcount] = *this;
2724
328
    ISC_LIST_APPEND(*current, &newlist[rdlcount], link);
2725
328
    rdlcount++;
2726
328
  }
2727
2728
5.06k
  ISC_LIST_INIT(save);
2729
5.06k
  ISC_LIST_FOREACH(*glue, this, link) {
2730
120
    ISC_LIST_UNLINK(*glue, this, link);
2731
120
    ISC_LIST_APPEND(save, this, link);
2732
120
  }
2733
5.06k
  ISC_LIST_FOREACH(save, this, link) {
2734
120
    ISC_LIST_UNLINK(save, this, link);
2735
120
    INSIST(rdlcount < new_len);
2736
120
    newlist[rdlcount] = *this;
2737
120
    ISC_LIST_APPEND(*glue, &newlist[rdlcount], link);
2738
120
    rdlcount++;
2739
120
  }
2740
2741
5.06k
  INSIST(rdlcount == old_len);
2742
5.06k
  if (oldlist != NULL) {
2743
14
    isc_mem_cput(mctx, oldlist, old_len, sizeof(*oldlist));
2744
14
  }
2745
5.06k
  return newlist;
2746
5.06k
}
2747
2748
/*
2749
 * Grow the slab of rdata structs.
2750
 * Re-link the current and glue chains.
2751
 */
2752
static dns_rdata_t *
2753
grow_rdata(int new_len, dns_rdata_t *oldlist, int old_len,
2754
11.8k
     rdatalist_head_t *current, rdatalist_head_t *glue, isc_mem_t *mctx) {
2755
11.8k
  dns_rdata_t *newlist;
2756
11.8k
  int rdcount = 0;
2757
11.8k
  ISC_LIST(dns_rdata_t) save;
2758
2759
11.8k
  newlist = isc_mem_cget(mctx, new_len, sizeof(*newlist));
2760
2761
  /*
2762
   * Copy current relinking.
2763
   */
2764
11.8k
  ISC_LIST_FOREACH(*current, this, link) {
2765
2.99k
    ISC_LIST_INIT(save);
2766
1.18M
    ISC_LIST_FOREACH(this->rdata, rdata, link) {
2767
1.18M
      ISC_LIST_UNLINK(this->rdata, rdata, link);
2768
1.18M
      ISC_LIST_APPEND(save, rdata, link);
2769
1.18M
    }
2770
1.18M
    ISC_LIST_FOREACH(save, rdata, link) {
2771
1.18M
      ISC_LIST_UNLINK(save, rdata, link);
2772
1.18M
      INSIST(rdcount < new_len);
2773
1.18M
      newlist[rdcount] = *rdata;
2774
1.18M
      ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
2775
1.18M
      rdcount++;
2776
1.18M
    }
2777
2.99k
  }
2778
2779
  /*
2780
   * Copy glue relinking.
2781
   */
2782
11.8k
  ISC_LIST_FOREACH(*glue, this, link) {
2783
706
    ISC_LIST_INIT(save);
2784
133k
    ISC_LIST_FOREACH(this->rdata, rdata, link) {
2785
133k
      ISC_LIST_UNLINK(this->rdata, rdata, link);
2786
133k
      ISC_LIST_APPEND(save, rdata, link);
2787
133k
    }
2788
133k
    ISC_LIST_FOREACH(save, rdata, link) {
2789
133k
      ISC_LIST_UNLINK(save, rdata, link);
2790
133k
      INSIST(rdcount < new_len);
2791
133k
      newlist[rdcount] = *rdata;
2792
133k
      ISC_LIST_APPEND(this->rdata, &newlist[rdcount], link);
2793
133k
      rdcount++;
2794
133k
    }
2795
706
  }
2796
11.8k
  INSIST(rdcount == old_len || rdcount == 0);
2797
11.8k
  if (oldlist != NULL) {
2798
313
    isc_mem_cput(mctx, oldlist, old_len, sizeof(*oldlist));
2799
313
  }
2800
11.8k
  return newlist;
2801
11.8k
}
2802
2803
static uint32_t
2804
0
resign_fromlist(dns_rdatalist_t *this, dns_loadctx_t *lctx) {
2805
0
  dns_rdata_t *rdata;
2806
0
  dns_rdata_rrsig_t sig;
2807
0
  uint32_t when;
2808
2809
0
  rdata = ISC_LIST_HEAD(this->rdata);
2810
0
  INSIST(rdata != NULL);
2811
0
  (void)dns_rdata_tostruct(rdata, &sig, NULL);
2812
0
  if (isc_serial_gt(sig.timesigned, lctx->now)) {
2813
0
    when = lctx->now;
2814
0
  } else {
2815
0
    when = sig.timeexpire - lctx->resign;
2816
0
  }
2817
2818
0
  rdata = ISC_LIST_NEXT(rdata, link);
2819
0
  while (rdata != NULL) {
2820
0
    (void)dns_rdata_tostruct(rdata, &sig, NULL);
2821
0
    if (isc_serial_gt(sig.timesigned, lctx->now)) {
2822
0
      when = lctx->now;
2823
0
    } else if (sig.timeexpire - lctx->resign < when) {
2824
0
      when = sig.timeexpire - lctx->resign;
2825
0
    }
2826
0
    rdata = ISC_LIST_NEXT(rdata, link);
2827
0
  }
2828
0
  return when;
2829
0
}
2830
2831
/*
2832
 * Convert each element from a rdatalist_t to rdataset then call commit.
2833
 * Unlink each element as we go.
2834
 */
2835
2836
static isc_result_t
2837
commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
2838
       rdatalist_head_t *head, dns_name_t *owner, const char *source,
2839
9.96M
       unsigned int line) {
2840
9.96M
  dns_rdataset_t dataset;
2841
9.96M
  isc_result_t result = ISC_R_SUCCESS;
2842
9.96M
  char namebuf[DNS_NAME_FORMATSIZE];
2843
9.96M
  void (*error)(struct dns_rdatacallbacks *, const char *, ...);
2844
2845
9.96M
  error = callbacks->error;
2846
2847
9.96M
  ISC_LIST_FOREACH(*head, this, link) {
2848
9.96M
    dns_rdataset_init(&dataset);
2849
9.96M
    dns_rdatalist_tordataset(this, &dataset);
2850
9.96M
    dataset.trust = dns_trust_ultimate;
2851
    /*
2852
     * If this is a secure dynamic zone set the re-signing time.
2853
     */
2854
9.96M
    if (dataset.type == dns_rdatatype_rrsig &&
2855
5.45k
        (lctx->options & DNS_MASTER_RESIGN) != 0)
2856
0
    {
2857
0
      dataset.attributes.resign = true;
2858
0
      dataset.resign = resign_fromlist(this, lctx);
2859
0
    }
2860
9.96M
    result = callbacks->update(callbacks->add_private, owner,
2861
9.96M
             &dataset,
2862
9.96M
             DNS_DIFFOP_ADD DNS__DB_FILELINE);
2863
9.96M
    if (result != ISC_R_SUCCESS) {
2864
250
      dns_name_format(owner, namebuf, sizeof(namebuf));
2865
250
      if (source != NULL) {
2866
250
        (*error)(callbacks, "%s: %s:%lu: %s: %s",
2867
250
           "dns_master_load", source, line,
2868
250
           namebuf, isc_result_totext(result));
2869
250
      } else {
2870
0
        (*error)(callbacks, "%s: %s: %s",
2871
0
           "dns_master_load", namebuf,
2872
0
           isc_result_totext(result));
2873
0
      }
2874
250
    }
2875
9.96M
    if (MANYERRS(lctx, result)) {
2876
0
      SETRESULT(lctx, result);
2877
9.96M
    } else if (result != ISC_R_SUCCESS) {
2878
250
      break;
2879
250
    }
2880
9.96M
    ISC_LIST_UNLINK(*head, this, link);
2881
9.96M
  }
2882
2883
9.96M
  return result;
2884
9.96M
}
2885
2886
/*
2887
 * Returns true if one of the NS rdata's contains 'owner'.
2888
 */
2889
2890
static bool
2891
4.40k
is_glue(rdatalist_head_t *head, dns_name_t *owner) {
2892
4.40k
  dns_rdatalist_t *nslist = NULL;
2893
4.40k
  isc_region_t region;
2894
4.40k
  dns_name_t name;
2895
2896
  /*
2897
   * Find NS rrset.
2898
   */
2899
5.00k
  ISC_LIST_FOREACH(*head, this, link) {
2900
5.00k
    if (this->type == dns_rdatatype_ns) {
2901
3.94k
      nslist = this;
2902
3.94k
      break;
2903
3.94k
    }
2904
5.00k
  }
2905
4.40k
  if (nslist == NULL) {
2906
456
    return false;
2907
456
  }
2908
2909
32.0k
  ISC_LIST_FOREACH(nslist->rdata, rdata, link) {
2910
32.0k
    dns_name_init(&name);
2911
32.0k
    dns_rdata_toregion(rdata, &region);
2912
32.0k
    dns_name_fromregion(&name, &region);
2913
32.0k
    if (dns_name_equal(&name, owner)) {
2914
1.27k
      return true;
2915
1.27k
    }
2916
32.0k
  }
2917
2.67k
  return false;
2918
3.94k
}
2919
2920
void
2921
0
dns_loadctx_cancel(dns_loadctx_t *lctx) {
2922
0
  REQUIRE(DNS_LCTX_VALID(lctx));
2923
2924
0
  atomic_store_release(&lctx->canceled, true);
2925
0
}
2926
2927
void
2928
17.5k
dns_master_initrawheader(dns_masterrawheader_t *header) {
2929
17.5k
  memset(header, 0, sizeof(dns_masterrawheader_t));
2930
17.5k
}