/contrib/bind9/lib/isccfg/namedconf.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 2741 lines · 2107 code · 353 blank · 281 comment · 168 complexity · 34ffe94fa630a73157ebddc734461e61 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2002, 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 <string.h>
  21. #include <isc/lex.h>
  22. #include <isc/mem.h>
  23. #include <isc/result.h>
  24. #include <isc/string.h>
  25. #include <isc/util.h>
  26. #include <isccfg/cfg.h>
  27. #include <isccfg/grammar.h>
  28. #include <isccfg/log.h>
  29. #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
  30. /*% Check a return value. */
  31. #define CHECK(op) \
  32. do { result = (op); \
  33. if (result != ISC_R_SUCCESS) goto cleanup; \
  34. } while (0)
  35. /*% Clean up a configuration object if non-NULL. */
  36. #define CLEANUP_OBJ(obj) \
  37. do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
  38. /*%
  39. * Forward declarations of static functions.
  40. */
  41. static isc_result_t
  42. parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
  43. const cfg_type_t *othertype, cfg_obj_t **ret);
  44. static isc_result_t
  45. parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
  46. static isc_result_t
  47. parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
  48. cfg_obj_t **ret);
  49. static isc_result_t
  50. parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
  51. cfg_obj_t **ret);
  52. static void
  53. print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj);
  54. static void
  55. doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type);
  56. static void
  57. print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj);
  58. static void
  59. doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
  60. static void
  61. doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
  62. static cfg_type_t cfg_type_acl;
  63. static cfg_type_t cfg_type_addrmatchelt;
  64. static cfg_type_t cfg_type_bracketed_aml;
  65. static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
  66. static cfg_type_t cfg_type_bracketed_sockaddrlist;
  67. static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
  68. static cfg_type_t cfg_type_controls;
  69. static cfg_type_t cfg_type_controls_sockaddr;
  70. static cfg_type_t cfg_type_destinationlist;
  71. static cfg_type_t cfg_type_dialuptype;
  72. static cfg_type_t cfg_type_ixfrdifftype;
  73. static cfg_type_t cfg_type_key;
  74. static cfg_type_t cfg_type_logfile;
  75. static cfg_type_t cfg_type_logging;
  76. static cfg_type_t cfg_type_logseverity;
  77. static cfg_type_t cfg_type_lwres;
  78. static cfg_type_t cfg_type_masterselement;
  79. static cfg_type_t cfg_type_nameportiplist;
  80. static cfg_type_t cfg_type_negated;
  81. static cfg_type_t cfg_type_notifytype;
  82. static cfg_type_t cfg_type_optional_allow;
  83. static cfg_type_t cfg_type_optional_class;
  84. static cfg_type_t cfg_type_optional_facility;
  85. static cfg_type_t cfg_type_optional_keyref;
  86. static cfg_type_t cfg_type_optional_port;
  87. static cfg_type_t cfg_type_options;
  88. static cfg_type_t cfg_type_portiplist;
  89. static cfg_type_t cfg_type_querysource4;
  90. static cfg_type_t cfg_type_querysource6;
  91. static cfg_type_t cfg_type_querysource;
  92. static cfg_type_t cfg_type_server;
  93. static cfg_type_t cfg_type_server_key_kludge;
  94. static cfg_type_t cfg_type_size;
  95. static cfg_type_t cfg_type_sizenodefault;
  96. static cfg_type_t cfg_type_sockaddr4wild;
  97. static cfg_type_t cfg_type_sockaddr6wild;
  98. static cfg_type_t cfg_type_statschannels;
  99. static cfg_type_t cfg_type_view;
  100. static cfg_type_t cfg_type_viewopts;
  101. static cfg_type_t cfg_type_zone;
  102. static cfg_type_t cfg_type_zoneopts;
  103. static cfg_type_t cfg_type_dynamically_loadable_zones;
  104. static cfg_type_t cfg_type_dynamically_loadable_zones_opts;
  105. static cfg_type_t cfg_type_v4_aaaa;
  106. /*
  107. * Clauses that can be found in a 'dynamically loadable zones' statement
  108. */
  109. static cfg_clausedef_t
  110. dynamically_loadable_zones_clauses[] = {
  111. { "database", &cfg_type_astring, 0 },
  112. { NULL, NULL, 0 }
  113. };
  114. /*
  115. * A dynamically loadable zones statement.
  116. */
  117. static cfg_tuplefielddef_t dynamically_loadable_zones_fields[] = {
  118. { "name", &cfg_type_astring, 0 },
  119. { "options", &cfg_type_dynamically_loadable_zones_opts, 0 },
  120. { NULL, NULL, 0 }
  121. };
  122. static cfg_type_t cfg_type_dynamically_loadable_zones = {
  123. "dlz", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  124. &cfg_rep_tuple,
  125. dynamically_loadable_zones_fields
  126. };
  127. /*% tkey-dhkey */
  128. static cfg_tuplefielddef_t tkey_dhkey_fields[] = {
  129. { "name", &cfg_type_qstring, 0 },
  130. { "keyid", &cfg_type_uint32, 0 },
  131. { NULL, NULL, 0 }
  132. };
  133. static cfg_type_t cfg_type_tkey_dhkey = {
  134. "tkey-dhkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  135. tkey_dhkey_fields
  136. };
  137. /*% listen-on */
  138. static cfg_tuplefielddef_t listenon_fields[] = {
  139. { "port", &cfg_type_optional_port, 0 },
  140. { "acl", &cfg_type_bracketed_aml, 0 },
  141. { NULL, NULL, 0 }
  142. };
  143. static cfg_type_t cfg_type_listenon = {
  144. "listenon", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, listenon_fields };
  145. /*% acl */
  146. static cfg_tuplefielddef_t acl_fields[] = {
  147. { "name", &cfg_type_astring, 0 },
  148. { "value", &cfg_type_bracketed_aml, 0 },
  149. { NULL, NULL, 0 }
  150. };
  151. static cfg_type_t cfg_type_acl = {
  152. "acl", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, acl_fields };
  153. /*% masters */
  154. static cfg_tuplefielddef_t masters_fields[] = {
  155. { "name", &cfg_type_astring, 0 },
  156. { "port", &cfg_type_optional_port, 0 },
  157. { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
  158. { NULL, NULL, 0 }
  159. };
  160. static cfg_type_t cfg_type_masters = {
  161. "masters", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, masters_fields };
  162. /*%
  163. * "sockaddrkeylist", a list of socket addresses with optional keys
  164. * and an optional default port, as used in the masters option.
  165. * E.g.,
  166. * "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
  167. */
  168. static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
  169. { "masterselement", &cfg_type_masterselement, 0 },
  170. { "key", &cfg_type_optional_keyref, 0 },
  171. { NULL, NULL, 0 },
  172. };
  173. static cfg_type_t cfg_type_namesockaddrkey = {
  174. "namesockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  175. namesockaddrkey_fields
  176. };
  177. static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
  178. "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list,
  179. cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_namesockaddrkey
  180. };
  181. static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
  182. { "port", &cfg_type_optional_port, 0 },
  183. { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
  184. { NULL, NULL, 0 }
  185. };
  186. static cfg_type_t cfg_type_namesockaddrkeylist = {
  187. "sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  188. namesockaddrkeylist_fields
  189. };
  190. /*%
  191. * A list of socket addresses with an optional default port,
  192. * as used in the also-notify option. E.g.,
  193. * "port 1234 { 10.0.0.1; 1::2 port 69; }"
  194. */
  195. static cfg_tuplefielddef_t portiplist_fields[] = {
  196. { "port", &cfg_type_optional_port, 0 },
  197. { "addresses", &cfg_type_bracketed_sockaddrlist, 0 },
  198. { NULL, NULL, 0 }
  199. };
  200. static cfg_type_t cfg_type_portiplist = {
  201. "portiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  202. portiplist_fields
  203. };
  204. /*%
  205. * A public key, as in the "pubkey" statement.
  206. */
  207. static cfg_tuplefielddef_t pubkey_fields[] = {
  208. { "flags", &cfg_type_uint32, 0 },
  209. { "protocol", &cfg_type_uint32, 0 },
  210. { "algorithm", &cfg_type_uint32, 0 },
  211. { "key", &cfg_type_qstring, 0 },
  212. { NULL, NULL, 0 }
  213. };
  214. static cfg_type_t cfg_type_pubkey = {
  215. "pubkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  216. &cfg_rep_tuple, pubkey_fields };
  217. /*%
  218. * A list of RR types, used in grant statements.
  219. * Note that the old parser allows quotes around the RR type names.
  220. */
  221. static cfg_type_t cfg_type_rrtypelist = {
  222. "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist,
  223. cfg_doc_terminal, &cfg_rep_list, &cfg_type_astring
  224. };
  225. static const char *mode_enums[] = { "grant", "deny", NULL };
  226. static cfg_type_t cfg_type_mode = {
  227. "mode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  228. &cfg_rep_string, &mode_enums
  229. };
  230. static isc_result_t
  231. parse_matchtype(cfg_parser_t *pctx, const cfg_type_t *type,
  232. cfg_obj_t **ret) {
  233. isc_result_t result;
  234. CHECK(cfg_peektoken(pctx, 0));
  235. if (pctx->token.type == isc_tokentype_string &&
  236. strcasecmp(TOKEN_STRING(pctx), "zonesub") == 0) {
  237. pctx->flags |= CFG_PCTX_SKIP;
  238. }
  239. return (cfg_parse_enum(pctx, type, ret));
  240. cleanup:
  241. return (result);
  242. }
  243. static isc_result_t
  244. parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
  245. isc_result_t result;
  246. cfg_obj_t *obj = NULL;
  247. if ((pctx->flags & CFG_PCTX_SKIP) != 0) {
  248. pctx->flags &= ~CFG_PCTX_SKIP;
  249. CHECK(cfg_parse_void(pctx, NULL, &obj));
  250. } else
  251. result = cfg_parse_astring(pctx, type, &obj);
  252. *ret = obj;
  253. cleanup:
  254. return (result);
  255. }
  256. static void
  257. doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
  258. cfg_print_chars(pctx, "[ ", 2);
  259. cfg_doc_obj(pctx, type->of);
  260. cfg_print_chars(pctx, " ]", 2);
  261. }
  262. static const char *matchtype_enums[] = {
  263. "name", "subdomain", "wildcard", "self", "selfsub", "selfwild",
  264. "krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain",
  265. "tcp-self", "6to4-self", "zonesub", "external", NULL };
  266. static cfg_type_t cfg_type_matchtype = {
  267. "matchtype", parse_matchtype, cfg_print_ustring,
  268. cfg_doc_enum, &cfg_rep_string, &matchtype_enums
  269. };
  270. static cfg_type_t cfg_type_matchname = {
  271. "optional_matchname", parse_matchname, cfg_print_ustring,
  272. &doc_matchname, &cfg_rep_tuple, &cfg_type_ustring
  273. };
  274. /*%
  275. * A grant statement, used in the update policy.
  276. */
  277. static cfg_tuplefielddef_t grant_fields[] = {
  278. { "mode", &cfg_type_mode, 0 },
  279. { "identity", &cfg_type_astring, 0 }, /* domain name */
  280. { "matchtype", &cfg_type_matchtype, 0 },
  281. { "name", &cfg_type_matchname, 0 }, /* domain name */
  282. { "types", &cfg_type_rrtypelist, 0 },
  283. { NULL, NULL, 0 }
  284. };
  285. static cfg_type_t cfg_type_grant = {
  286. "grant", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  287. &cfg_rep_tuple, grant_fields
  288. };
  289. static cfg_type_t cfg_type_updatepolicy = {
  290. "update_policy", parse_updatepolicy, print_updatepolicy,
  291. doc_updatepolicy, &cfg_rep_list, &cfg_type_grant
  292. };
  293. static isc_result_t
  294. parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
  295. cfg_obj_t **ret) {
  296. isc_result_t result;
  297. CHECK(cfg_gettoken(pctx, 0));
  298. if (pctx->token.type == isc_tokentype_special &&
  299. pctx->token.value.as_char == '{') {
  300. cfg_ungettoken(pctx);
  301. return (cfg_parse_bracketed_list(pctx, type, ret));
  302. }
  303. if (pctx->token.type == isc_tokentype_string &&
  304. strcasecmp(TOKEN_STRING(pctx), "local") == 0) {
  305. cfg_obj_t *obj = NULL;
  306. CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj));
  307. obj->value.string.length = strlen("local");
  308. obj->value.string.base = isc_mem_get(pctx->mctx,
  309. obj->value.string.length + 1);
  310. if (obj->value.string.base == NULL) {
  311. isc_mem_put(pctx->mctx, obj, sizeof(*obj));
  312. return (ISC_R_NOMEMORY);
  313. }
  314. memcpy(obj->value.string.base, "local", 5);
  315. obj->value.string.base[5] = '\0';
  316. *ret = obj;
  317. return (ISC_R_SUCCESS);
  318. }
  319. cfg_ungettoken(pctx);
  320. return (ISC_R_UNEXPECTEDTOKEN);
  321. cleanup:
  322. return (result);
  323. }
  324. static void
  325. print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj) {
  326. if (cfg_obj_isstring(obj))
  327. cfg_print_ustring(pctx, obj);
  328. else
  329. cfg_print_bracketed_list(pctx, obj);
  330. }
  331. static void
  332. doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type) {
  333. cfg_print_cstr(pctx, "( local | { ");
  334. cfg_doc_obj(pctx, type->of);
  335. cfg_print_cstr(pctx, "; ... }");
  336. }
  337. /*%
  338. * A view statement.
  339. */
  340. static cfg_tuplefielddef_t view_fields[] = {
  341. { "name", &cfg_type_astring, 0 },
  342. { "class", &cfg_type_optional_class, 0 },
  343. { "options", &cfg_type_viewopts, 0 },
  344. { NULL, NULL, 0 }
  345. };
  346. static cfg_type_t cfg_type_view = {
  347. "view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  348. &cfg_rep_tuple, view_fields
  349. };
  350. /*%
  351. * A zone statement.
  352. */
  353. static cfg_tuplefielddef_t zone_fields[] = {
  354. { "name", &cfg_type_astring, 0 },
  355. { "class", &cfg_type_optional_class, 0 },
  356. { "options", &cfg_type_zoneopts, 0 },
  357. { NULL, NULL, 0 }
  358. };
  359. static cfg_type_t cfg_type_zone = {
  360. "zone", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  361. &cfg_rep_tuple, zone_fields
  362. };
  363. /*%
  364. * A "category" clause in the "logging" statement.
  365. */
  366. static cfg_tuplefielddef_t category_fields[] = {
  367. { "name", &cfg_type_astring, 0 },
  368. { "destinations", &cfg_type_destinationlist,0 },
  369. { NULL, NULL, 0 }
  370. };
  371. static cfg_type_t cfg_type_category = {
  372. "category", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  373. &cfg_rep_tuple, category_fields
  374. };
  375. /*%
  376. * A dnssec key, as used in the "trusted-keys" statement.
  377. */
  378. static cfg_tuplefielddef_t dnsseckey_fields[] = {
  379. { "name", &cfg_type_astring, 0 },
  380. { "flags", &cfg_type_uint32, 0 },
  381. { "protocol", &cfg_type_uint32, 0 },
  382. { "algorithm", &cfg_type_uint32, 0 },
  383. { "key", &cfg_type_qstring, 0 },
  384. { NULL, NULL, 0 }
  385. };
  386. static cfg_type_t cfg_type_dnsseckey = {
  387. "dnsseckey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  388. &cfg_rep_tuple, dnsseckey_fields
  389. };
  390. /*%
  391. * A managed key initialization specifier, as used in the
  392. * "managed-keys" statement.
  393. */
  394. static cfg_tuplefielddef_t managedkey_fields[] = {
  395. { "name", &cfg_type_astring, 0 },
  396. { "init", &cfg_type_ustring, 0 }, /* must be literal "initial-key" */
  397. { "flags", &cfg_type_uint32, 0 },
  398. { "protocol", &cfg_type_uint32, 0 },
  399. { "algorithm", &cfg_type_uint32, 0 },
  400. { "key", &cfg_type_qstring, 0 },
  401. { NULL, NULL, 0 }
  402. };
  403. static cfg_type_t cfg_type_managedkey = {
  404. "managedkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  405. &cfg_rep_tuple, managedkey_fields
  406. };
  407. static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
  408. static cfg_type_t cfg_type_optional_wild_class = {
  409. "optional_wild_class", parse_optional_keyvalue, print_keyvalue,
  410. doc_optional_keyvalue, &cfg_rep_string, &wild_class_kw
  411. };
  412. static keyword_type_t wild_type_kw = { "type", &cfg_type_ustring };
  413. static cfg_type_t cfg_type_optional_wild_type = {
  414. "optional_wild_type", parse_optional_keyvalue,
  415. print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &wild_type_kw
  416. };
  417. static keyword_type_t wild_name_kw = { "name", &cfg_type_qstring };
  418. static cfg_type_t cfg_type_optional_wild_name = {
  419. "optional_wild_name", parse_optional_keyvalue,
  420. print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &wild_name_kw
  421. };
  422. /*%
  423. * An rrset ordering element.
  424. */
  425. static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
  426. { "class", &cfg_type_optional_wild_class, 0 },
  427. { "type", &cfg_type_optional_wild_type, 0 },
  428. { "name", &cfg_type_optional_wild_name, 0 },
  429. { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
  430. { "ordering", &cfg_type_ustring, 0 },
  431. { NULL, NULL, 0 }
  432. };
  433. static cfg_type_t cfg_type_rrsetorderingelement = {
  434. "rrsetorderingelement", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  435. rrsetorderingelement_fields
  436. };
  437. /*%
  438. * A global or view "check-names" option. Note that the zone
  439. * "check-names" option has a different syntax.
  440. */
  441. static const char *checktype_enums[] = { "master", "slave", "response", NULL };
  442. static cfg_type_t cfg_type_checktype = {
  443. "checktype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  444. &cfg_rep_string, &checktype_enums
  445. };
  446. static const char *checkmode_enums[] = { "fail", "warn", "ignore", NULL };
  447. static cfg_type_t cfg_type_checkmode = {
  448. "checkmode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  449. &cfg_rep_string, &checkmode_enums
  450. };
  451. static cfg_tuplefielddef_t checknames_fields[] = {
  452. { "type", &cfg_type_checktype, 0 },
  453. { "mode", &cfg_type_checkmode, 0 },
  454. { NULL, NULL, 0 }
  455. };
  456. static cfg_type_t cfg_type_checknames = {
  457. "checknames", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
  458. checknames_fields
  459. };
  460. static cfg_type_t cfg_type_bracketed_sockaddrlist = {
  461. "bracketed_sockaddrlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
  462. &cfg_rep_list, &cfg_type_sockaddr
  463. };
  464. static const char *autodnssec_enums[] = { "allow", "maintain", "off", NULL };
  465. static cfg_type_t cfg_type_autodnssec = {
  466. "autodnssec", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  467. &cfg_rep_string, &autodnssec_enums
  468. };
  469. static cfg_type_t cfg_type_rrsetorder = {
  470. "rrsetorder", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
  471. &cfg_rep_list, &cfg_type_rrsetorderingelement
  472. };
  473. static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
  474. static cfg_type_t cfg_type_optional_port = {
  475. "optional_port", parse_optional_keyvalue, print_keyvalue,
  476. doc_optional_keyvalue, &cfg_rep_uint32, &port_kw
  477. };
  478. /*% A list of keys, as in the "key" clause of the controls statement. */
  479. static cfg_type_t cfg_type_keylist = {
  480. "keylist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
  481. cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring
  482. };
  483. /*% A list of dnssec keys, as in "trusted-keys" */
  484. static cfg_type_t cfg_type_dnsseckeys = {
  485. "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
  486. cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey
  487. };
  488. /*%
  489. * A list of managed key entries, as in "trusted-keys". Currently
  490. * (9.7.0) this has a format similar to dnssec keys, except the keyname
  491. * is followed by the keyword "initial-key". In future releases, this
  492. * keyword may take other values indicating different methods for the
  493. * key to be initialized.
  494. */
  495. static cfg_type_t cfg_type_managedkeys = {
  496. "managedkeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,
  497. cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_managedkey
  498. };
  499. static const char *forwardtype_enums[] = { "first", "only", NULL };
  500. static cfg_type_t cfg_type_forwardtype = {
  501. "forwardtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
  502. &forwardtype_enums
  503. };
  504. static const char *zonetype_enums[] = {
  505. "master", "slave", "stub", "static-stub", "hint", "forward",
  506. "delegation-only", NULL };
  507. static cfg_type_t cfg_type_zonetype = {
  508. "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  509. &cfg_rep_string, &zonetype_enums
  510. };
  511. static const char *loglevel_enums[] = {
  512. "critical", "error", "warning", "notice", "info", "dynamic", NULL };
  513. static cfg_type_t cfg_type_loglevel = {
  514. "loglevel", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
  515. &loglevel_enums
  516. };
  517. static const char *transferformat_enums[] = {
  518. "many-answers", "one-answer", NULL };
  519. static cfg_type_t cfg_type_transferformat = {
  520. "transferformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
  521. &transferformat_enums
  522. };
  523. /*%
  524. * The special keyword "none", as used in the pid-file option.
  525. */
  526. static void
  527. print_none(cfg_printer_t *pctx, const cfg_obj_t *obj) {
  528. UNUSED(obj);
  529. cfg_print_cstr(pctx, "none");
  530. }
  531. static cfg_type_t cfg_type_none = {
  532. "none", NULL, print_none, NULL, &cfg_rep_void, NULL
  533. };
  534. /*%
  535. * A quoted string or the special keyword "none". Used in the pid-file option.
  536. */
  537. static isc_result_t
  538. parse_qstringornone(cfg_parser_t *pctx, const cfg_type_t *type,
  539. cfg_obj_t **ret)
  540. {
  541. isc_result_t result;
  542. CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
  543. if (pctx->token.type == isc_tokentype_string &&
  544. strcasecmp(TOKEN_STRING(pctx), "none") == 0)
  545. return (cfg_create_obj(pctx, &cfg_type_none, ret));
  546. cfg_ungettoken(pctx);
  547. return (cfg_parse_qstring(pctx, type, ret));
  548. cleanup:
  549. return (result);
  550. }
  551. static void
  552. doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) {
  553. UNUSED(type);
  554. cfg_print_cstr(pctx, "( <quoted_string> | none )");
  555. }
  556. static cfg_type_t cfg_type_qstringornone = {
  557. "qstringornone", parse_qstringornone, NULL, doc_qstringornone,
  558. NULL, NULL
  559. };
  560. /*%
  561. * A boolean ("yes" or "no"), or the special keyword "auto".
  562. * Used in the dnssec-validation option.
  563. */
  564. static void
  565. print_auto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
  566. UNUSED(obj);
  567. cfg_print_cstr(pctx, "auto");
  568. }
  569. static cfg_type_t cfg_type_auto = {
  570. "auto", NULL, print_auto, NULL, &cfg_rep_void, NULL
  571. };
  572. static isc_result_t
  573. parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type,
  574. cfg_obj_t **ret)
  575. {
  576. isc_result_t result;
  577. CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
  578. if (pctx->token.type == isc_tokentype_string &&
  579. strcasecmp(TOKEN_STRING(pctx), "auto") == 0)
  580. return (cfg_create_obj(pctx, &cfg_type_auto, ret));
  581. cfg_ungettoken(pctx);
  582. return (cfg_parse_boolean(pctx, type, ret));
  583. cleanup:
  584. return (result);
  585. }
  586. static void
  587. print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
  588. if (obj->type->rep == &cfg_rep_void)
  589. cfg_print_chars(pctx, "auto", 4);
  590. else if (obj->value.boolean)
  591. cfg_print_chars(pctx, "yes", 3);
  592. else
  593. cfg_print_chars(pctx, "no", 2);
  594. }
  595. static void
  596. doc_boolorauto(cfg_printer_t *pctx, const cfg_type_t *type) {
  597. UNUSED(type);
  598. cfg_print_cstr(pctx, "( yes | no | auto )");
  599. }
  600. static cfg_type_t cfg_type_boolorauto = {
  601. "boolorauto", parse_boolorauto, print_boolorauto,
  602. doc_boolorauto, NULL, NULL
  603. };
  604. /*%
  605. * keyword hostname
  606. */
  607. static void
  608. print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) {
  609. UNUSED(obj);
  610. cfg_print_cstr(pctx, "hostname");
  611. }
  612. static cfg_type_t cfg_type_hostname = {
  613. "hostname", NULL, print_hostname, NULL, &cfg_rep_boolean, NULL
  614. };
  615. /*%
  616. * "server-id" argument.
  617. */
  618. static isc_result_t
  619. parse_serverid(cfg_parser_t *pctx, const cfg_type_t *type,
  620. cfg_obj_t **ret)
  621. {
  622. isc_result_t result;
  623. CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
  624. if (pctx->token.type == isc_tokentype_string &&
  625. strcasecmp(TOKEN_STRING(pctx), "none") == 0)
  626. return (cfg_create_obj(pctx, &cfg_type_none, ret));
  627. if (pctx->token.type == isc_tokentype_string &&
  628. strcasecmp(TOKEN_STRING(pctx), "hostname") == 0) {
  629. return (cfg_create_obj(pctx, &cfg_type_hostname, ret));
  630. }
  631. cfg_ungettoken(pctx);
  632. return (cfg_parse_qstring(pctx, type, ret));
  633. cleanup:
  634. return (result);
  635. }
  636. static void
  637. doc_serverid(cfg_printer_t *pctx, const cfg_type_t *type) {
  638. UNUSED(type);
  639. cfg_print_cstr(pctx, "( <quoted_string> | none | hostname )");
  640. }
  641. static cfg_type_t cfg_type_serverid = {
  642. "serverid", parse_serverid, NULL, doc_serverid, NULL, NULL };
  643. /*%
  644. * Port list.
  645. */
  646. static cfg_tuplefielddef_t porttuple_fields[] = {
  647. { "loport", &cfg_type_uint32, 0 },
  648. { "hiport", &cfg_type_uint32, 0 },
  649. { NULL, NULL, 0 }
  650. };
  651. static cfg_type_t cfg_type_porttuple = {
  652. "porttuple", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  653. &cfg_rep_tuple, porttuple_fields
  654. };
  655. static isc_result_t
  656. parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
  657. isc_result_t result;
  658. CHECK(cfg_parse_uint32(pctx, NULL, ret));
  659. if ((*ret)->value.uint32 > 0xffff) {
  660. cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid port");
  661. cfg_obj_destroy(pctx, ret);
  662. result = ISC_R_RANGE;
  663. }
  664. cleanup:
  665. return (result);
  666. }
  667. static isc_result_t
  668. parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
  669. isc_result_t result;
  670. cfg_obj_t *obj = NULL;
  671. UNUSED(type);
  672. CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
  673. if (pctx->token.type == isc_tokentype_number)
  674. CHECK(parse_port(pctx, ret));
  675. else {
  676. CHECK(cfg_gettoken(pctx, 0));
  677. if (pctx->token.type != isc_tokentype_string ||
  678. strcasecmp(TOKEN_STRING(pctx), "range") != 0) {
  679. cfg_parser_error(pctx, CFG_LOG_NEAR,
  680. "expected integer or 'range'");
  681. return (ISC_R_UNEXPECTEDTOKEN);
  682. }
  683. CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
  684. CHECK(parse_port(pctx, &obj->value.tuple[0]));
  685. CHECK(parse_port(pctx, &obj->value.tuple[1]));
  686. if (obj->value.tuple[0]->value.uint32 >
  687. obj->value.tuple[1]->value.uint32) {
  688. cfg_parser_error(pctx, CFG_LOG_NOPREP,
  689. "low port '%u' must not be larger "
  690. "than high port",
  691. obj->value.tuple[0]->value.uint32);
  692. result = ISC_R_RANGE;
  693. goto cleanup;
  694. }
  695. *ret = obj;
  696. obj = NULL;
  697. }
  698. cleanup:
  699. if (obj != NULL)
  700. cfg_obj_destroy(pctx, &obj);
  701. return (result);
  702. }
  703. static cfg_type_t cfg_type_portrange = {
  704. "portrange", parse_portrange, NULL, cfg_doc_terminal,
  705. NULL, NULL
  706. };
  707. static cfg_type_t cfg_type_bracketed_portlist = {
  708. "bracketed_sockaddrlist", cfg_parse_bracketed_list,
  709. cfg_print_bracketed_list, cfg_doc_bracketed_list,
  710. &cfg_rep_list, &cfg_type_portrange
  711. };
  712. /*%
  713. * Clauses that can be found within the top level of the named.conf
  714. * file only.
  715. */
  716. static cfg_clausedef_t
  717. namedconf_clauses[] = {
  718. { "options", &cfg_type_options, 0 },
  719. { "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
  720. { "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
  721. { "masters", &cfg_type_masters, CFG_CLAUSEFLAG_MULTI },
  722. { "logging", &cfg_type_logging, 0 },
  723. { "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
  724. { "lwres", &cfg_type_lwres, CFG_CLAUSEFLAG_MULTI },
  725. { "statistics-channels", &cfg_type_statschannels,
  726. CFG_CLAUSEFLAG_MULTI },
  727. { NULL, NULL, 0 }
  728. };
  729. /*%
  730. * Clauses that can occur at the top level or in the view
  731. * statement, but not in the options block.
  732. */
  733. static cfg_clausedef_t
  734. namedconf_or_view_clauses[] = {
  735. { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
  736. { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
  737. /* only 1 DLZ per view allowed */
  738. { "dlz", &cfg_type_dynamically_loadable_zones, 0 },
  739. { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
  740. { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
  741. { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
  742. { NULL, NULL, 0 }
  743. };
  744. /*%
  745. * Clauses that can occur in the bind.keys file.
  746. */
  747. static cfg_clausedef_t
  748. bindkeys_clauses[] = {
  749. { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
  750. { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI },
  751. { NULL, NULL, 0 }
  752. };
  753. /*%
  754. * Clauses that can be found within the 'options' statement.
  755. */
  756. static cfg_clausedef_t
  757. options_clauses[] = {
  758. { "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
  759. { "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
  760. { "bindkeys-file", &cfg_type_qstring, 0 },
  761. { "blackhole", &cfg_type_bracketed_aml, 0 },
  762. { "coresize", &cfg_type_size, 0 },
  763. { "datasize", &cfg_type_size, 0 },
  764. { "session-keyfile", &cfg_type_qstringornone, 0 },
  765. { "session-keyname", &cfg_type_astring, 0 },
  766. { "session-keyalg", &cfg_type_astring, 0 },
  767. { "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  768. { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
  769. { "dump-file", &cfg_type_qstring, 0 },
  770. { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  771. { "files", &cfg_type_size, 0 },
  772. { "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
  773. { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  774. { "heartbeat-interval", &cfg_type_uint32, 0 },
  775. { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP },
  776. { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
  777. { "hostname", &cfg_type_qstringornone, 0 },
  778. { "interface-interval", &cfg_type_uint32, 0 },
  779. { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
  780. { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
  781. { "managed-keys-directory", &cfg_type_qstring, 0 },
  782. { "match-mapped-addresses", &cfg_type_boolean, 0 },
  783. { "memstatistics-file", &cfg_type_qstring, 0 },
  784. { "memstatistics", &cfg_type_boolean, 0 },
  785. { "multiple-cnames", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  786. { "named-xfer", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
  787. { "pid-file", &cfg_type_qstringornone, 0 },
  788. { "port", &cfg_type_uint32, 0 },
  789. { "querylog", &cfg_type_boolean, 0 },
  790. { "recursing-file", &cfg_type_qstring, 0 },
  791. { "random-device", &cfg_type_qstring, 0 },
  792. { "recursive-clients", &cfg_type_uint32, 0 },
  793. { "reserved-sockets", &cfg_type_uint32, 0 },
  794. { "secroots-file", &cfg_type_qstring, 0 },
  795. { "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
  796. { "serial-query-rate", &cfg_type_uint32, 0 },
  797. { "server-id", &cfg_type_serverid, 0 },
  798. { "stacksize", &cfg_type_size, 0 },
  799. { "statistics-file", &cfg_type_qstring, 0 },
  800. { "statistics-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_NYI },
  801. { "tcp-clients", &cfg_type_uint32, 0 },
  802. { "tcp-listen-queue", &cfg_type_uint32, 0 },
  803. { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
  804. { "tkey-gssapi-credential", &cfg_type_qstring, 0 },
  805. { "tkey-gssapi-keytab", &cfg_type_qstring, 0 },
  806. { "tkey-domain", &cfg_type_qstring, 0 },
  807. { "transfers-per-ns", &cfg_type_uint32, 0 },
  808. { "transfers-in", &cfg_type_uint32, 0 },
  809. { "transfers-out", &cfg_type_uint32, 0 },
  810. { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  811. { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  812. { "use-ixfr", &cfg_type_boolean, 0 },
  813. { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
  814. { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
  815. { "version", &cfg_type_qstringornone, 0 },
  816. { NULL, NULL, 0 }
  817. };
  818. static cfg_type_t cfg_type_namelist = {
  819. "namelist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
  820. cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_qstring };
  821. static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist };
  822. static cfg_type_t cfg_type_optional_exclude = {
  823. "optional_exclude", parse_optional_keyvalue, print_keyvalue,
  824. doc_optional_keyvalue, &cfg_rep_list, &exclude_kw };
  825. static keyword_type_t exceptionnames_kw = { "except-from", &cfg_type_namelist };
  826. static cfg_type_t cfg_type_optional_exceptionnames = {
  827. "optional_allow", parse_optional_keyvalue, print_keyvalue,
  828. doc_optional_keyvalue, &cfg_rep_list, &exceptionnames_kw };
  829. static cfg_tuplefielddef_t denyaddresses_fields[] = {
  830. { "acl", &cfg_type_bracketed_aml, 0 },
  831. { "except-from", &cfg_type_optional_exceptionnames, 0 },
  832. { NULL, NULL, 0 }
  833. };
  834. static cfg_type_t cfg_type_denyaddresses = {
  835. "denyaddresses", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  836. &cfg_rep_tuple, denyaddresses_fields
  837. };
  838. static cfg_tuplefielddef_t denyaliases_fields[] = {
  839. { "name", &cfg_type_namelist, 0 },
  840. { "except-from", &cfg_type_optional_exceptionnames, 0 },
  841. { NULL, NULL, 0 }
  842. };
  843. static cfg_type_t cfg_type_denyaliases = {
  844. "denyaliases", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  845. &cfg_rep_tuple, denyaliases_fields
  846. };
  847. static cfg_type_t cfg_type_algorithmlist = {
  848. "algorithmlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
  849. cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
  850. static cfg_tuplefielddef_t disablealgorithm_fields[] = {
  851. { "name", &cfg_type_astring, 0 },
  852. { "algorithms", &cfg_type_algorithmlist, 0 },
  853. { NULL, NULL, 0 }
  854. };
  855. static cfg_type_t cfg_type_disablealgorithm = {
  856. "disablealgorithm", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  857. &cfg_rep_tuple, disablealgorithm_fields
  858. };
  859. static cfg_tuplefielddef_t mustbesecure_fields[] = {
  860. { "name", &cfg_type_astring, 0 },
  861. { "value", &cfg_type_boolean, 0 },
  862. { NULL, NULL, 0 }
  863. };
  864. static cfg_type_t cfg_type_mustbesecure = {
  865. "mustbesecure", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  866. &cfg_rep_tuple, mustbesecure_fields
  867. };
  868. static const char *masterformat_enums[] = { "text", "raw", NULL };
  869. static cfg_type_t cfg_type_masterformat = {
  870. "masterformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  871. &cfg_rep_string, &masterformat_enums
  872. };
  873. /*
  874. * response-policy {
  875. * zone <string> [ policy (given|disabled|passthru|
  876. * nxdomain|nodata|cname <domain> ) ];
  877. * };
  878. *
  879. * this is a chimera of doc_optional_keyvalue() and cfg_doc_enum()
  880. */
  881. static void
  882. doc_rpz_policies(cfg_printer_t *pctx, const cfg_type_t *type) {
  883. const keyword_type_t *kw;
  884. const char * const *p;
  885. kw = type->of;
  886. cfg_print_chars(pctx, "[ ", 2);
  887. cfg_print_cstr(pctx, kw->name);
  888. cfg_print_chars(pctx, " ", 1);
  889. cfg_print_chars(pctx, "( ", 2);
  890. for (p = kw->type->of; *p != NULL; p++) {
  891. cfg_print_cstr(pctx, *p);
  892. if (p[1] != NULL)
  893. cfg_print_chars(pctx, " | ", 3);
  894. }
  895. }
  896. /*
  897. * print_qstring() from parser.c
  898. */
  899. static void
  900. print_rpz_cname(cfg_printer_t *pctx, const cfg_obj_t *obj)
  901. {
  902. cfg_print_chars(pctx, "\"", 1);
  903. cfg_print_ustring(pctx, obj);
  904. cfg_print_chars(pctx, "\"", 1);
  905. }
  906. static void
  907. doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
  908. cfg_doc_terminal(pctx, type);
  909. cfg_print_chars(pctx, " ) ]", 4);
  910. }
  911. static isc_result_t
  912. parse_rpz(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
  913. isc_result_t result;
  914. cfg_obj_t *obj = NULL;
  915. const cfg_tuplefielddef_t *fields = type->of;
  916. CHECK(cfg_create_tuple(pctx, type, &obj));
  917. CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
  918. CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
  919. /*
  920. * parse cname domain only after "policy cname"
  921. */
  922. if (cfg_obj_isvoid(obj->value.tuple[1]) ||
  923. strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[1]))) {
  924. CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
  925. } else {
  926. CHECK(cfg_parse_obj(pctx, fields[2].type, &obj->value.tuple[2]));
  927. }
  928. *ret = obj;
  929. return (ISC_R_SUCCESS);
  930. cleanup:
  931. CLEANUP_OBJ(obj);
  932. return (result);
  933. }
  934. static const char *rpz_policies[] = {
  935. "given", "disabled", "passthru", "no-op", "nxdomain", "nodata",
  936. "cname", NULL
  937. };
  938. static cfg_type_t cfg_type_rpz_policylist = {
  939. "policies", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
  940. &cfg_rep_string, &rpz_policies
  941. };
  942. static keyword_type_t rpz_policies_kw = {
  943. "policy", &cfg_type_rpz_policylist
  944. };
  945. static cfg_type_t cfg_type_rpz_policy = {
  946. "optional_policy", parse_optional_keyvalue, print_keyvalue,
  947. doc_rpz_policies, &cfg_rep_string, &rpz_policies_kw
  948. };
  949. static cfg_type_t cfg_type_cname = {
  950. "domain", cfg_parse_astring, print_rpz_cname, doc_rpz_cname,
  951. &cfg_rep_string, NULL
  952. };
  953. static cfg_tuplefielddef_t rpzone_fields[] = {
  954. { "name", &cfg_type_astring, 0 },
  955. { "policy", &cfg_type_rpz_policy, 0 },
  956. { "cname", &cfg_type_cname, 0 },
  957. { NULL, NULL, 0 }
  958. };
  959. static cfg_type_t cfg_type_rpzone = {
  960. "rpzone", parse_rpz, cfg_print_tuple, cfg_doc_tuple,
  961. &cfg_rep_tuple, rpzone_fields
  962. };
  963. static cfg_clausedef_t rpz_clauses[] = {
  964. { "zone", &cfg_type_rpzone, CFG_CLAUSEFLAG_MULTI },
  965. { NULL, NULL, 0 }
  966. };
  967. static cfg_clausedef_t *rpz_clausesets[] = {
  968. rpz_clauses,
  969. NULL
  970. };
  971. static cfg_type_t cfg_type_rpz = {
  972. "rpz", cfg_parse_map, cfg_print_map, cfg_doc_map,
  973. &cfg_rep_map, rpz_clausesets
  974. };
  975. /*%
  976. * dnssec-lookaside
  977. */
  978. static void
  979. print_lookaside(cfg_printer_t *pctx, const cfg_obj_t *obj)
  980. {
  981. const cfg_obj_t *domain = obj->value.tuple[0];
  982. if (domain->value.string.length == 4 &&
  983. strncmp(domain->value.string.base, "auto", 4) == 0)
  984. cfg_print_cstr(pctx, "auto");
  985. else
  986. cfg_print_tuple(pctx, obj);
  987. }
  988. static void
  989. doc_lookaside(cfg_printer_t *pctx, const cfg_type_t *type) {
  990. UNUSED(type);
  991. cfg_print_cstr(pctx, "( <string> trust-anchor <string> | auto | no )");
  992. }
  993. static keyword_type_t trustanchor_kw = { "trust-anchor", &cfg_type_astring };
  994. static cfg_type_t cfg_type_optional_trustanchor = {
  995. "optional_trustanchor", parse_optional_keyvalue, print_keyvalue,
  996. doc_keyvalue, &cfg_rep_string, &trustanchor_kw
  997. };
  998. static cfg_tuplefielddef_t lookaside_fields[] = {
  999. { "domain", &cfg_type_astring, 0 },
  1000. { "trust-anchor", &cfg_type_optional_trustanchor, 0 },
  1001. { NULL, NULL, 0 }
  1002. };
  1003. static cfg_type_t cfg_type_lookaside = {
  1004. "lookaside", cfg_parse_tuple, print_lookaside, doc_lookaside,
  1005. &cfg_rep_tuple, lookaside_fields
  1006. };
  1007. /*
  1008. * DNS64.
  1009. */
  1010. static cfg_clausedef_t
  1011. dns64_clauses[] = {
  1012. { "clients", &cfg_type_bracketed_aml, 0 },
  1013. { "mapped", &cfg_type_bracketed_aml, 0 },
  1014. { "exclude", &cfg_type_bracketed_aml, 0 },
  1015. { "suffix", &cfg_type_netaddr6, 0 },
  1016. { "recursive-only", &cfg_type_boolean, 0 },
  1017. { "break-dnssec", &cfg_type_boolean, 0 },
  1018. { NULL, NULL, 0 },
  1019. };
  1020. static cfg_clausedef_t *
  1021. dns64_clausesets[] = {
  1022. dns64_clauses,
  1023. NULL
  1024. };
  1025. static cfg_type_t cfg_type_dns64 = {
  1026. "dns64", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map,
  1027. &cfg_rep_map, dns64_clausesets
  1028. };
  1029. /*%
  1030. * Clauses that can be found within the 'view' statement,
  1031. * with defaults in the 'options' statement.
  1032. */
  1033. static cfg_clausedef_t
  1034. view_clauses[] = {
  1035. { "acache-cleaning-interval", &cfg_type_uint32, 0 },
  1036. { "acache-enable", &cfg_type_boolean, 0 },
  1037. { "additional-from-auth", &cfg_type_boolean, 0 },
  1038. { "additional-from-cache", &cfg_type_boolean, 0 },
  1039. { "allow-new-zones", &cfg_type_boolean, 0 },
  1040. { "allow-query-cache", &cfg_type_bracketed_aml, 0 },
  1041. { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
  1042. { "allow-recursion", &cfg_type_bracketed_aml, 0 },
  1043. { "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
  1044. { "allow-v6-synthesis", &cfg_type_bracketed_aml,
  1045. CFG_CLAUSEFLAG_OBSOLETE },
  1046. { "attach-cache", &cfg_type_astring, 0 },
  1047. { "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
  1048. { "cache-file", &cfg_type_qstring, 0 },
  1049. { "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
  1050. { "cleaning-interval", &cfg_type_uint32, 0 },
  1051. { "clients-per-query", &cfg_type_uint32, 0 },
  1052. { "deny-answer-addresses", &cfg_type_denyaddresses, 0 },
  1053. { "deny-answer-aliases", &cfg_type_denyaliases, 0 },
  1054. { "disable-algorithms", &cfg_type_disablealgorithm,
  1055. CFG_CLAUSEFLAG_MULTI },
  1056. { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
  1057. { "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
  1058. { "dns64-server", &cfg_type_astring, 0 },
  1059. { "dns64-contact", &cfg_type_astring, 0 },
  1060. { "dnssec-accept-expired", &cfg_type_boolean, 0 },
  1061. { "dnssec-enable", &cfg_type_boolean, 0 },
  1062. { "dnssec-lookaside", &cfg_type_lookaside, CFG_CLAUSEFLAG_MULTI },
  1063. { "dnssec-must-be-secure", &cfg_type_mustbesecure,
  1064. CFG_CLAUSEFLAG_MULTI },
  1065. { "dnssec-validation", &cfg_type_boolorauto, 0 },
  1066. { "dual-stack-servers", &cfg_type_nameportiplist, 0 },
  1067. { "edns-udp-size", &cfg_type_uint32, 0 },
  1068. { "empty-contact", &cfg_type_astring, 0 },
  1069. { "empty-server", &cfg_type_astring, 0 },
  1070. { "empty-zones-enable", &cfg_type_boolean, 0 },
  1071. { "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  1072. { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
  1073. { "lame-ttl", &cfg_type_uint32, 0 },
  1074. { "max-acache-size", &cfg_type_sizenodefault, 0 },
  1075. { "max-cache-size", &cfg_type_sizenodefault, 0 },
  1076. { "max-cache-ttl", &cfg_type_uint32, 0 },
  1077. { "max-clients-per-query", &cfg_type_uint32, 0 },
  1078. { "max-ncache-ttl", &cfg_type_uint32, 0 },
  1079. { "max-udp-size", &cfg_type_uint32, 0 },
  1080. { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
  1081. { "minimal-responses", &cfg_type_boolean, 0 },
  1082. { "preferred-glue", &cfg_type_astring, 0 },
  1083. { "provide-ixfr", &cfg_type_boolean, 0 },
  1084. /*
  1085. * Note that the query-source option syntax is different
  1086. * from the other -source options.
  1087. */
  1088. { "query-source", &cfg_type_querysource4, 0 },
  1089. { "query-source-v6", &cfg_type_querysource6, 0 },
  1090. { "queryport-pool-ports", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
  1091. { "queryport-pool-updateinterval", &cfg_type_uint32,
  1092. CFG_CLAUSEFLAG_OBSOLETE },
  1093. { "recursion", &cfg_type_boolean, 0 },
  1094. { "request-ixfr", &cfg_type_boolean, 0 },
  1095. { "request-nsid", &cfg_type_boolean, 0 },
  1096. { "resolver-query-timeout", &cfg_type_uint32, 0 },
  1097. { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
  1098. { "root-delegation-only", &cfg_type_optional_exclude, 0 },
  1099. { "rrset-order", &cfg_type_rrsetorder, 0 },
  1100. { "sortlist", &cfg_type_bracketed_aml, 0 },
  1101. { "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
  1102. { "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
  1103. { "transfer-format", &cfg_type_transferformat, 0 },
  1104. { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  1105. { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
  1106. #ifdef ALLOW_FILTER_AAAA_ON_V4
  1107. { "filter-aaaa", &cfg_type_bracketed_aml, 0 },
  1108. { "filter-aaaa-on-v4", &cfg_type_v4_aaaa, 0 },
  1109. #else
  1110. { "filter-aaaa", &cfg_type_bracketed_aml,
  1111. CFG_CLAUSEFLAG_NOTCONFIGURED },
  1112. { "filter-aaaa-on-v4", &cfg_type_v4_aaaa,
  1113. CFG_CLAUSEFLAG_NOTCONFIGURED },
  1114. #endif
  1115. { "response-policy", &cfg_type_rpz, 0 },
  1116. { NULL, NULL, 0 }
  1117. };
  1118. /*%
  1119. * Clauses that can be found within the 'view' statement only.
  1120. */
  1121. static cfg_clausedef_t
  1122. view_only_clauses[] = {
  1123. { "match-clients", &cfg_type_bracketed_aml, 0 },
  1124. { "match-destinations", &cfg_type_bracketed_aml, 0 },
  1125. { "match-recursive-only", &cfg_type_boolean, 0 },
  1126. { NULL, NULL, 0 }
  1127. };
  1128. /*%
  1129. * Sig-validity-interval.
  1130. */
  1131. static isc_result_t
  1132. parse_optional_uint32(cfg_parser_t *pctx, const cfg_type_t *type,
  1133. cfg_obj_t **ret)
  1134. {
  1135. isc_result_t result;
  1136. UNUSED(type);
  1137. CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
  1138. if (pctx->token.type == isc_tokentype_number) {
  1139. CHECK(cfg_parse_obj(pctx, &cfg_type_uint32, ret));
  1140. } else {
  1141. CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
  1142. }
  1143. cleanup:
  1144. return (result);
  1145. }
  1146. static void
  1147. doc_optional_uint32(cfg_printer_t *pctx, const cfg_type_t *type) {
  1148. UNUSED(type);
  1149. cfg_print_cstr(pctx, "[ <integer> ]");
  1150. }
  1151. static cfg_type_t cfg_type_optional_uint32 = {
  1152. "optional_uint32", parse_optional_uint32, NULL, doc_optional_uint32,
  1153. NULL, NULL };
  1154. static cfg_tuplefielddef_t validityinterval_fields[] = {
  1155. { "validity", &cfg_type_uint32, 0 },
  1156. { "re-sign", &cfg_type_optional_uint32, 0 },
  1157. { NULL, NULL, 0 }
  1158. };
  1159. static cfg_type_t cfg_type_validityinterval = {
  1160. "validityinterval", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
  1161. &cfg_rep_tuple, validityinterval_fields
  1162. };
  1163. /*%
  1164. * Clauses that can be found in a 'zone' statement,
  1165. * with defaults in the 'view' or 'options' statement.
  1166. */
  1167. static cfg_clausedef_t
  1168. zone_clauses[] = {
  1169. { "allow-notify", &cfg_type_bracketed_aml, 0 },
  1170. { "allow-query", &cfg_type_bracketed_aml, 0 },
  1171. { "allow-query-on", &cfg_type_bracketed_aml, 0 },
  1172. { "allow-transfer", &cfg_type_bracketed_aml, 0 },
  1173. { "allow-update", &cfg_type_bracketed_aml, 0 },
  1174. { "allow-update-forwarding", &cfg_type_bracketed_aml, 0 },
  1175. { "also-notify", &cfg_type_portiplist, 0 },
  1176. { "alt-transfer-source", &cfg_type_sockaddr4wild, 0 },
  1177. { "alt-transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
  1178. { "auto-dnssec", &cfg_type_autodnssec, 0 },
  1179. { "check-dup-records", &cfg_type_checkmode, 0 },
  1180. { "check-integrity", &cfg_type_boolean, 0 },
  1181. { "check-mx", &cfg_type_checkmode, 0 },
  1182. { "check-mx-cname", &cfg_type_checkmode, 0 },
  1183. { "check-sibling", &cfg_type_boolean, 0 },
  1184. { "check-srv-cname", &cfg_type_checkmode, 0 },
  1185. { "check-wildcard", &cfg_type_boolean, 0 },
  1186. { "dialup", &cfg_type_dialuptype, 0 },
  1187. { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 },
  1188. { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 },
  1189. { "forward", &cfg_type_forwardtype, 0 },
  1190. { "forwarders", &cfg_type_portiplist, 0 },
  1191. { "key-directory", &cfg_type_qstring, 0 },
  1192. { "maintain-ixfr-base", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  1193. { "masterfile-format", &cfg_type_masterformat, 0 },
  1194. { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE },
  1195. { "max-journal-size", &cfg_type_sizenodefault, 0 },
  1196. { "max-refresh-time", &cfg_type_uint32, 0 },
  1197. { "max-retry-time", &cfg_type_uint32, 0 },
  1198. { "max-transfer-idle-in", &cfg_type_uint32, 0 },
  1199. { "max-transfer-idle-out", &cfg_type_uint32, 0 },
  1200. { "max-transfer-time-in", &cfg_type_uint32, 0 },
  1201. { "max-transfer-time-out", &cfg_type_uint32, 0 },
  1202. { "min-refresh-time", &cfg_type_uint32, 0 },
  1203. { "min-retry-time", &cfg_type_uint32, 0 },
  1204. { "multi-master", &cfg_type_boolean, 0 },
  1205. { "notify", &cfg_type_notifytype, 0 },
  1206. { "notify-delay", &cfg_type_uint32, 0 },
  1207. { "notify-source", &cfg_type_sockaddr4wild, 0 },
  1208. { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
  1209. { "notify-to-soa", &cfg_type_boolean, 0 },
  1210. { "nsec3-test-zone", &cfg_type_boolean, CFG_CLAUSEFLAG_TESTONLY },
  1211. { "sig-signing-nodes", &cfg_type_uint32, 0 },
  1212. { "sig-signing-signatures", &cfg_type_uint32, 0 },
  1213. { "sig-signing-type", &cfg_type_uint32, 0 },
  1214. { "sig-validity-interval", &cfg_type_validityinterval, 0 },
  1215. { "transfer-source", &cfg_type_sockaddr4wild, 0 },
  1216. { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
  1217. { "try-tcp-refresh", &cfg_type_boolean, 0 },
  1218. { "update-check-ksk", &cfg_type_boolean, 0 },
  1219. { "use-alt-transfer-source", &cfg_type_boolean, 0 },
  1220. { "zero-no-soa-ttl", &cfg_type_boolean, 0 },
  1221. { "zone-statistics", &cfg_type_boolean, 0 },
  1222. { NULL, NULL, 0 }
  1223. };
  1224. /*%
  1225. * Clauses that can be found in a 'zone' statement
  1226. * only.
  1227. */
  1228. static cfg_clausedef_t
  1229. zone_only_clauses[] = {
  1230. { "type", &cfg_type_zonetype, 0 },
  1231. { "file", &cfg_type_qstring, 0 },
  1232. { "journal", &cfg_type_qstring, 0 },
  1233. { "ixfr-base", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
  1234. { "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
  1235. { "masters", &cfg_type_namesockaddrkeylist, 0 },
  1236. { "pubkey", &cfg_type_pubkey,
  1237. CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
  1238. { "update-policy", &cfg_type_updatepolicy, 0 },
  1239. { "database", &cfg_type_astring, 0 },
  1240. { "delegation-only", &cfg_type_boolean, 0 },
  1241. /*
  1242. * Note that the format of the check-names option is different between
  1243. * the zone options and the global/view options. Ugh.
  1244. */
  1245. { "check-names", &cfg_type_checkmode, 0 },
  1246. { "ixfr-from-differences", &cfg_type_boolean, 0 },
  1247. { "server-addresses", &cfg_type_bracketed_sockaddrlist, 0 },
  1248. { "server-names", &cfg_type_namelist, 0 },
  1249. { NULL, NULL, 0 }
  1250. };
  1251. /*% The top-level named.conf syntax. */
  1252. static cfg_clausedef_t *
  1253. namedconf_clausesets[] = {
  1254. namedconf_clauses,
  1255. namedconf_or_view_clauses,
  1256. NULL
  1257. };
  1258. LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = {
  1259. "namedconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
  1260. &cfg_rep_map, namedconf_clausesets
  1261. };
  1262. /*% The bind.keys syntax (trusted-keys/managed-keys only). */
  1263. static cfg_clausedef_t *
  1264. bindkeys_clausesets[] = {
  1265. bindkeys_clauses,
  1266. NULL
  1267. };
  1268. LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_bindkeys = {
  1269. "bindkeys", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
  1270. &cfg_rep_map, bindkeys_clausesets
  1271. };
  1272. /*% The new-zone-file syntax (for zones added by 'rndc addzone') */
  1273. static cfg_clausedef_t
  1274. newzones_clauses[] = {
  1275. { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
  1276. { NULL, NULL, 0 }
  1277. };
  1278. static cfg_clausedef_t *
  1279. newzones_clausesets[] = {
  1280. newzones_clauses,
  1281. NULL
  1282. };
  1283. LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_newzones = {
  1284. "newzones", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
  1285. &cfg_rep_map, newzones_clausesets
  1286. };
  1287. /*% The "options" statement syntax. */
  1288. static cfg_clausedef_t *
  1289. options_clausesets[] = {
  1290. options_clauses,
  1291. view_clauses,
  1292. zone_clauses,
  1293. NULL
  1294. };
  1295. static cfg_type_t cfg_type_options = {
  1296. "options", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, options_clausesets };
  1297. /*% The "view" statement syntax. */
  1298. static cfg_clausedef_t *
  1299. view_clausesets[] = {
  1300. view_only_clauses,
  1301. namedconf_or_view_clauses,
  1302. view_clauses,
  1303. zone_clauses,
  1304. dynamically_loadable_zones_clauses,
  1305. NULL
  1306. };
  1307. static cfg_type_t cfg_type_viewopts = {
  1308. "view", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, view_clausesets };
  1309. /*% The "zone" statement syntax. */
  1310. static cfg_clausedef_t *
  1311. zone_clausesets[] = {
  1312. zone_only_clauses,
  1313. zone_clauses,
  1314. NULL
  1315. };
  1316. static cfg_type_t cfg_type_zoneopts = {
  1317. "zoneopts", cfg_parse_map, cfg_print_map,
  1318. cfg_doc_map, &cfg_rep_map, zone_clausesets };
  1319. /*% The "dynamically loadable zones" statement syntax. */
  1320. static cfg_clausedef_t *
  1321. dynamically_loadable_zones_clausesets[] = {
  1322. dynamically_loadable_zones_clauses,
  1323. NULL
  1324. };
  1325. static cfg_type_t cfg_type_dynamically_loadable_zones_opts = {
  1326. "dynamically_loadable_zones_opts", cfg_parse_map,
  1327. cfg_print_map, cfg_doc_map, &cfg_rep_map,
  1328. dynamically_loadable_zones_clausesets
  1329. };
  1330. /*%
  1331. * Clauses that can be found within the 'key' statement.
  1332. */
  1333. static cfg_clausedef_t
  1334. key_clauses[] = {
  1335. { "algorithm", &cfg_type_astring, 0 },
  1336. { "secret", &cfg_type_astring, 0 },
  1337. { NULL, NULL, 0 }
  1338. };
  1339. static cfg_clausedef_t *
  1340. key_clausesets[] = {
  1341. key_clauses,
  1342. NULL
  1343. };
  1344. static cfg_type_t cfg_type_key = {
  1345. "key", cfg_parse_named_map, cfg_print_map,
  1346. cfg_doc_map, &cfg_rep_map, key_clausesets
  1347. };
  1348. /*%
  1349. * Clauses that can be found in a 'server' statement.
  1350. */
  1351. static cfg_clausedef_t
  1352. server_clauses[] = {
  1353. { "bogus", &cfg_type_boolean, 0 },
  1354. { "provide-ixfr", &cfg_type_boolean, 0 },
  1355. { "request-ixfr", &cfg_type_boolean, 0 },
  1356. { "support-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
  1357. { "transfers", &cfg_type_uint32, 0 },
  1358. { "transfer-format", &cfg_type_transferformat, 0 },
  1359. { "keys", &cfg_type_server_key_kludge, 0 },
  1360. { "edns", &cfg_type_boolean, 0 },
  1361. { "edns-udp-size", &cfg_type_uint32, 0 },
  1362. { "max-udp-size", &cfg_type_uint32, 0 },
  1363. { "notify-source", &cfg_type_sockaddr4wild, 0 },
  1364. { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
  1365. { "query-source", &cfg_type_querysource4, 0 },
  1366. { "query-source-v6", &cfg_type_querysource6, 0 },
  1367. { "transfer-source", &cfg_type_sockaddr4wild, 0 },
  1368. { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
  1369. { NULL, NULL, 0 }
  1370. };
  1371. static cfg_clausedef_t *
  1372. server_clausesets[] = {
  1373. server_clauses,
  1374. NULL
  1375. };
  1376. static cfg_type_t cfg_type_server = {
  1377. "server", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
  1378. server_clausesets
  1379. };
  1380. /*%
  1381. * Clauses that can be found in a 'channel' clause in the
  1382. * 'logging' statement.
  1383. *
  1384. * These have some additional constraints that need to be
  1385. * checked after parsing:
  1386. * - There must exactly one of file/syslog/null/stderr
  1387. *
  1388. */
  1389. static cfg_clausedef_t
  1390. channel_clauses[] = {
  1391. /* Destinations. We no longer require these to be first. */
  1392. { "file", &cfg_type_logfile, 0 },
  1393. { "syslog", &cfg_type_optional_facility, 0 },
  1394. { "null", &cfg_type_void, 0 },
  1395. { "stderr", &cfg_type_void, 0 },
  1396. /* Options. We now accept these for the null channel, too. */
  1397. { "severity", &cfg_type_logseverity, 0 },
  1398. { "print-time", &cfg_type_boolean, 0 },
  1399. { "print-severity", &cfg_type_boolean, 0 },
  1400. { "print-category", &cfg_type_boolean, 0 },
  1401. { NULL, NULL, 0 }
  1402. };
  1403. static cfg_clausedef_t *
  1404. channel_clausesets[] = {
  1405. channel_clauses,
  1406. NULL
  1407. };
  1408. static cfg_type_t cfg_type_channel = {
  1409. "channel", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
  1410. &cfg_rep_map, channel_clausesets
  1411. };
  1412. /*% A list of log destination, used in the "category" clause. */
  1413. static cfg_type_t cfg_type_destinationlist = {
  1414. "destinationlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
  1415. &cfg_rep_list, &cfg_type_astring };
  1416. /*%
  1417. * Clauses that can be found in a 'logging' statement.
  1418. */
  1419. static cfg_clausede