PageRenderTime 37ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/bind9/lib/dns/master.c

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