/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

Large files are truncated click here to view the full file

  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);