Home | History | Annotate | Line # | Download | only in isccfg
namedconf.c revision 1.15.2.1
      1  1.15.2.1  perseant /*	$NetBSD: namedconf.c,v 1.15.2.1 2025/08/02 05:54:06 perseant Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*
      4       1.1  christos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5       1.1  christos  *
      6      1.13  christos  * SPDX-License-Identifier: MPL-2.0
      7      1.13  christos  *
      8       1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      9       1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10       1.9  christos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11       1.1  christos  *
     12       1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     13       1.1  christos  * information regarding copyright ownership.
     14       1.1  christos  */
     15       1.1  christos 
     16       1.1  christos /*! \file */
     17       1.1  christos 
     18       1.3  christos #include <inttypes.h>
     19       1.3  christos #include <stdbool.h>
     20       1.1  christos #include <stdlib.h>
     21       1.1  christos #include <string.h>
     22       1.1  christos 
     23       1.1  christos #include <isc/lex.h>
     24       1.1  christos #include <isc/mem.h>
     25       1.1  christos #include <isc/result.h>
     26       1.1  christos #include <isc/string.h>
     27       1.1  christos #include <isc/util.h>
     28       1.1  christos 
     29       1.1  christos #include <dns/ttl.h>
     30       1.1  christos 
     31       1.1  christos #include <isccfg/cfg.h>
     32       1.1  christos #include <isccfg/grammar.h>
     33       1.1  christos #include <isccfg/log.h>
     34       1.1  christos #include <isccfg/namedconf.h>
     35       1.1  christos 
     36       1.1  christos #define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
     37       1.1  christos 
     38       1.1  christos /*% Check a return value. */
     39       1.8  christos #define CHECK(op)                            \
     40       1.8  christos 	do {                                 \
     41       1.8  christos 		result = (op);               \
     42       1.8  christos 		if (result != ISC_R_SUCCESS) \
     43       1.8  christos 			goto cleanup;        \
     44      1.10    rillig 	} while (0)
     45       1.1  christos 
     46       1.1  christos /*% Clean up a configuration object if non-NULL. */
     47       1.8  christos #define CLEANUP_OBJ(obj)                               \
     48       1.8  christos 	do {                                           \
     49       1.8  christos 		if ((obj) != NULL)                     \
     50       1.8  christos 			cfg_obj_destroy(pctx, &(obj)); \
     51      1.10    rillig 	} while (0)
     52       1.1  christos 
     53       1.1  christos /*%
     54       1.1  christos  * Forward declarations of static functions.
     55       1.1  christos  */
     56       1.1  christos 
     57       1.1  christos static isc_result_t
     58       1.1  christos parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
     59       1.1  christos 
     60       1.1  christos static isc_result_t
     61       1.1  christos parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
     62       1.1  christos 			cfg_obj_t **ret);
     63       1.1  christos 
     64       1.1  christos static isc_result_t
     65       1.8  christos parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
     66       1.1  christos static void
     67       1.1  christos print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj);
     68       1.1  christos 
     69       1.1  christos static void
     70       1.1  christos doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type);
     71       1.1  christos 
     72       1.1  christos static void
     73       1.1  christos print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj);
     74       1.1  christos 
     75       1.1  christos static void
     76       1.1  christos doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
     77       1.1  christos 
     78       1.1  christos static void
     79       1.1  christos doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
     80       1.1  christos 
     81      1.15  christos static isc_result_t
     82      1.15  christos cfg_parse_kv_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
     83      1.15  christos 
     84      1.15  christos static void
     85      1.15  christos cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj);
     86      1.15  christos 
     87      1.15  christos static void
     88      1.15  christos cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type);
     89      1.15  christos 
     90       1.1  christos static cfg_type_t cfg_type_acl;
     91       1.1  christos static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
     92       1.3  christos static cfg_type_t cfg_type_bracketed_netaddrlist;
     93       1.1  christos static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
     94  1.15.2.1  perseant static cfg_type_t cfg_type_bracketed_sockaddrtlslist;
     95      1.15  christos static cfg_type_t cfg_type_bracketed_http_endpoint_list;
     96  1.15.2.1  perseant static cfg_type_t cfg_type_checkdstype;
     97       1.1  christos static cfg_type_t cfg_type_controls;
     98       1.1  christos static cfg_type_t cfg_type_controls_sockaddr;
     99       1.1  christos static cfg_type_t cfg_type_destinationlist;
    100       1.1  christos static cfg_type_t cfg_type_dialuptype;
    101       1.1  christos static cfg_type_t cfg_type_dlz;
    102       1.8  christos static cfg_type_t cfg_type_dnssecpolicy;
    103       1.1  christos static cfg_type_t cfg_type_dnstap;
    104       1.1  christos static cfg_type_t cfg_type_dnstapoutput;
    105       1.1  christos static cfg_type_t cfg_type_dyndb;
    106      1.15  christos static cfg_type_t cfg_type_http_description;
    107       1.1  christos static cfg_type_t cfg_type_ixfrdifftype;
    108       1.9  christos static cfg_type_t cfg_type_ixfrratio;
    109       1.1  christos static cfg_type_t cfg_type_key;
    110  1.15.2.1  perseant static cfg_type_t cfg_type_keystore;
    111       1.1  christos static cfg_type_t cfg_type_logfile;
    112       1.1  christos static cfg_type_t cfg_type_logging;
    113       1.1  christos static cfg_type_t cfg_type_logseverity;
    114       1.1  christos static cfg_type_t cfg_type_logsuffix;
    115       1.1  christos static cfg_type_t cfg_type_logversions;
    116      1.12  christos static cfg_type_t cfg_type_remoteselement;
    117       1.8  christos static cfg_type_t cfg_type_maxduration;
    118       1.1  christos static cfg_type_t cfg_type_minimal;
    119       1.1  christos static cfg_type_t cfg_type_nameportiplist;
    120       1.1  christos static cfg_type_t cfg_type_notifytype;
    121       1.1  christos static cfg_type_t cfg_type_optional_allow;
    122       1.1  christos static cfg_type_t cfg_type_optional_class;
    123       1.1  christos static cfg_type_t cfg_type_optional_facility;
    124       1.1  christos static cfg_type_t cfg_type_optional_keyref;
    125       1.1  christos static cfg_type_t cfg_type_optional_port;
    126  1.15.2.1  perseant static cfg_type_t cfg_type_optional_sourceaddr4;
    127  1.15.2.1  perseant static cfg_type_t cfg_type_optional_sourceaddr6;
    128       1.1  christos static cfg_type_t cfg_type_optional_uint32;
    129      1.15  christos static cfg_type_t cfg_type_optional_tls;
    130       1.1  christos static cfg_type_t cfg_type_options;
    131      1.15  christos static cfg_type_t cfg_type_plugin;
    132       1.1  christos static cfg_type_t cfg_type_portiplist;
    133       1.1  christos static cfg_type_t cfg_type_printtime;
    134       1.3  christos static cfg_type_t cfg_type_qminmethod;
    135       1.1  christos static cfg_type_t cfg_type_querysource4;
    136       1.1  christos static cfg_type_t cfg_type_querysource6;
    137  1.15.2.1  perseant static cfg_type_t cfg_type_server_querysource4;
    138  1.15.2.1  perseant static cfg_type_t cfg_type_server_querysource6;
    139       1.1  christos static cfg_type_t cfg_type_querysource;
    140       1.1  christos static cfg_type_t cfg_type_server;
    141       1.1  christos static cfg_type_t cfg_type_server_key_kludge;
    142       1.1  christos static cfg_type_t cfg_type_size;
    143       1.1  christos static cfg_type_t cfg_type_sizenodefault;
    144       1.1  christos static cfg_type_t cfg_type_sizeorpercent;
    145       1.1  christos static cfg_type_t cfg_type_sizeval;
    146       1.1  christos static cfg_type_t cfg_type_sockaddr4wild;
    147       1.1  christos static cfg_type_t cfg_type_sockaddr6wild;
    148       1.1  christos static cfg_type_t cfg_type_statschannels;
    149      1.15  christos static cfg_type_t cfg_type_tlsconf;
    150       1.1  christos static cfg_type_t cfg_type_view;
    151       1.1  christos static cfg_type_t cfg_type_viewopts;
    152       1.1  christos static cfg_type_t cfg_type_zone;
    153       1.1  christos 
    154       1.1  christos /*% listen-on */
    155       1.1  christos 
    156      1.15  christos static cfg_tuplefielddef_t listenon_tuple_fields[] = {
    157      1.15  christos 	{ "port", &cfg_type_optional_port, 0 },
    158  1.15.2.1  perseant 	/*
    159  1.15.2.1  perseant 	 * Let's follow the protocols encapsulation order (lower->upper), at
    160  1.15.2.1  perseant 	 * least roughly.
    161  1.15.2.1  perseant 	 */
    162  1.15.2.1  perseant 	{ "proxy", &cfg_type_astring, CFG_CLAUSEFLAG_EXPERIMENTAL },
    163      1.15  christos 	{ "tls", &cfg_type_astring, 0 },
    164      1.15  christos #if HAVE_LIBNGHTTP2
    165      1.15  christos 	{ "http", &cfg_type_astring, 0 },
    166      1.15  christos #else
    167      1.15  christos 	{ "http", &cfg_type_astring, CFG_CLAUSEFLAG_NOTCONFIGURED },
    168      1.15  christos #endif
    169      1.15  christos 	{ NULL, NULL, 0 }
    170      1.15  christos };
    171      1.15  christos static cfg_type_t cfg_type_listen_tuple = {
    172      1.15  christos 	"listenon tuple", cfg_parse_kv_tuple, cfg_print_kv_tuple,
    173      1.15  christos 	cfg_doc_kv_tuple, &cfg_rep_tuple,     listenon_tuple_fields
    174      1.15  christos };
    175      1.15  christos 
    176       1.1  christos static cfg_tuplefielddef_t listenon_fields[] = {
    177      1.15  christos 	{ "tuple", &cfg_type_listen_tuple, 0 },
    178       1.1  christos 	{ "acl", &cfg_type_bracketed_aml, 0 },
    179       1.1  christos 	{ NULL, NULL, 0 }
    180       1.1  christos };
    181       1.1  christos 
    182       1.8  christos static cfg_type_t cfg_type_listenon = { "listenon",	 cfg_parse_tuple,
    183       1.8  christos 					cfg_print_tuple, cfg_doc_tuple,
    184       1.8  christos 					&cfg_rep_tuple,	 listenon_fields };
    185       1.1  christos 
    186       1.1  christos /*% acl */
    187       1.1  christos 
    188      1.15  christos /*
    189      1.15  christos  * Encrypted transfer related definitions
    190      1.15  christos  */
    191      1.15  christos 
    192      1.15  christos static cfg_tuplefielddef_t cfg_transport_acl_tuple_fields[] = {
    193      1.15  christos 	{ "port", &cfg_type_optional_port, 0 },
    194      1.15  christos 	{ "transport", &cfg_type_astring, 0 },
    195      1.15  christos 	{ NULL, NULL, 0 }
    196      1.15  christos };
    197      1.15  christos static cfg_type_t cfg_transport_acl_tuple = {
    198      1.15  christos 	"transport-acl tuple", cfg_parse_kv_tuple,
    199      1.15  christos 	cfg_print_kv_tuple,    cfg_doc_kv_tuple,
    200      1.15  christos 	&cfg_rep_tuple,	       cfg_transport_acl_tuple_fields
    201      1.15  christos };
    202      1.15  christos 
    203      1.15  christos static cfg_tuplefielddef_t cfg_transport_acl_fields[] = {
    204      1.15  christos 	{ "port-transport", &cfg_transport_acl_tuple, 0 },
    205      1.15  christos 	{ "aml", &cfg_type_bracketed_aml, 0 },
    206      1.15  christos 	{ NULL, NULL, 0 }
    207      1.15  christos };
    208      1.15  christos 
    209      1.15  christos static cfg_type_t cfg_type_transport_acl = {
    210      1.15  christos 	"transport-acl", cfg_parse_tuple, cfg_print_tuple,
    211      1.15  christos 	cfg_doc_tuple,	 &cfg_rep_tuple,  cfg_transport_acl_fields
    212      1.15  christos };
    213      1.15  christos 
    214      1.15  christos /*
    215      1.15  christos  * NOTE: To enable syntax which allows specifying port and protocol,
    216      1.15  christos  * replace 'cfg_type_bracketed_aml' with
    217      1.15  christos  * 'cfg_type_transport_acl'.
    218      1.15  christos  *
    219      1.15  christos  * Example: acl port 853 protocol tls { ... };
    220      1.15  christos  */
    221       1.8  christos static cfg_tuplefielddef_t acl_fields[] = { { "name", &cfg_type_astring, 0 },
    222       1.8  christos 					    { "value", &cfg_type_bracketed_aml,
    223       1.8  christos 					      0 },
    224       1.8  christos 					    { NULL, NULL, 0 } };
    225       1.8  christos 
    226       1.8  christos static cfg_type_t cfg_type_acl = { "acl",	    cfg_parse_tuple,
    227       1.8  christos 				   cfg_print_tuple, cfg_doc_tuple,
    228       1.8  christos 				   &cfg_rep_tuple,  acl_fields };
    229       1.1  christos 
    230      1.12  christos /*% remote servers, used for primaries and parental agents */
    231      1.12  christos static cfg_tuplefielddef_t remotes_fields[] = {
    232       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    233       1.1  christos 	{ "port", &cfg_type_optional_port, 0 },
    234  1.15.2.1  perseant 	{ "source", &cfg_type_optional_sourceaddr4, 0 },
    235  1.15.2.1  perseant 	{ "source-v6", &cfg_type_optional_sourceaddr6, 0 },
    236       1.1  christos 	{ "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
    237       1.1  christos 	{ NULL, NULL, 0 }
    238       1.1  christos };
    239       1.1  christos 
    240  1.15.2.1  perseant static cfg_type_t cfg_type_serverlist = { "server-list",   cfg_parse_tuple,
    241  1.15.2.1  perseant 					  cfg_print_tuple, cfg_doc_tuple,
    242  1.15.2.1  perseant 					  &cfg_rep_tuple,  remotes_fields };
    243       1.1  christos 
    244       1.1  christos /*%
    245       1.1  christos  * "sockaddrkeylist", a list of socket addresses with optional keys
    246      1.12  christos  * and an optional default port, as used in the remote-servers option.
    247       1.1  christos  * E.g.,
    248      1.12  christos  *   "port 1234 { myservers; 10.0.0.1 key foo; 1::2 port 69; }"
    249       1.1  christos  */
    250       1.1  christos 
    251       1.1  christos static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
    252      1.12  christos 	{ "remoteselement", &cfg_type_remoteselement, 0 },
    253       1.1  christos 	{ "key", &cfg_type_optional_keyref, 0 },
    254      1.15  christos 	{ "tls", &cfg_type_optional_tls, 0 },
    255       1.1  christos 	{ NULL, NULL, 0 },
    256       1.1  christos };
    257       1.1  christos 
    258       1.1  christos static cfg_type_t cfg_type_namesockaddrkey = {
    259       1.8  christos 	"namesockaddrkey", cfg_parse_tuple, cfg_print_tuple,
    260       1.8  christos 	cfg_doc_tuple,	   &cfg_rep_tuple,  namesockaddrkey_fields
    261       1.1  christos };
    262       1.1  christos 
    263       1.1  christos static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
    264       1.8  christos 	"bracketed_namesockaddrkeylist",
    265       1.8  christos 	cfg_parse_bracketed_list,
    266       1.8  christos 	cfg_print_bracketed_list,
    267       1.8  christos 	cfg_doc_bracketed_list,
    268       1.8  christos 	&cfg_rep_list,
    269       1.1  christos 	&cfg_type_namesockaddrkey
    270       1.1  christos };
    271       1.1  christos 
    272       1.1  christos static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
    273       1.1  christos 	{ "port", &cfg_type_optional_port, 0 },
    274  1.15.2.1  perseant 	{ "source", &cfg_type_optional_sourceaddr4, 0 },
    275  1.15.2.1  perseant 	{ "source-v6", &cfg_type_optional_sourceaddr6, 0 },
    276       1.1  christos 	{ "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
    277       1.1  christos 	{ NULL, NULL, 0 }
    278       1.1  christos };
    279       1.1  christos static cfg_type_t cfg_type_namesockaddrkeylist = {
    280       1.8  christos 	"sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple,
    281       1.8  christos 	cfg_doc_tuple,	   &cfg_rep_tuple,  namesockaddrkeylist_fields
    282       1.1  christos };
    283       1.1  christos 
    284       1.1  christos /*%
    285       1.1  christos  * A list of socket addresses with an optional default port, as used
    286  1.15.2.1  perseant  * in the 'forwarders' option.  E.g., "{ 10.0.0.1; 1::2 port 69; }"
    287       1.1  christos  */
    288       1.1  christos static cfg_tuplefielddef_t portiplist_fields[] = {
    289       1.1  christos 	{ "port", &cfg_type_optional_port, 0 },
    290  1.15.2.1  perseant 	{ "tls", &cfg_type_optional_tls, 0 },
    291  1.15.2.1  perseant 	{ "addresses", &cfg_type_bracketed_sockaddrtlslist, 0 },
    292       1.1  christos 	{ NULL, NULL, 0 }
    293       1.1  christos };
    294       1.8  christos static cfg_type_t cfg_type_portiplist = { "portiplist",	   cfg_parse_tuple,
    295       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
    296       1.8  christos 					  &cfg_rep_tuple,  portiplist_fields };
    297       1.1  christos 
    298       1.1  christos /*%
    299       1.1  christos  * A list of RR types, used in grant statements.
    300       1.1  christos  * Note that the old parser allows quotes around the RR type names.
    301       1.1  christos  */
    302       1.1  christos static cfg_type_t cfg_type_rrtypelist = {
    303       1.8  christos 	"rrtypelist",	  cfg_parse_spacelist, cfg_print_spacelist,
    304       1.8  christos 	cfg_doc_terminal, &cfg_rep_list,       &cfg_type_astring
    305       1.1  christos };
    306       1.1  christos 
    307       1.1  christos static const char *mode_enums[] = { "deny", "grant", NULL };
    308       1.1  christos static cfg_type_t cfg_type_mode = {
    309       1.8  christos 	"mode",	      cfg_parse_enum,  cfg_print_ustring,
    310       1.8  christos 	cfg_doc_enum, &cfg_rep_string, &mode_enums
    311       1.1  christos };
    312       1.1  christos 
    313       1.1  christos static isc_result_t
    314       1.1  christos parse_matchtype(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
    315       1.1  christos 	isc_result_t result;
    316       1.1  christos 
    317       1.1  christos 	CHECK(cfg_peektoken(pctx, 0));
    318       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
    319       1.8  christos 	    strcasecmp(TOKEN_STRING(pctx), "zonesub") == 0)
    320       1.8  christos 	{
    321       1.1  christos 		pctx->flags |= CFG_PCTX_SKIP;
    322       1.1  christos 	}
    323  1.15.2.1  perseant 	return cfg_parse_enum(pctx, type, ret);
    324       1.1  christos 
    325       1.8  christos cleanup:
    326  1.15.2.1  perseant 	return result;
    327       1.1  christos }
    328       1.1  christos 
    329       1.1  christos static isc_result_t
    330       1.1  christos parse_matchname(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
    331       1.1  christos 	isc_result_t result;
    332       1.1  christos 	cfg_obj_t *obj = NULL;
    333       1.1  christos 
    334       1.1  christos 	if ((pctx->flags & CFG_PCTX_SKIP) != 0) {
    335       1.1  christos 		pctx->flags &= ~CFG_PCTX_SKIP;
    336       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj));
    337       1.8  christos 	} else {
    338       1.1  christos 		result = cfg_parse_astring(pctx, type, &obj);
    339       1.8  christos 	}
    340       1.1  christos 
    341       1.1  christos 	*ret = obj;
    342       1.8  christos cleanup:
    343  1.15.2.1  perseant 	return result;
    344       1.1  christos }
    345       1.1  christos 
    346       1.1  christos static void
    347       1.1  christos doc_matchname(cfg_printer_t *pctx, const cfg_type_t *type) {
    348       1.1  christos 	cfg_print_cstr(pctx, "[ ");
    349       1.1  christos 	cfg_doc_obj(pctx, type->of);
    350       1.1  christos 	cfg_print_cstr(pctx, " ]");
    351       1.1  christos }
    352       1.1  christos 
    353       1.8  christos static const char *matchtype_enums[] = { "6to4-self",
    354       1.8  christos 					 "external",
    355       1.8  christos 					 "krb5-self",
    356       1.8  christos 					 "krb5-selfsub",
    357       1.8  christos 					 "krb5-subdomain",
    358      1.15  christos 					 "krb5-subdomain-self-rhs",
    359       1.8  christos 					 "ms-self",
    360       1.8  christos 					 "ms-selfsub",
    361       1.8  christos 					 "ms-subdomain",
    362      1.15  christos 					 "ms-subdomain-self-rhs",
    363       1.8  christos 					 "name",
    364       1.8  christos 					 "self",
    365       1.8  christos 					 "selfsub",
    366       1.8  christos 					 "selfwild",
    367       1.8  christos 					 "subdomain",
    368       1.8  christos 					 "tcp-self",
    369       1.8  christos 					 "wildcard",
    370       1.8  christos 					 "zonesub",
    371       1.8  christos 					 NULL };
    372       1.8  christos 
    373       1.8  christos static cfg_type_t cfg_type_matchtype = { "matchtype",	    parse_matchtype,
    374       1.8  christos 					 cfg_print_ustring, cfg_doc_enum,
    375       1.8  christos 					 &cfg_rep_string,   &matchtype_enums };
    376       1.1  christos 
    377       1.1  christos static cfg_type_t cfg_type_matchname = {
    378       1.1  christos 	"optional_matchname", parse_matchname, cfg_print_ustring,
    379       1.8  christos 	doc_matchname,	      &cfg_rep_tuple,  &cfg_type_ustring
    380       1.1  christos };
    381       1.1  christos 
    382       1.1  christos /*%
    383       1.1  christos  * A grant statement, used in the update policy.
    384       1.1  christos  */
    385       1.1  christos static cfg_tuplefielddef_t grant_fields[] = {
    386       1.1  christos 	{ "mode", &cfg_type_mode, 0 },
    387       1.1  christos 	{ "identity", &cfg_type_astring, 0 }, /* domain name */
    388       1.1  christos 	{ "matchtype", &cfg_type_matchtype, 0 },
    389       1.1  christos 	{ "name", &cfg_type_matchname, 0 }, /* domain name */
    390       1.1  christos 	{ "types", &cfg_type_rrtypelist, 0 },
    391       1.1  christos 	{ NULL, NULL, 0 }
    392       1.1  christos };
    393       1.8  christos static cfg_type_t cfg_type_grant = { "grant",	      cfg_parse_tuple,
    394       1.8  christos 				     cfg_print_tuple, cfg_doc_tuple,
    395       1.8  christos 				     &cfg_rep_tuple,  grant_fields };
    396       1.1  christos 
    397       1.1  christos static cfg_type_t cfg_type_updatepolicy = {
    398       1.8  christos 	"update_policy",  parse_updatepolicy, print_updatepolicy,
    399       1.8  christos 	doc_updatepolicy, &cfg_rep_list,      &cfg_type_grant
    400       1.1  christos };
    401       1.1  christos 
    402       1.1  christos static isc_result_t
    403       1.1  christos parse_updatepolicy(cfg_parser_t *pctx, const cfg_type_t *type,
    404       1.8  christos 		   cfg_obj_t **ret) {
    405       1.1  christos 	isc_result_t result;
    406       1.1  christos 	CHECK(cfg_gettoken(pctx, 0));
    407       1.1  christos 	if (pctx->token.type == isc_tokentype_special &&
    408       1.8  christos 	    pctx->token.value.as_char == '{')
    409       1.8  christos 	{
    410       1.1  christos 		cfg_ungettoken(pctx);
    411  1.15.2.1  perseant 		return cfg_parse_bracketed_list(pctx, type, ret);
    412       1.1  christos 	}
    413       1.1  christos 
    414       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
    415       1.8  christos 	    strcasecmp(TOKEN_STRING(pctx), "local") == 0)
    416       1.8  christos 	{
    417       1.1  christos 		cfg_obj_t *obj = NULL;
    418       1.1  christos 		CHECK(cfg_create_obj(pctx, &cfg_type_ustring, &obj));
    419       1.1  christos 		obj->value.string.length = strlen("local");
    420       1.8  christos 		obj->value.string.base =
    421       1.8  christos 			isc_mem_get(pctx->mctx, obj->value.string.length + 1);
    422       1.1  christos 		memmove(obj->value.string.base, "local", 5);
    423       1.1  christos 		obj->value.string.base[5] = '\0';
    424       1.1  christos 		*ret = obj;
    425  1.15.2.1  perseant 		return ISC_R_SUCCESS;
    426       1.1  christos 	}
    427       1.1  christos 
    428       1.1  christos 	cfg_ungettoken(pctx);
    429  1.15.2.1  perseant 	return ISC_R_UNEXPECTEDTOKEN;
    430       1.1  christos 
    431       1.8  christos cleanup:
    432  1.15.2.1  perseant 	return result;
    433       1.1  christos }
    434       1.1  christos 
    435       1.1  christos static void
    436       1.1  christos print_updatepolicy(cfg_printer_t *pctx, const cfg_obj_t *obj) {
    437       1.8  christos 	if (cfg_obj_isstring(obj)) {
    438       1.1  christos 		cfg_print_ustring(pctx, obj);
    439       1.8  christos 	} else {
    440       1.1  christos 		cfg_print_bracketed_list(pctx, obj);
    441       1.8  christos 	}
    442       1.1  christos }
    443       1.1  christos 
    444       1.1  christos static void
    445       1.1  christos doc_updatepolicy(cfg_printer_t *pctx, const cfg_type_t *type) {
    446       1.1  christos 	cfg_print_cstr(pctx, "( local | { ");
    447       1.1  christos 	cfg_doc_obj(pctx, type->of);
    448      1.14  christos 	cfg_print_cstr(pctx, "; ... } )");
    449       1.1  christos }
    450       1.1  christos 
    451       1.1  christos /*%
    452       1.1  christos  * A view statement.
    453       1.1  christos  */
    454       1.1  christos static cfg_tuplefielddef_t view_fields[] = {
    455       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    456       1.1  christos 	{ "class", &cfg_type_optional_class, 0 },
    457       1.1  christos 	{ "options", &cfg_type_viewopts, 0 },
    458       1.1  christos 	{ NULL, NULL, 0 }
    459       1.1  christos };
    460       1.8  christos static cfg_type_t cfg_type_view = { "view",	     cfg_parse_tuple,
    461       1.8  christos 				    cfg_print_tuple, cfg_doc_tuple,
    462       1.8  christos 				    &cfg_rep_tuple,  view_fields };
    463       1.1  christos 
    464       1.1  christos /*%
    465       1.1  christos  * A zone statement.
    466       1.1  christos  */
    467       1.1  christos static cfg_tuplefielddef_t zone_fields[] = {
    468       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    469       1.1  christos 	{ "class", &cfg_type_optional_class, 0 },
    470       1.1  christos 	{ "options", &cfg_type_zoneopts, 0 },
    471       1.1  christos 	{ NULL, NULL, 0 }
    472       1.1  christos };
    473       1.8  christos static cfg_type_t cfg_type_zone = { "zone",	     cfg_parse_tuple,
    474       1.8  christos 				    cfg_print_tuple, cfg_doc_tuple,
    475       1.8  christos 				    &cfg_rep_tuple,  zone_fields };
    476       1.8  christos 
    477       1.8  christos /*%
    478       1.8  christos  * A dnssec-policy statement.
    479       1.8  christos  */
    480       1.8  christos static cfg_tuplefielddef_t dnssecpolicy_fields[] = {
    481       1.8  christos 	{ "name", &cfg_type_astring, 0 },
    482       1.8  christos 	{ "options", &cfg_type_dnssecpolicyopts, 0 },
    483       1.8  christos 	{ NULL, NULL, 0 }
    484       1.8  christos };
    485       1.8  christos static cfg_type_t cfg_type_dnssecpolicy = {
    486       1.8  christos 	"dnssec-policy", cfg_parse_tuple, cfg_print_tuple,
    487       1.8  christos 	cfg_doc_tuple,	 &cfg_rep_tuple,  dnssecpolicy_fields
    488       1.1  christos };
    489       1.1  christos 
    490       1.1  christos /*%
    491       1.1  christos  * A "category" clause in the "logging" statement.
    492       1.1  christos  */
    493       1.1  christos static cfg_tuplefielddef_t category_fields[] = {
    494       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    495       1.8  christos 	{ "destinations", &cfg_type_destinationlist, 0 },
    496       1.1  christos 	{ NULL, NULL, 0 }
    497       1.1  christos };
    498       1.8  christos static cfg_type_t cfg_type_category = { "category",	 cfg_parse_tuple,
    499       1.8  christos 					cfg_print_tuple, cfg_doc_tuple,
    500       1.8  christos 					&cfg_rep_tuple,	 category_fields };
    501       1.8  christos 
    502       1.8  christos static isc_result_t
    503       1.8  christos parse_maxduration(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
    504  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_duration, ret);
    505       1.8  christos }
    506       1.8  christos 
    507       1.8  christos static void
    508       1.8  christos doc_maxduration(cfg_printer_t *pctx, const cfg_type_t *type) {
    509       1.8  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_duration);
    510       1.8  christos }
    511       1.8  christos 
    512       1.8  christos /*%
    513       1.8  christos  * A duration or "unlimited", but not "default".
    514       1.8  christos  */
    515       1.8  christos static const char *maxduration_enums[] = { "unlimited", NULL };
    516       1.8  christos static cfg_type_t cfg_type_maxduration = {
    517       1.8  christos 	"maxduration_no_default", parse_maxduration, cfg_print_ustring,
    518       1.8  christos 	doc_maxduration,	  &cfg_rep_duration, maxduration_enums
    519       1.1  christos };
    520       1.1  christos 
    521       1.1  christos /*%
    522       1.1  christos  * A dnssec key, as used in the "trusted-keys" statement.
    523       1.1  christos  */
    524       1.1  christos static cfg_tuplefielddef_t dnsseckey_fields[] = {
    525       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    526       1.8  christos 	{ "anchortype", &cfg_type_void, 0 },
    527       1.8  christos 	{ "rdata1", &cfg_type_uint32, 0 },
    528       1.8  christos 	{ "rdata2", &cfg_type_uint32, 0 },
    529       1.8  christos 	{ "rdata3", &cfg_type_uint32, 0 },
    530       1.8  christos 	{ "data", &cfg_type_qstring, 0 },
    531       1.1  christos 	{ NULL, NULL, 0 }
    532       1.1  christos };
    533       1.8  christos static cfg_type_t cfg_type_dnsseckey = { "dnsseckey",	  cfg_parse_tuple,
    534       1.8  christos 					 cfg_print_tuple, cfg_doc_tuple,
    535       1.8  christos 					 &cfg_rep_tuple,  dnsseckey_fields };
    536       1.8  christos 
    537       1.8  christos /*%
    538       1.8  christos  * Optional enums.
    539       1.8  christos  *
    540       1.8  christos  */
    541       1.8  christos static isc_result_t
    542       1.8  christos parse_optional_enum(cfg_parser_t *pctx, const cfg_type_t *type,
    543       1.8  christos 		    cfg_obj_t **ret) {
    544  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_void, ret);
    545       1.8  christos }
    546       1.8  christos 
    547       1.8  christos static void
    548       1.8  christos doc_optional_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
    549       1.8  christos 	UNUSED(type);
    550       1.8  christos 	cfg_print_cstr(pctx, "[ ");
    551       1.8  christos 	cfg_doc_enum(pctx, type);
    552       1.8  christos 	cfg_print_cstr(pctx, " ]");
    553       1.8  christos }
    554       1.1  christos 
    555       1.1  christos /*%
    556       1.8  christos  * A key initialization specifier, as used in the
    557       1.8  christos  * "trust-anchors" (or synonymous "managed-keys") statement.
    558       1.1  christos  */
    559       1.8  christos static const char *anchortype_enums[] = { "static-key", "initial-key",
    560       1.8  christos 					  "static-ds", "initial-ds", NULL };
    561       1.8  christos static cfg_type_t cfg_type_anchortype = { "anchortype",	     cfg_parse_enum,
    562       1.8  christos 					  cfg_print_ustring, cfg_doc_enum,
    563       1.8  christos 					  &cfg_rep_string,   anchortype_enums };
    564       1.1  christos static cfg_tuplefielddef_t managedkey_fields[] = {
    565       1.1  christos 	{ "name", &cfg_type_astring, 0 },
    566       1.8  christos 	{ "anchortype", &cfg_type_anchortype, 0 },
    567       1.8  christos 	{ "rdata1", &cfg_type_uint32, 0 },
    568       1.8  christos 	{ "rdata2", &cfg_type_uint32, 0 },
    569       1.8  christos 	{ "rdata3", &cfg_type_uint32, 0 },
    570       1.8  christos 	{ "data", &cfg_type_qstring, 0 },
    571       1.1  christos 	{ NULL, NULL, 0 }
    572       1.1  christos };
    573       1.8  christos static cfg_type_t cfg_type_managedkey = { "managedkey",	   cfg_parse_tuple,
    574       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
    575       1.8  christos 					  &cfg_rep_tuple,  managedkey_fields };
    576       1.8  christos 
    577       1.8  christos /*%
    578       1.8  christos  * DNSSEC key roles.
    579       1.8  christos  */
    580       1.8  christos static const char *dnsseckeyrole_enums[] = { "csk", "ksk", "zsk", NULL };
    581       1.8  christos static cfg_type_t cfg_type_dnsseckeyrole = {
    582       1.8  christos 	"dnssec-key-role", cfg_parse_enum,  cfg_print_ustring,
    583       1.8  christos 	cfg_doc_enum,	   &cfg_rep_string, &dnsseckeyrole_enums
    584       1.8  christos };
    585       1.8  christos 
    586       1.8  christos /*%
    587       1.8  christos  * DNSSEC key storage types.
    588       1.8  christos  */
    589  1.15.2.1  perseant static keyword_type_t keystore_kw = { "key-store", &cfg_type_astring };
    590  1.15.2.1  perseant static cfg_type_t cfg_type_keystorage = { "keystorage",	   parse_keyvalue,
    591  1.15.2.1  perseant 					  print_keyvalue,  doc_keyvalue,
    592  1.15.2.1  perseant 					  &cfg_rep_string, &keystore_kw };
    593  1.15.2.1  perseant 
    594  1.15.2.1  perseant static isc_result_t
    595  1.15.2.1  perseant parse_keystore(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
    596  1.15.2.1  perseant 	isc_result_t result;
    597  1.15.2.1  perseant 	cfg_obj_t *obj = NULL;
    598  1.15.2.1  perseant 
    599  1.15.2.1  perseant 	UNUSED(type);
    600  1.15.2.1  perseant 
    601  1.15.2.1  perseant 	CHECK(cfg_peektoken(pctx, 0));
    602  1.15.2.1  perseant 	if (pctx->token.type == isc_tokentype_string &&
    603  1.15.2.1  perseant 	    strcasecmp(TOKEN_STRING(pctx), "key-directory") == 0)
    604  1.15.2.1  perseant 	{
    605  1.15.2.1  perseant 		CHECK(cfg_parse_obj(pctx, &cfg_type_ustring, &obj));
    606  1.15.2.1  perseant 	} else if (pctx->token.type == isc_tokentype_string &&
    607  1.15.2.1  perseant 		   strcasecmp(TOKEN_STRING(pctx), "key-store") == 0)
    608  1.15.2.1  perseant 	{
    609  1.15.2.1  perseant 		CHECK(cfg_parse_obj(pctx, &cfg_type_keystorage, &obj));
    610  1.15.2.1  perseant 	} else {
    611  1.15.2.1  perseant 		CHECK(cfg_parse_void(pctx, NULL, &obj));
    612  1.15.2.1  perseant 	}
    613  1.15.2.1  perseant 
    614  1.15.2.1  perseant 	*ret = obj;
    615  1.15.2.1  perseant cleanup:
    616  1.15.2.1  perseant 	return result;
    617  1.15.2.1  perseant }
    618  1.15.2.1  perseant 
    619  1.15.2.1  perseant static void
    620  1.15.2.1  perseant doc_keystore(cfg_printer_t *pctx, const cfg_type_t *type) {
    621  1.15.2.1  perseant 	UNUSED(type);
    622  1.15.2.1  perseant 
    623  1.15.2.1  perseant 	cfg_print_cstr(pctx, "[ key-directory | key-store <string> ]");
    624  1.15.2.1  perseant }
    625  1.15.2.1  perseant 
    626  1.15.2.1  perseant static void
    627  1.15.2.1  perseant print_keystore(cfg_printer_t *pctx, const cfg_obj_t *obj) {
    628  1.15.2.1  perseant 	REQUIRE(pctx != NULL);
    629  1.15.2.1  perseant 	REQUIRE(obj != NULL);
    630  1.15.2.1  perseant 	REQUIRE(obj->type->rep == &cfg_rep_string);
    631  1.15.2.1  perseant 
    632  1.15.2.1  perseant 	if (strcasecmp(cfg_obj_asstring(obj), "key-directory") != 0) {
    633  1.15.2.1  perseant 		cfg_print_cstr(pctx, "key-store ");
    634  1.15.2.1  perseant 	}
    635  1.15.2.1  perseant 	cfg_print_ustring(pctx, obj);
    636  1.15.2.1  perseant }
    637  1.15.2.1  perseant 
    638  1.15.2.1  perseant static cfg_type_t cfg_type_optional_keystore = {
    639  1.15.2.1  perseant 	"optionalkeystorage", parse_keystore,  print_keystore,
    640  1.15.2.1  perseant 	doc_keystore,	      &cfg_rep_string, &keystore_kw
    641       1.8  christos };
    642       1.8  christos 
    643       1.8  christos /*%
    644       1.8  christos  * A dnssec key, as used in the "keys" statement in a "dnssec-policy".
    645       1.8  christos  */
    646       1.8  christos static keyword_type_t algorithm_kw = { "algorithm", &cfg_type_ustring };
    647       1.8  christos static cfg_type_t cfg_type_algorithm = { "algorithm",	  parse_keyvalue,
    648       1.8  christos 					 print_keyvalue,  doc_keyvalue,
    649       1.8  christos 					 &cfg_rep_string, &algorithm_kw };
    650       1.8  christos 
    651       1.8  christos static keyword_type_t lifetime_kw = { "lifetime",
    652       1.8  christos 				      &cfg_type_duration_or_unlimited };
    653       1.8  christos static cfg_type_t cfg_type_lifetime = { "lifetime",	   parse_keyvalue,
    654       1.8  christos 					print_keyvalue,	   doc_keyvalue,
    655       1.8  christos 					&cfg_rep_duration, &lifetime_kw };
    656  1.15.2.1  perseant /*
    657  1.15.2.1  perseant  *
    658  1.15.2.1  perseant  */
    659  1.15.2.1  perseant static void
    660  1.15.2.1  perseant print_tagrange(cfg_printer_t *pctx, const cfg_obj_t *obj) {
    661  1.15.2.1  perseant 	REQUIRE(pctx != NULL);
    662  1.15.2.1  perseant 	REQUIRE(obj != NULL);
    663  1.15.2.1  perseant 	REQUIRE(obj->type->rep == &cfg_rep_tuple);
    664  1.15.2.1  perseant 
    665  1.15.2.1  perseant 	if (cfg_obj_istuple(obj)) {
    666  1.15.2.1  perseant 		cfg_print_cstr(pctx, "tag-range ");
    667  1.15.2.1  perseant 		cfg_print_tuple(pctx, obj);
    668  1.15.2.1  perseant 	}
    669  1.15.2.1  perseant }
    670  1.15.2.1  perseant 
    671  1.15.2.1  perseant static cfg_tuplefielddef_t tagrange_fields[] = {
    672  1.15.2.1  perseant 	{ "tag-min", &cfg_type_uint32, 0 },
    673  1.15.2.1  perseant 	{ "tag-max", &cfg_type_uint32, 0 },
    674  1.15.2.1  perseant 	{ NULL, NULL, 0 }
    675  1.15.2.1  perseant };
    676  1.15.2.1  perseant 
    677  1.15.2.1  perseant static cfg_type_t cfg_type_tagrange = { "tagrange",	cfg_parse_tuple,
    678  1.15.2.1  perseant 					print_tagrange, cfg_doc_tuple,
    679  1.15.2.1  perseant 					&cfg_rep_tuple, tagrange_fields };
    680  1.15.2.1  perseant 
    681  1.15.2.1  perseant static keyword_type_t tagrange_kw = { "tag-range", &cfg_type_tagrange };
    682  1.15.2.1  perseant static void
    683  1.15.2.1  perseant doc_optionaltagrange(cfg_printer_t *pctx, const cfg_type_t *type) {
    684  1.15.2.1  perseant 	UNUSED(type);
    685  1.15.2.1  perseant 
    686  1.15.2.1  perseant 	cfg_print_cstr(pctx, "[ tag-range <integer> <integer> ]");
    687  1.15.2.1  perseant }
    688  1.15.2.1  perseant 
    689  1.15.2.1  perseant static isc_result_t
    690  1.15.2.1  perseant parse_optionaltagrange(cfg_parser_t *pctx, const cfg_type_t *type,
    691  1.15.2.1  perseant 		       cfg_obj_t **ret) {
    692  1.15.2.1  perseant 	isc_result_t result;
    693  1.15.2.1  perseant 	cfg_obj_t *obj = NULL;
    694  1.15.2.1  perseant 
    695  1.15.2.1  perseant 	UNUSED(type);
    696  1.15.2.1  perseant 
    697  1.15.2.1  perseant 	CHECK(cfg_peektoken(pctx, 0));
    698  1.15.2.1  perseant 	if (pctx->token.type == isc_tokentype_string &&
    699  1.15.2.1  perseant 	    strcasecmp(TOKEN_STRING(pctx), "tag-range") == 0)
    700  1.15.2.1  perseant 	{
    701  1.15.2.1  perseant 		CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
    702  1.15.2.1  perseant 		CHECK(cfg_parse_obj(pctx, &cfg_type_tagrange, &obj));
    703  1.15.2.1  perseant 	} else {
    704  1.15.2.1  perseant 		CHECK(cfg_parse_void(pctx, NULL, &obj));
    705  1.15.2.1  perseant 	}
    706  1.15.2.1  perseant 
    707  1.15.2.1  perseant 	*ret = obj;
    708  1.15.2.1  perseant cleanup:
    709  1.15.2.1  perseant 	return result;
    710  1.15.2.1  perseant }
    711  1.15.2.1  perseant 
    712  1.15.2.1  perseant static cfg_type_t cfg_type_optional_tagrange = {
    713  1.15.2.1  perseant 	"optionaltagrange",   parse_optionaltagrange, NULL,
    714  1.15.2.1  perseant 	doc_optionaltagrange, &cfg_rep_tuple,	      &tagrange_kw
    715  1.15.2.1  perseant };
    716       1.8  christos 
    717       1.8  christos static cfg_tuplefielddef_t kaspkey_fields[] = {
    718       1.8  christos 	{ "role", &cfg_type_dnsseckeyrole, 0 },
    719  1.15.2.1  perseant 	{ "keystorage", &cfg_type_optional_keystore, 0 },
    720       1.8  christos 	{ "lifetime", &cfg_type_lifetime, 0 },
    721       1.8  christos 	{ "algorithm", &cfg_type_algorithm, 0 },
    722  1.15.2.1  perseant 	{ "tag-range", &cfg_type_optional_tagrange, 0 },
    723       1.8  christos 	{ "length", &cfg_type_optional_uint32, 0 },
    724       1.8  christos 	{ NULL, NULL, 0 }
    725       1.1  christos };
    726       1.8  christos static cfg_type_t cfg_type_kaspkey = { "kaspkey",	cfg_parse_tuple,
    727       1.8  christos 				       cfg_print_tuple, cfg_doc_tuple,
    728       1.8  christos 				       &cfg_rep_tuple,	kaspkey_fields };
    729       1.1  christos 
    730       1.8  christos /*%
    731       1.9  christos  * NSEC3 parameters.
    732       1.9  christos  */
    733       1.9  christos static keyword_type_t nsec3iter_kw = { "iterations", &cfg_type_uint32 };
    734       1.9  christos static cfg_type_t cfg_type_nsec3iter = {
    735       1.9  christos 	"iterations",	       parse_optional_keyvalue, print_keyvalue,
    736       1.9  christos 	doc_optional_keyvalue, &cfg_rep_uint32,		&nsec3iter_kw
    737       1.9  christos };
    738       1.9  christos 
    739       1.9  christos static keyword_type_t nsec3optout_kw = { "optout", &cfg_type_boolean };
    740       1.9  christos static cfg_type_t cfg_type_nsec3optout = {
    741       1.9  christos 	"optout",	  parse_optional_keyvalue,
    742       1.9  christos 	print_keyvalue,	  doc_optional_keyvalue,
    743       1.9  christos 	&cfg_rep_boolean, &nsec3optout_kw
    744       1.9  christos };
    745       1.9  christos 
    746       1.9  christos static keyword_type_t nsec3salt_kw = { "salt-length", &cfg_type_uint32 };
    747       1.9  christos static cfg_type_t cfg_type_nsec3salt = {
    748       1.9  christos 	"salt-length",	       parse_optional_keyvalue, print_keyvalue,
    749       1.9  christos 	doc_optional_keyvalue, &cfg_rep_uint32,		&nsec3salt_kw
    750       1.9  christos };
    751       1.9  christos 
    752       1.9  christos static cfg_tuplefielddef_t nsec3param_fields[] = {
    753       1.9  christos 	{ "iterations", &cfg_type_nsec3iter, 0 },
    754       1.9  christos 	{ "optout", &cfg_type_nsec3optout, 0 },
    755       1.9  christos 	{ "salt-length", &cfg_type_nsec3salt, 0 },
    756       1.9  christos 	{ NULL, NULL, 0 }
    757       1.9  christos };
    758       1.9  christos 
    759       1.9  christos static cfg_type_t cfg_type_nsec3 = { "nsec3param",    cfg_parse_tuple,
    760       1.9  christos 				     cfg_print_tuple, cfg_doc_tuple,
    761       1.9  christos 				     &cfg_rep_tuple,  nsec3param_fields };
    762       1.9  christos 
    763       1.9  christos /*%
    764       1.8  christos  * Wild class, type, name.
    765       1.8  christos  */
    766       1.1  christos static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
    767       1.1  christos 
    768       1.1  christos static cfg_type_t cfg_type_optional_wild_class = {
    769       1.1  christos 	"optional_wild_class", parse_optional_keyvalue, print_keyvalue,
    770       1.8  christos 	doc_optional_keyvalue, &cfg_rep_string,		&wild_class_kw
    771       1.1  christos };
    772       1.1  christos 
    773       1.1  christos static keyword_type_t wild_type_kw = { "type", &cfg_type_ustring };
    774       1.1  christos 
    775       1.1  christos static cfg_type_t cfg_type_optional_wild_type = {
    776       1.8  christos 	"optional_wild_type",  parse_optional_keyvalue, print_keyvalue,
    777       1.8  christos 	doc_optional_keyvalue, &cfg_rep_string,		&wild_type_kw
    778       1.1  christos };
    779       1.1  christos 
    780       1.1  christos static keyword_type_t wild_name_kw = { "name", &cfg_type_qstring };
    781       1.1  christos 
    782       1.1  christos static cfg_type_t cfg_type_optional_wild_name = {
    783       1.8  christos 	"optional_wild_name",  parse_optional_keyvalue, print_keyvalue,
    784       1.8  christos 	doc_optional_keyvalue, &cfg_rep_string,		&wild_name_kw
    785       1.1  christos };
    786       1.1  christos 
    787       1.1  christos /*%
    788       1.1  christos  * An rrset ordering element.
    789       1.1  christos  */
    790       1.1  christos static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
    791       1.1  christos 	{ "class", &cfg_type_optional_wild_class, 0 },
    792       1.1  christos 	{ "type", &cfg_type_optional_wild_type, 0 },
    793       1.1  christos 	{ "name", &cfg_type_optional_wild_name, 0 },
    794       1.1  christos 	{ "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
    795       1.1  christos 	{ "ordering", &cfg_type_ustring, 0 },
    796       1.1  christos 	{ NULL, NULL, 0 }
    797       1.1  christos };
    798       1.1  christos static cfg_type_t cfg_type_rrsetorderingelement = {
    799       1.1  christos 	"rrsetorderingelement", cfg_parse_tuple, cfg_print_tuple,
    800       1.8  christos 	cfg_doc_tuple,		&cfg_rep_tuple,	 rrsetorderingelement_fields
    801       1.1  christos };
    802       1.1  christos 
    803       1.1  christos /*%
    804       1.1  christos  * A global or view "check-names" option.  Note that the zone
    805       1.1  christos  * "check-names" option has a different syntax.
    806       1.1  christos  */
    807       1.1  christos 
    808       1.8  christos static const char *checktype_enums[] = { "primary", "master",	"secondary",
    809       1.8  christos 					 "slave",   "response", NULL };
    810       1.8  christos static cfg_type_t cfg_type_checktype = { "checktype",	    cfg_parse_enum,
    811       1.8  christos 					 cfg_print_ustring, cfg_doc_enum,
    812       1.8  christos 					 &cfg_rep_string,   &checktype_enums };
    813       1.1  christos 
    814       1.1  christos static const char *checkmode_enums[] = { "fail", "warn", "ignore", NULL };
    815       1.8  christos static cfg_type_t cfg_type_checkmode = { "checkmode",	    cfg_parse_enum,
    816       1.8  christos 					 cfg_print_ustring, cfg_doc_enum,
    817       1.8  christos 					 &cfg_rep_string,   &checkmode_enums };
    818       1.1  christos 
    819       1.1  christos static const char *warn_enums[] = { "warn", "ignore", NULL };
    820       1.1  christos static cfg_type_t cfg_type_warn = {
    821       1.8  christos 	"warn",	      cfg_parse_enum,  cfg_print_ustring,
    822       1.8  christos 	cfg_doc_enum, &cfg_rep_string, &warn_enums
    823       1.1  christos };
    824       1.1  christos 
    825       1.1  christos static cfg_tuplefielddef_t checknames_fields[] = {
    826       1.1  christos 	{ "type", &cfg_type_checktype, 0 },
    827       1.1  christos 	{ "mode", &cfg_type_checkmode, 0 },
    828       1.1  christos 	{ NULL, NULL, 0 }
    829       1.1  christos };
    830       1.1  christos 
    831       1.8  christos static cfg_type_t cfg_type_checknames = { "checknames",	   cfg_parse_tuple,
    832       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
    833       1.8  christos 					  &cfg_rep_tuple,  checknames_fields };
    834       1.1  christos 
    835       1.8  christos static cfg_type_t cfg_type_bracketed_netaddrlist = { "bracketed_netaddrlist",
    836       1.8  christos 						     cfg_parse_bracketed_list,
    837       1.8  christos 						     cfg_print_bracketed_list,
    838       1.8  christos 						     cfg_doc_bracketed_list,
    839       1.8  christos 						     &cfg_rep_list,
    840       1.8  christos 						     &cfg_type_netaddr };
    841       1.1  christos 
    842  1.15.2.1  perseant static cfg_type_t cfg_type_bracketed_sockaddrtlslist = {
    843  1.15.2.1  perseant 	"bracketed_sockaddrtlslist",
    844  1.15.2.1  perseant 	cfg_parse_bracketed_list,
    845  1.15.2.1  perseant 	cfg_print_bracketed_list,
    846  1.15.2.1  perseant 	cfg_doc_bracketed_list,
    847  1.15.2.1  perseant 	&cfg_rep_list,
    848  1.15.2.1  perseant 	&cfg_type_sockaddrtls
    849  1.15.2.1  perseant };
    850  1.15.2.1  perseant 
    851       1.8  christos static const char *autodnssec_enums[] = { "allow", "maintain", "off", NULL };
    852       1.1  christos static cfg_type_t cfg_type_autodnssec = {
    853       1.8  christos 	"autodnssec", cfg_parse_enum,  cfg_print_ustring,
    854       1.8  christos 	cfg_doc_enum, &cfg_rep_string, &autodnssec_enums
    855       1.1  christos };
    856       1.1  christos 
    857       1.8  christos static const char *dnssecupdatemode_enums[] = { "maintain", "no-resign", NULL };
    858       1.1  christos static cfg_type_t cfg_type_dnssecupdatemode = {
    859       1.8  christos 	"dnssecupdatemode", cfg_parse_enum,  cfg_print_ustring,
    860       1.8  christos 	cfg_doc_enum,	    &cfg_rep_string, &dnssecupdatemode_enums
    861       1.1  christos };
    862       1.1  christos 
    863       1.8  christos static const char *updatemethods_enums[] = { "date", "increment", "unixtime",
    864       1.8  christos 					     NULL };
    865       1.1  christos static cfg_type_t cfg_type_updatemethod = {
    866       1.8  christos 	"updatemethod", cfg_parse_enum,	 cfg_print_ustring,
    867       1.8  christos 	cfg_doc_enum,	&cfg_rep_string, &updatemethods_enums
    868       1.1  christos };
    869       1.1  christos 
    870       1.1  christos /*
    871       1.1  christos  * zone-statistics: full, terse, or none.
    872       1.1  christos  *
    873       1.1  christos  * for backward compatibility, we also support boolean values.
    874       1.1  christos  * yes represents "full", no represents "terse". in the future we
    875       1.1  christos  * may change no to mean "none".
    876       1.1  christos  */
    877       1.1  christos static const char *zonestat_enums[] = { "full", "terse", "none", NULL };
    878       1.1  christos static isc_result_t
    879       1.1  christos parse_zonestat(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
    880  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
    881       1.1  christos }
    882       1.1  christos static void
    883       1.1  christos doc_zonestat(cfg_printer_t *pctx, const cfg_type_t *type) {
    884       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
    885       1.1  christos }
    886       1.8  christos static cfg_type_t cfg_type_zonestat = { "zonestat",	   parse_zonestat,
    887       1.8  christos 					cfg_print_ustring, doc_zonestat,
    888       1.8  christos 					&cfg_rep_string,   zonestat_enums };
    889       1.8  christos 
    890       1.8  christos static cfg_type_t cfg_type_rrsetorder = { "rrsetorder",
    891       1.8  christos 					  cfg_parse_bracketed_list,
    892       1.8  christos 					  cfg_print_bracketed_list,
    893       1.8  christos 					  cfg_doc_bracketed_list,
    894       1.8  christos 					  &cfg_rep_list,
    895       1.8  christos 					  &cfg_type_rrsetorderingelement };
    896       1.1  christos 
    897       1.1  christos static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
    898       1.1  christos 
    899       1.1  christos static cfg_type_t cfg_type_optional_port = {
    900       1.8  christos 	"optional_port",       parse_optional_keyvalue, print_keyvalue,
    901       1.8  christos 	doc_optional_keyvalue, &cfg_rep_uint32,		&port_kw
    902       1.1  christos };
    903       1.1  christos 
    904       1.1  christos /*% A list of keys, as in the "key" clause of the controls statement. */
    905       1.8  christos static cfg_type_t cfg_type_keylist = { "keylist",
    906       1.8  christos 				       cfg_parse_bracketed_list,
    907       1.8  christos 				       cfg_print_bracketed_list,
    908       1.8  christos 				       cfg_doc_bracketed_list,
    909       1.8  christos 				       &cfg_rep_list,
    910       1.8  christos 				       &cfg_type_astring };
    911       1.8  christos 
    912       1.8  christos /*% A list of dnssec keys, as in "trusted-keys". Deprecated. */
    913       1.8  christos static cfg_type_t cfg_type_trustedkeys = { "trustedkeys",
    914       1.8  christos 					   cfg_parse_bracketed_list,
    915       1.8  christos 					   cfg_print_bracketed_list,
    916       1.8  christos 					   cfg_doc_bracketed_list,
    917       1.8  christos 					   &cfg_rep_list,
    918       1.8  christos 					   &cfg_type_dnsseckey };
    919       1.8  christos 
    920       1.8  christos /*%
    921       1.8  christos  * A list of managed trust anchors.  Each entry contains a name, a keyword
    922       1.8  christos  * ("static-key", initial-key", "static-ds" or "initial-ds"), and the
    923       1.8  christos  * fields associated with either a DNSKEY or a DS record.
    924       1.8  christos  */
    925       1.8  christos static cfg_type_t cfg_type_dnsseckeys = { "dnsseckeys",
    926       1.8  christos 					  cfg_parse_bracketed_list,
    927       1.8  christos 					  cfg_print_bracketed_list,
    928       1.8  christos 					  cfg_doc_bracketed_list,
    929       1.8  christos 					  &cfg_rep_list,
    930       1.8  christos 					  &cfg_type_managedkey };
    931       1.8  christos 
    932       1.8  christos /*%
    933       1.8  christos  * A list of key entries, used in a DNSSEC Key and Signing Policy.
    934       1.8  christos  */
    935       1.8  christos static cfg_type_t cfg_type_kaspkeys = { "kaspkeys",
    936       1.8  christos 					cfg_parse_bracketed_list,
    937       1.8  christos 					cfg_print_bracketed_list,
    938       1.8  christos 					cfg_doc_bracketed_list,
    939       1.8  christos 					&cfg_rep_list,
    940       1.8  christos 					&cfg_type_kaspkey };
    941       1.1  christos 
    942       1.1  christos static const char *forwardtype_enums[] = { "first", "only", NULL };
    943       1.1  christos static cfg_type_t cfg_type_forwardtype = {
    944       1.8  christos 	"forwardtype", cfg_parse_enum,	cfg_print_ustring,
    945       1.8  christos 	cfg_doc_enum,  &cfg_rep_string, &forwardtype_enums
    946       1.1  christos };
    947       1.1  christos 
    948  1.15.2.1  perseant static const char *zonetype_enums[] = { "primary", "master",   "secondary",
    949  1.15.2.1  perseant 					"slave",   "mirror",   "forward",
    950  1.15.2.1  perseant 					"hint",	   "redirect", "static-stub",
    951  1.15.2.1  perseant 					"stub",	   NULL };
    952       1.8  christos static cfg_type_t cfg_type_zonetype = { "zonetype",	   cfg_parse_enum,
    953       1.8  christos 					cfg_print_ustring, cfg_doc_enum,
    954       1.8  christos 					&cfg_rep_string,   &zonetype_enums };
    955       1.8  christos 
    956       1.8  christos static const char *loglevel_enums[] = { "critical", "error", "warning",
    957       1.8  christos 					"notice",   "info",  "dynamic",
    958       1.8  christos 					NULL };
    959       1.8  christos static cfg_type_t cfg_type_loglevel = { "loglevel",	   cfg_parse_enum,
    960       1.8  christos 					cfg_print_ustring, cfg_doc_enum,
    961       1.8  christos 					&cfg_rep_string,   &loglevel_enums };
    962       1.1  christos 
    963       1.8  christos static const char *transferformat_enums[] = { "many-answers", "one-answer",
    964       1.8  christos 					      NULL };
    965       1.1  christos static cfg_type_t cfg_type_transferformat = {
    966       1.8  christos 	"transferformat", cfg_parse_enum,  cfg_print_ustring,
    967       1.8  christos 	cfg_doc_enum,	  &cfg_rep_string, &transferformat_enums
    968       1.1  christos };
    969       1.1  christos 
    970       1.1  christos /*%
    971       1.1  christos  * The special keyword "none", as used in the pid-file option.
    972       1.1  christos  */
    973       1.1  christos 
    974       1.1  christos static void
    975       1.1  christos print_none(cfg_printer_t *pctx, const cfg_obj_t *obj) {
    976       1.1  christos 	UNUSED(obj);
    977       1.1  christos 	cfg_print_cstr(pctx, "none");
    978       1.1  christos }
    979       1.1  christos 
    980       1.8  christos static cfg_type_t cfg_type_none = { "none", NULL,	   print_none,
    981       1.8  christos 				    NULL,   &cfg_rep_void, NULL };
    982       1.1  christos 
    983       1.1  christos /*%
    984       1.1  christos  * A quoted string or the special keyword "none".  Used in the pid-file option.
    985       1.1  christos  */
    986       1.1  christos static isc_result_t
    987       1.1  christos parse_qstringornone(cfg_parser_t *pctx, const cfg_type_t *type,
    988       1.8  christos 		    cfg_obj_t **ret) {
    989       1.1  christos 	isc_result_t result;
    990       1.1  christos 
    991       1.1  christos 	CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
    992       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
    993       1.1  christos 	    strcasecmp(TOKEN_STRING(pctx), "none") == 0)
    994       1.8  christos 	{
    995  1.15.2.1  perseant 		return cfg_create_obj(pctx, &cfg_type_none, ret);
    996       1.8  christos 	}
    997       1.1  christos 	cfg_ungettoken(pctx);
    998  1.15.2.1  perseant 	return cfg_parse_qstring(pctx, type, ret);
    999       1.8  christos cleanup:
   1000  1.15.2.1  perseant 	return result;
   1001       1.1  christos }
   1002       1.1  christos 
   1003       1.1  christos static void
   1004       1.1  christos doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) {
   1005       1.1  christos 	UNUSED(type);
   1006       1.1  christos 	cfg_print_cstr(pctx, "( <quoted_string> | none )");
   1007       1.1  christos }
   1008       1.1  christos 
   1009       1.8  christos static cfg_type_t cfg_type_qstringornone = { "qstringornone",
   1010       1.8  christos 					     parse_qstringornone,
   1011       1.8  christos 					     NULL,
   1012       1.8  christos 					     doc_qstringornone,
   1013       1.8  christos 					     NULL,
   1014       1.8  christos 					     NULL };
   1015       1.1  christos 
   1016       1.1  christos /*%
   1017       1.1  christos  * A boolean ("yes" or "no"), or the special keyword "auto".
   1018       1.1  christos  * Used in the dnssec-validation option.
   1019       1.1  christos  */
   1020       1.1  christos static void
   1021       1.1  christos print_auto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1022       1.1  christos 	UNUSED(obj);
   1023       1.1  christos 	cfg_print_cstr(pctx, "auto");
   1024       1.1  christos }
   1025       1.1  christos 
   1026       1.8  christos static cfg_type_t cfg_type_auto = { "auto", NULL,	   print_auto,
   1027       1.8  christos 				    NULL,   &cfg_rep_void, NULL };
   1028       1.1  christos 
   1029       1.1  christos static isc_result_t
   1030       1.1  christos parse_boolorauto(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   1031       1.1  christos 	isc_result_t result;
   1032       1.1  christos 
   1033       1.1  christos 	CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
   1034       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
   1035       1.1  christos 	    strcasecmp(TOKEN_STRING(pctx), "auto") == 0)
   1036       1.8  christos 	{
   1037  1.15.2.1  perseant 		return cfg_create_obj(pctx, &cfg_type_auto, ret);
   1038       1.8  christos 	}
   1039       1.1  christos 	cfg_ungettoken(pctx);
   1040  1.15.2.1  perseant 	return cfg_parse_boolean(pctx, type, ret);
   1041       1.8  christos cleanup:
   1042  1.15.2.1  perseant 	return result;
   1043       1.1  christos }
   1044       1.1  christos 
   1045       1.1  christos static void
   1046       1.1  christos print_boolorauto(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1047       1.8  christos 	if (obj->type->rep == &cfg_rep_void) {
   1048       1.1  christos 		cfg_print_cstr(pctx, "auto");
   1049       1.8  christos 	} else if (obj->value.boolean) {
   1050       1.1  christos 		cfg_print_cstr(pctx, "yes");
   1051       1.8  christos 	} else {
   1052       1.1  christos 		cfg_print_cstr(pctx, "no");
   1053       1.8  christos 	}
   1054       1.1  christos }
   1055       1.1  christos 
   1056       1.1  christos static void
   1057       1.1  christos doc_boolorauto(cfg_printer_t *pctx, const cfg_type_t *type) {
   1058       1.1  christos 	UNUSED(type);
   1059       1.1  christos 	cfg_print_cstr(pctx, "( yes | no | auto )");
   1060       1.1  christos }
   1061       1.1  christos 
   1062       1.1  christos static cfg_type_t cfg_type_boolorauto = {
   1063       1.8  christos 	"boolorauto", parse_boolorauto, print_boolorauto, doc_boolorauto, NULL,
   1064       1.8  christos 	NULL
   1065       1.1  christos };
   1066       1.1  christos 
   1067       1.1  christos /*%
   1068       1.1  christos  * keyword hostname
   1069       1.1  christos  */
   1070       1.1  christos static void
   1071       1.1  christos print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1072       1.1  christos 	UNUSED(obj);
   1073       1.1  christos 	cfg_print_cstr(pctx, "hostname");
   1074       1.1  christos }
   1075       1.1  christos 
   1076       1.8  christos static cfg_type_t cfg_type_hostname = { "hostname",	  NULL,
   1077       1.8  christos 					print_hostname,	  NULL,
   1078       1.8  christos 					&cfg_rep_boolean, NULL };
   1079       1.1  christos 
   1080       1.1  christos /*%
   1081       1.1  christos  * "server-id" argument.
   1082       1.1  christos  */
   1083       1.1  christos 
   1084       1.1  christos static isc_result_t
   1085       1.8  christos parse_serverid(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   1086       1.1  christos 	isc_result_t result;
   1087       1.1  christos 	CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
   1088       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
   1089       1.1  christos 	    strcasecmp(TOKEN_STRING(pctx), "none") == 0)
   1090       1.8  christos 	{
   1091  1.15.2.1  perseant 		return cfg_create_obj(pctx, &cfg_type_none, ret);
   1092       1.8  christos 	}
   1093       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
   1094       1.8  christos 	    strcasecmp(TOKEN_STRING(pctx), "hostname") == 0)
   1095       1.8  christos 	{
   1096       1.1  christos 		result = cfg_create_obj(pctx, &cfg_type_hostname, ret);
   1097       1.8  christos 		if (result == ISC_R_SUCCESS) {
   1098       1.3  christos 			(*ret)->value.boolean = true;
   1099       1.8  christos 		}
   1100  1.15.2.1  perseant 		return result;
   1101       1.1  christos 	}
   1102       1.1  christos 	cfg_ungettoken(pctx);
   1103  1.15.2.1  perseant 	return cfg_parse_qstring(pctx, type, ret);
   1104       1.8  christos cleanup:
   1105  1.15.2.1  perseant 	return result;
   1106       1.1  christos }
   1107       1.1  christos 
   1108       1.1  christos static void
   1109       1.1  christos doc_serverid(cfg_printer_t *pctx, const cfg_type_t *type) {
   1110       1.1  christos 	UNUSED(type);
   1111       1.1  christos 	cfg_print_cstr(pctx, "( <quoted_string> | none | hostname )");
   1112       1.1  christos }
   1113       1.1  christos 
   1114       1.8  christos static cfg_type_t cfg_type_serverid = { "serverid",   parse_serverid, NULL,
   1115       1.8  christos 					doc_serverid, NULL,	      NULL };
   1116       1.1  christos 
   1117       1.1  christos /*%
   1118       1.1  christos  * Port list.
   1119       1.1  christos  */
   1120       1.1  christos static void
   1121       1.1  christos print_porttuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1122       1.1  christos 	cfg_print_cstr(pctx, "range ");
   1123       1.1  christos 	cfg_print_tuple(pctx, obj);
   1124       1.1  christos }
   1125       1.1  christos static cfg_tuplefielddef_t porttuple_fields[] = {
   1126       1.1  christos 	{ "loport", &cfg_type_uint32, 0 },
   1127       1.1  christos 	{ "hiport", &cfg_type_uint32, 0 },
   1128       1.1  christos 	{ NULL, NULL, 0 }
   1129       1.1  christos };
   1130       1.8  christos static cfg_type_t cfg_type_porttuple = { "porttuple",	  cfg_parse_tuple,
   1131       1.8  christos 					 print_porttuple, cfg_doc_tuple,
   1132       1.8  christos 					 &cfg_rep_tuple,  porttuple_fields };
   1133       1.1  christos 
   1134       1.1  christos static isc_result_t
   1135       1.1  christos parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
   1136       1.1  christos 	isc_result_t result;
   1137       1.1  christos 
   1138       1.1  christos 	CHECK(cfg_parse_uint32(pctx, NULL, ret));
   1139       1.1  christos 	if ((*ret)->value.uint32 > 0xffff) {
   1140       1.1  christos 		cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid port");
   1141       1.1  christos 		cfg_obj_destroy(pctx, ret);
   1142       1.1  christos 		result = ISC_R_RANGE;
   1143       1.1  christos 	}
   1144       1.1  christos 
   1145       1.8  christos cleanup:
   1146  1.15.2.1  perseant 	return result;
   1147       1.1  christos }
   1148       1.1  christos 
   1149       1.1  christos static isc_result_t
   1150       1.1  christos parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   1151       1.1  christos 	isc_result_t result;
   1152       1.1  christos 	cfg_obj_t *obj = NULL;
   1153       1.1  christos 
   1154       1.1  christos 	UNUSED(type);
   1155       1.1  christos 
   1156       1.1  christos 	CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
   1157       1.8  christos 	if (pctx->token.type == isc_tokentype_number) {
   1158       1.1  christos 		CHECK(parse_port(pctx, ret));
   1159       1.8  christos 	} else {
   1160       1.1  christos 		CHECK(cfg_gettoken(pctx, 0));
   1161       1.1  christos 		if (pctx->token.type != isc_tokentype_string ||
   1162       1.8  christos 		    strcasecmp(TOKEN_STRING(pctx), "range") != 0)
   1163       1.8  christos 		{
   1164       1.1  christos 			cfg_parser_error(pctx, CFG_LOG_NEAR,
   1165       1.1  christos 					 "expected integer or 'range'");
   1166  1.15.2.1  perseant 			return ISC_R_UNEXPECTEDTOKEN;
   1167       1.1  christos 		}
   1168       1.1  christos 		CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
   1169       1.1  christos 		CHECK(parse_port(pctx, &obj->value.tuple[0]));
   1170       1.1  christos 		CHECK(parse_port(pctx, &obj->value.tuple[1]));
   1171       1.1  christos 		if (obj->value.tuple[0]->value.uint32 >
   1172      1.14  christos 		    obj->value.tuple[1]->value.uint32)
   1173      1.14  christos 		{
   1174       1.1  christos 			cfg_parser_error(pctx, CFG_LOG_NOPREP,
   1175       1.1  christos 					 "low port '%u' must not be larger "
   1176       1.1  christos 					 "than high port",
   1177       1.1  christos 					 obj->value.tuple[0]->value.uint32);
   1178       1.1  christos 			result = ISC_R_RANGE;
   1179       1.1  christos 			goto cleanup;
   1180       1.1  christos 		}
   1181       1.1  christos 		*ret = obj;
   1182       1.1  christos 		obj = NULL;
   1183       1.1  christos 	}
   1184       1.1  christos 
   1185       1.8  christos cleanup:
   1186       1.8  christos 	if (obj != NULL) {
   1187       1.1  christos 		cfg_obj_destroy(pctx, &obj);
   1188       1.8  christos 	}
   1189  1.15.2.1  perseant 	return result;
   1190       1.1  christos }
   1191       1.1  christos 
   1192       1.8  christos static cfg_type_t cfg_type_portrange = { "portrange", parse_portrange,
   1193       1.8  christos 					 NULL,	      cfg_doc_terminal,
   1194       1.8  christos 					 NULL,	      NULL };
   1195       1.8  christos 
   1196  1.15.2.1  perseant static cfg_type_t cfg_type_bracketed_portlist = { "bracketed_portlist",
   1197       1.8  christos 						  cfg_parse_bracketed_list,
   1198       1.8  christos 						  cfg_print_bracketed_list,
   1199       1.8  christos 						  cfg_doc_bracketed_list,
   1200       1.8  christos 						  &cfg_rep_list,
   1201       1.8  christos 						  &cfg_type_portrange };
   1202       1.8  christos 
   1203  1.15.2.1  perseant static const char *cookiealg_enums[] = { "siphash24", NULL };
   1204       1.8  christos static cfg_type_t cfg_type_cookiealg = { "cookiealg",	    cfg_parse_enum,
   1205       1.8  christos 					 cfg_print_ustring, cfg_doc_enum,
   1206       1.8  christos 					 &cfg_rep_string,   &cookiealg_enums };
   1207       1.1  christos 
   1208       1.1  christos /*%
   1209       1.1  christos  * fetch-quota-params
   1210       1.1  christos  */
   1211       1.1  christos 
   1212       1.1  christos static cfg_tuplefielddef_t fetchquota_fields[] = {
   1213       1.1  christos 	{ "frequency", &cfg_type_uint32, 0 },
   1214       1.1  christos 	{ "low", &cfg_type_fixedpoint, 0 },
   1215       1.1  christos 	{ "high", &cfg_type_fixedpoint, 0 },
   1216       1.1  christos 	{ "discount", &cfg_type_fixedpoint, 0 },
   1217       1.1  christos 	{ NULL, NULL, 0 }
   1218       1.1  christos };
   1219       1.1  christos 
   1220       1.8  christos static cfg_type_t cfg_type_fetchquota = { "fetchquota",	   cfg_parse_tuple,
   1221       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
   1222       1.8  christos 					  &cfg_rep_tuple,  fetchquota_fields };
   1223       1.1  christos 
   1224       1.1  christos /*%
   1225       1.1  christos  * fetches-per-server or fetches-per-zone
   1226       1.1  christos  */
   1227       1.1  christos 
   1228       1.1  christos static const char *response_enums[] = { "drop", "fail", NULL };
   1229       1.1  christos 
   1230       1.1  christos static cfg_type_t cfg_type_responsetype = {
   1231       1.8  christos 	"responsetype",	   parse_optional_enum, cfg_print_ustring,
   1232       1.8  christos 	doc_optional_enum, &cfg_rep_string,	response_enums
   1233       1.1  christos };
   1234       1.1  christos 
   1235       1.1  christos static cfg_tuplefielddef_t fetchesper_fields[] = {
   1236       1.1  christos 	{ "fetches", &cfg_type_uint32, 0 },
   1237       1.1  christos 	{ "response", &cfg_type_responsetype, 0 },
   1238       1.1  christos 	{ NULL, NULL, 0 }
   1239       1.1  christos };
   1240       1.1  christos 
   1241       1.8  christos static cfg_type_t cfg_type_fetchesper = { "fetchesper",	   cfg_parse_tuple,
   1242       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
   1243       1.8  christos 					  &cfg_rep_tuple,  fetchesper_fields };
   1244       1.1  christos 
   1245       1.1  christos /*%
   1246       1.1  christos  * Clauses that can be found within the top level of the named.conf
   1247       1.1  christos  * file only.
   1248       1.1  christos  */
   1249       1.8  christos static cfg_clausedef_t namedconf_clauses[] = {
   1250       1.1  christos 	{ "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
   1251       1.1  christos 	{ "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
   1252       1.8  christos 	{ "dnssec-policy", &cfg_type_dnssecpolicy, CFG_CLAUSEFLAG_MULTI },
   1253      1.15  christos #if HAVE_LIBNGHTTP2
   1254      1.15  christos 	{ "http", &cfg_type_http_description, CFG_CLAUSEFLAG_MULTI },
   1255      1.15  christos #else
   1256      1.15  christos 	{ "http", &cfg_type_http_description,
   1257      1.15  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NOTCONFIGURED },
   1258      1.15  christos #endif
   1259  1.15.2.1  perseant 	{ "key-store", &cfg_type_keystore, CFG_CLAUSEFLAG_MULTI },
   1260       1.1  christos 	{ "logging", &cfg_type_logging, 0 },
   1261      1.15  christos 	{ "lwres", NULL, CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
   1262  1.15.2.1  perseant 	{ "masters", &cfg_type_serverlist,
   1263      1.15  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NODOC },
   1264       1.1  christos 	{ "options", &cfg_type_options, 0 },
   1265  1.15.2.1  perseant 	{ "parental-agents", &cfg_type_serverlist,
   1266  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NODOC },
   1267  1.15.2.1  perseant 	{ "primaries", &cfg_type_serverlist,
   1268  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NODOC },
   1269  1.15.2.1  perseant 	{ "remote-servers", &cfg_type_serverlist, CFG_CLAUSEFLAG_MULTI },
   1270  1.15.2.1  perseant #if defined(HAVE_LIBXML2) || defined(HAVE_JSON_C)
   1271       1.1  christos 	{ "statistics-channels", &cfg_type_statschannels,
   1272       1.1  christos 	  CFG_CLAUSEFLAG_MULTI },
   1273  1.15.2.1  perseant #else
   1274  1.15.2.1  perseant 	{ "statistics-channels", &cfg_type_statschannels,
   1275  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NOTCONFIGURED },
   1276  1.15.2.1  perseant #endif
   1277      1.15  christos 	{ "tls", &cfg_type_tlsconf, CFG_CLAUSEFLAG_MULTI },
   1278       1.1  christos 	{ "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
   1279       1.1  christos 	{ NULL, NULL, 0 }
   1280       1.1  christos };
   1281       1.1  christos 
   1282       1.1  christos /*%
   1283       1.1  christos  * Clauses that can occur at the top level or in the view
   1284       1.1  christos  * statement, but not in the options block.
   1285       1.1  christos  */
   1286       1.8  christos static cfg_clausedef_t namedconf_or_view_clauses[] = {
   1287       1.1  christos 	{ "dlz", &cfg_type_dlz, CFG_CLAUSEFLAG_MULTI },
   1288       1.1  christos 	{ "dyndb", &cfg_type_dyndb, CFG_CLAUSEFLAG_MULTI },
   1289       1.1  christos 	{ "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
   1290       1.8  christos 	{ "managed-keys", &cfg_type_dnsseckeys,
   1291       1.8  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
   1292       1.3  christos 	{ "plugin", &cfg_type_plugin, CFG_CLAUSEFLAG_MULTI },
   1293       1.1  christos 	{ "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
   1294       1.8  christos 	{ "trust-anchors", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
   1295       1.8  christos 	{ "trusted-keys", &cfg_type_trustedkeys,
   1296       1.8  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
   1297      1.15  christos 	{ "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NODOC },
   1298       1.1  christos 	{ NULL, NULL, 0 }
   1299       1.1  christos };
   1300       1.1  christos 
   1301       1.1  christos /*%
   1302       1.1  christos  * Clauses that can occur in the bind.keys file.
   1303       1.1  christos  */
   1304       1.8  christos static cfg_clausedef_t bindkeys_clauses[] = {
   1305       1.8  christos 	{ "managed-keys", &cfg_type_dnsseckeys,
   1306       1.8  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
   1307       1.8  christos 	{ "trust-anchors", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI },
   1308       1.8  christos 	{ "trusted-keys", &cfg_type_trustedkeys,
   1309       1.8  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
   1310       1.1  christos 	{ NULL, NULL, 0 }
   1311       1.1  christos };
   1312       1.1  christos 
   1313       1.1  christos static const char *fstrm_model_enums[] = { "mpsc", "spsc", NULL };
   1314       1.1  christos static cfg_type_t cfg_type_fstrm_model = {
   1315       1.8  christos 	"model",      cfg_parse_enum,  cfg_print_ustring,
   1316       1.8  christos 	cfg_doc_enum, &cfg_rep_string, &fstrm_model_enums
   1317       1.1  christos };
   1318       1.1  christos 
   1319       1.1  christos /*%
   1320       1.1  christos  * Clauses that can be found within the 'options' statement.
   1321       1.1  christos  */
   1322       1.8  christos static cfg_clausedef_t options_clauses[] = {
   1323       1.1  christos 	{ "answer-cookie", &cfg_type_boolean, 0 },
   1324       1.1  christos 	{ "automatic-interface-scan", &cfg_type_boolean, 0 },
   1325      1.15  christos 	{ "avoid-v4-udp-ports", &cfg_type_bracketed_portlist,
   1326      1.15  christos 	  CFG_CLAUSEFLAG_DEPRECATED },
   1327      1.15  christos 	{ "avoid-v6-udp-ports", &cfg_type_bracketed_portlist,
   1328      1.15  christos 	  CFG_CLAUSEFLAG_DEPRECATED },
   1329  1.15.2.1  perseant 	{ "bindkeys-file", &cfg_type_qstring, CFG_CLAUSEFLAG_TESTONLY },
   1330       1.1  christos 	{ "blackhole", &cfg_type_bracketed_aml, 0 },
   1331       1.1  christos 	{ "cookie-algorithm", &cfg_type_cookiealg, 0 },
   1332       1.1  christos 	{ "cookie-secret", &cfg_type_sstring, CFG_CLAUSEFLAG_MULTI },
   1333  1.15.2.1  perseant 	{ "coresize", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT },
   1334  1.15.2.1  perseant 	{ "datasize", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT },
   1335      1.15  christos 	{ "deallocate-on-exit", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1336       1.1  christos 	{ "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
   1337  1.15.2.1  perseant #ifdef USE_DNSRPS
   1338  1.15.2.1  perseant 	{ "dnsrps-library", &cfg_type_qstring, 0 },
   1339  1.15.2.1  perseant #else  /* ifdef USE_DNSRPS */
   1340  1.15.2.1  perseant 	{ "dnsrps-library", &cfg_type_qstring, CFG_CLAUSEFLAG_NOTCONFIGURED },
   1341  1.15.2.1  perseant #endif /* ifdef USE_DNSRPS */
   1342       1.1  christos #ifdef HAVE_DNSTAP
   1343       1.1  christos 	{ "dnstap-output", &cfg_type_dnstapoutput, 0 },
   1344       1.1  christos 	{ "dnstap-identity", &cfg_type_serverid, 0 },
   1345       1.1  christos 	{ "dnstap-version", &cfg_type_qstringornone, 0 },
   1346       1.8  christos #else  /* ifdef HAVE_DNSTAP */
   1347       1.1  christos 	{ "dnstap-output", &cfg_type_dnstapoutput,
   1348       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1349       1.8  christos 	{ "dnstap-identity", &cfg_type_serverid, CFG_CLAUSEFLAG_NOTCONFIGURED },
   1350       1.1  christos 	{ "dnstap-version", &cfg_type_qstringornone,
   1351       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1352       1.8  christos #endif /* ifdef HAVE_DNSTAP */
   1353  1.15.2.1  perseant 	{ "dscp", &cfg_type_uint32, CFG_CLAUSEFLAG_ANCIENT },
   1354       1.1  christos 	{ "dump-file", &cfg_type_qstring, 0 },
   1355      1.15  christos 	{ "fake-iquery", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1356  1.15.2.1  perseant 	{ "files", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT },
   1357       1.1  christos 	{ "flush-zones-on-shutdown", &cfg_type_boolean, 0 },
   1358       1.1  christos #ifdef HAVE_DNSTAP
   1359       1.1  christos 	{ "fstrm-set-buffer-hint", &cfg_type_uint32, 0 },
   1360       1.1  christos 	{ "fstrm-set-flush-timeout", &cfg_type_uint32, 0 },
   1361       1.1  christos 	{ "fstrm-set-input-queue-size", &cfg_type_uint32, 0 },
   1362       1.1  christos 	{ "fstrm-set-output-notify-threshold", &cfg_type_uint32, 0 },
   1363       1.1  christos 	{ "fstrm-set-output-queue-model", &cfg_type_fstrm_model, 0 },
   1364       1.1  christos 	{ "fstrm-set-output-queue-size", &cfg_type_uint32, 0 },
   1365       1.8  christos 	{ "fstrm-set-reopen-interval", &cfg_type_duration, 0 },
   1366       1.8  christos #else  /* ifdef HAVE_DNSTAP */
   1367       1.1  christos 	{ "fstrm-set-buffer-hint", &cfg_type_uint32,
   1368       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1369       1.1  christos 	{ "fstrm-set-flush-timeout", &cfg_type_uint32,
   1370       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1371       1.1  christos 	{ "fstrm-set-input-queue-size", &cfg_type_uint32,
   1372       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1373       1.1  christos 	{ "fstrm-set-output-notify-threshold", &cfg_type_uint32,
   1374       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1375       1.1  christos 	{ "fstrm-set-output-queue-model", &cfg_type_fstrm_model,
   1376       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1377       1.1  christos 	{ "fstrm-set-output-queue-size", &cfg_type_uint32,
   1378       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1379       1.8  christos 	{ "fstrm-set-reopen-interval", &cfg_type_duration,
   1380       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1381       1.1  christos #endif /* HAVE_DNSTAP */
   1382       1.8  christos #if defined(HAVE_GEOIP2)
   1383       1.1  christos 	{ "geoip-directory", &cfg_type_qstringornone, 0 },
   1384       1.8  christos #else  /* if defined(HAVE_GEOIP2) */
   1385       1.1  christos 	{ "geoip-directory", &cfg_type_qstringornone,
   1386       1.1  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1387       1.8  christos #endif /* HAVE_GEOIP2 */
   1388      1.15  christos 	{ "geoip-use-ecs", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1389      1.15  christos 	{ "has-old-clients", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1390      1.15  christos 	{ "heartbeat-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_DEPRECATED },
   1391      1.15  christos 	{ "host-statistics", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1392      1.15  christos 	{ "host-statistics-max", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1393       1.1  christos 	{ "hostname", &cfg_type_qstringornone, 0 },
   1394       1.8  christos 	{ "interface-interval", &cfg_type_duration, 0 },
   1395  1.15.2.1  perseant 	{ "keep-response-order", &cfg_type_bracketed_aml,
   1396  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_OBSOLETE },
   1397       1.1  christos 	{ "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
   1398       1.1  christos 	{ "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
   1399  1.15.2.1  perseant 	{ "lock-file", &cfg_type_qstringornone, CFG_CLAUSEFLAG_ANCIENT },
   1400       1.1  christos 	{ "managed-keys-directory", &cfg_type_qstring, 0 },
   1401       1.1  christos 	{ "match-mapped-addresses", &cfg_type_boolean, 0 },
   1402       1.1  christos 	{ "max-rsa-exponent-size", &cfg_type_uint32, 0 },
   1403       1.1  christos 	{ "memstatistics", &cfg_type_boolean, 0 },
   1404       1.1  christos 	{ "memstatistics-file", &cfg_type_qstring, 0 },
   1405      1.15  christos 	{ "multiple-cnames", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1406      1.15  christos 	{ "named-xfer", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1407       1.1  christos 	{ "notify-rate", &cfg_type_uint32, 0 },
   1408       1.1  christos 	{ "pid-file", &cfg_type_qstringornone, 0 },
   1409       1.1  christos 	{ "port", &cfg_type_uint32, 0 },
   1410      1.15  christos 	{ "tls-port", &cfg_type_uint32, 0 },
   1411      1.15  christos #if HAVE_LIBNGHTTP2
   1412      1.15  christos 	{ "http-port", &cfg_type_uint32, 0 },
   1413      1.15  christos 	{ "http-listener-clients", &cfg_type_uint32, 0 },
   1414      1.15  christos 	{ "http-streams-per-connection", &cfg_type_uint32, 0 },
   1415      1.15  christos 	{ "https-port", &cfg_type_uint32, 0 },
   1416      1.15  christos #else
   1417      1.15  christos 	{ "http-port", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTCONFIGURED },
   1418      1.15  christos 	{ "http-listener-clients", &cfg_type_uint32,
   1419      1.15  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1420      1.15  christos 	{ "http-streams-per-connection", &cfg_type_uint32,
   1421      1.15  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1422      1.15  christos 	{ "https-port", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTCONFIGURED },
   1423      1.15  christos #endif
   1424       1.1  christos 	{ "querylog", &cfg_type_boolean, 0 },
   1425  1.15.2.1  perseant 	{ "random-device", &cfg_type_qstringornone, CFG_CLAUSEFLAG_ANCIENT },
   1426       1.1  christos 	{ "recursing-file", &cfg_type_qstring, 0 },
   1427       1.1  christos 	{ "recursive-clients", &cfg_type_uint32, 0 },
   1428      1.13  christos 	{ "reuseport", &cfg_type_boolean, 0 },
   1429  1.15.2.1  perseant 	{ "reserved-sockets", &cfg_type_uint32, CFG_CLAUSEFLAG_ANCIENT },
   1430  1.15.2.1  perseant 	{ "responselog", &cfg_type_boolean, 0 },
   1431       1.1  christos 	{ "secroots-file", &cfg_type_qstring, 0 },
   1432      1.15  christos 	{ "serial-queries", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1433       1.1  christos 	{ "serial-query-rate", &cfg_type_uint32, 0 },
   1434       1.1  christos 	{ "server-id", &cfg_type_serverid, 0 },
   1435       1.1  christos 	{ "session-keyalg", &cfg_type_astring, 0 },
   1436       1.1  christos 	{ "session-keyfile", &cfg_type_qstringornone, 0 },
   1437       1.1  christos 	{ "session-keyname", &cfg_type_astring, 0 },
   1438  1.15.2.1  perseant 	{ "sig0checks-quota", &cfg_type_uint32, CFG_CLAUSEFLAG_EXPERIMENTAL },
   1439  1.15.2.1  perseant 	{ "sig0checks-quota-exempt", &cfg_type_bracketed_aml,
   1440  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_EXPERIMENTAL },
   1441      1.15  christos 	{ "sit-secret", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1442  1.15.2.1  perseant 	{ "stacksize", &cfg_type_size, CFG_CLAUSEFLAG_ANCIENT },
   1443       1.1  christos 	{ "startup-notify-rate", &cfg_type_uint32, 0 },
   1444       1.1  christos 	{ "statistics-file", &cfg_type_qstring, 0 },
   1445      1.15  christos 	{ "statistics-interval", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1446       1.1  christos 	{ "tcp-advertised-timeout", &cfg_type_uint32, 0 },
   1447       1.1  christos 	{ "tcp-clients", &cfg_type_uint32, 0 },
   1448       1.1  christos 	{ "tcp-idle-timeout", &cfg_type_uint32, 0 },
   1449       1.1  christos 	{ "tcp-initial-timeout", &cfg_type_uint32, 0 },
   1450       1.1  christos 	{ "tcp-keepalive-timeout", &cfg_type_uint32, 0 },
   1451       1.1  christos 	{ "tcp-listen-queue", &cfg_type_uint32, 0 },
   1452      1.15  christos 	{ "tcp-receive-buffer", &cfg_type_uint32, 0 },
   1453      1.15  christos 	{ "tcp-send-buffer", &cfg_type_uint32, 0 },
   1454  1.15.2.1  perseant 	{ "tkey-dhkey", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1455       1.1  christos 	{ "tkey-domain", &cfg_type_qstring, 0 },
   1456       1.1  christos 	{ "tkey-gssapi-credential", &cfg_type_qstring, 0 },
   1457       1.1  christos 	{ "tkey-gssapi-keytab", &cfg_type_qstring, 0 },
   1458       1.1  christos 	{ "transfer-message-size", &cfg_type_uint32, 0 },
   1459       1.1  christos 	{ "transfers-in", &cfg_type_uint32, 0 },
   1460       1.1  christos 	{ "transfers-out", &cfg_type_uint32, 0 },
   1461       1.1  christos 	{ "transfers-per-ns", &cfg_type_uint32, 0 },
   1462      1.15  christos 	{ "treat-cr-as-space", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1463      1.15  christos 	{ "udp-receive-buffer", &cfg_type_uint32, 0 },
   1464      1.15  christos 	{ "udp-send-buffer", &cfg_type_uint32, 0 },
   1465      1.14  christos 	{ "update-quota", &cfg_type_uint32, 0 },
   1466      1.15  christos 	{ "use-id-pool", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1467      1.15  christos 	{ "use-ixfr", NULL, CFG_CLAUSEFLAG_ANCIENT },
   1468      1.15  christos 	{ "use-v4-udp-ports", &cfg_type_bracketed_portlist,
   1469      1.15  christos 	  CFG_CLAUSEFLAG_DEPRECATED },
   1470      1.15  christos 	{ "use-v6-udp-ports", &cfg_type_bracketed_portlist,
   1471      1.15  christos 	  CFG_CLAUSEFLAG_DEPRECATED },
   1472       1.1  christos 	{ "version", &cfg_type_qstringornone, 0 },
   1473       1.1  christos 	{ NULL, NULL, 0 }
   1474       1.1  christos };
   1475       1.1  christos 
   1476       1.8  christos static cfg_type_t cfg_type_namelist = { "namelist",
   1477       1.8  christos 					cfg_parse_bracketed_list,
   1478       1.8  christos 					cfg_print_bracketed_list,
   1479       1.8  christos 					cfg_doc_bracketed_list,
   1480       1.8  christos 					&cfg_rep_list,
   1481       1.8  christos 					&cfg_type_astring };
   1482       1.1  christos 
   1483       1.1  christos static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist };
   1484       1.1  christos 
   1485       1.1  christos static cfg_type_t cfg_type_optional_exclude = {
   1486       1.8  christos 	"optional_exclude",    parse_optional_keyvalue, print_keyvalue,
   1487       1.8  christos 	doc_optional_keyvalue, &cfg_rep_list,		&exclude_kw
   1488       1.1  christos };
   1489       1.1  christos 
   1490       1.8  christos static keyword_type_t exceptionnames_kw = { "except-from", &cfg_type_namelist };
   1491       1.1  christos 
   1492       1.1  christos static cfg_type_t cfg_type_optional_exceptionnames = {
   1493       1.8  christos 	"optional_allow",      parse_optional_keyvalue, print_keyvalue,
   1494       1.8  christos 	doc_optional_keyvalue, &cfg_rep_list,		&exceptionnames_kw
   1495       1.1  christos };
   1496       1.1  christos 
   1497       1.1  christos static cfg_tuplefielddef_t denyaddresses_fields[] = {
   1498       1.1  christos 	{ "acl", &cfg_type_bracketed_aml, 0 },
   1499       1.1  christos 	{ "except-from", &cfg_type_optional_exceptionnames, 0 },
   1500       1.1  christos 	{ NULL, NULL, 0 }
   1501       1.1  christos };
   1502       1.1  christos 
   1503       1.1  christos static cfg_type_t cfg_type_denyaddresses = {
   1504       1.8  christos 	"denyaddresses", cfg_parse_tuple, cfg_print_tuple,
   1505       1.8  christos 	cfg_doc_tuple,	 &cfg_rep_tuple,  denyaddresses_fields
   1506       1.1  christos };
   1507       1.1  christos 
   1508       1.1  christos static cfg_tuplefielddef_t denyaliases_fields[] = {
   1509       1.1  christos 	{ "name", &cfg_type_namelist, 0 },
   1510       1.1  christos 	{ "except-from", &cfg_type_optional_exceptionnames, 0 },
   1511       1.1  christos 	{ NULL, NULL, 0 }
   1512       1.1  christos };
   1513       1.1  christos 
   1514       1.1  christos static cfg_type_t cfg_type_denyaliases = {
   1515       1.8  christos 	"denyaliases", cfg_parse_tuple, cfg_print_tuple,
   1516       1.8  christos 	cfg_doc_tuple, &cfg_rep_tuple,	denyaliases_fields
   1517       1.1  christos };
   1518       1.1  christos 
   1519       1.8  christos static cfg_type_t cfg_type_algorithmlist = { "algorithmlist",
   1520       1.8  christos 					     cfg_parse_bracketed_list,
   1521       1.8  christos 					     cfg_print_bracketed_list,
   1522       1.8  christos 					     cfg_doc_bracketed_list,
   1523       1.8  christos 					     &cfg_rep_list,
   1524       1.8  christos 					     &cfg_type_astring };
   1525       1.1  christos 
   1526       1.1  christos static cfg_tuplefielddef_t disablealgorithm_fields[] = {
   1527       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   1528       1.1  christos 	{ "algorithms", &cfg_type_algorithmlist, 0 },
   1529       1.1  christos 	{ NULL, NULL, 0 }
   1530       1.1  christos };
   1531       1.1  christos 
   1532       1.1  christos static cfg_type_t cfg_type_disablealgorithm = {
   1533       1.8  christos 	"disablealgorithm", cfg_parse_tuple, cfg_print_tuple,
   1534       1.8  christos 	cfg_doc_tuple,	    &cfg_rep_tuple,  disablealgorithm_fields
   1535       1.1  christos };
   1536       1.1  christos 
   1537       1.8  christos static cfg_type_t cfg_type_dsdigestlist = { "dsdigestlist",
   1538       1.8  christos 					    cfg_parse_bracketed_list,
   1539       1.8  christos 					    cfg_print_bracketed_list,
   1540       1.8  christos 					    cfg_doc_bracketed_list,
   1541       1.8  christos 					    &cfg_rep_list,
   1542       1.8  christos 					    &cfg_type_astring };
   1543       1.1  christos 
   1544       1.1  christos static cfg_tuplefielddef_t disabledsdigest_fields[] = {
   1545       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   1546       1.1  christos 	{ "digests", &cfg_type_dsdigestlist, 0 },
   1547       1.1  christos 	{ NULL, NULL, 0 }
   1548       1.1  christos };
   1549       1.1  christos 
   1550       1.1  christos static cfg_type_t cfg_type_disabledsdigest = {
   1551       1.8  christos 	"disabledsdigest", cfg_parse_tuple, cfg_print_tuple,
   1552       1.8  christos 	cfg_doc_tuple,	   &cfg_rep_tuple,  disabledsdigest_fields
   1553       1.1  christos };
   1554       1.1  christos 
   1555       1.1  christos static cfg_tuplefielddef_t mustbesecure_fields[] = {
   1556       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   1557       1.1  christos 	{ "value", &cfg_type_boolean, 0 },
   1558       1.1  christos 	{ NULL, NULL, 0 }
   1559       1.1  christos };
   1560       1.1  christos 
   1561       1.1  christos static cfg_type_t cfg_type_mustbesecure = {
   1562       1.8  christos 	"mustbesecure", cfg_parse_tuple, cfg_print_tuple,
   1563       1.8  christos 	cfg_doc_tuple,	&cfg_rep_tuple,	 mustbesecure_fields
   1564       1.1  christos };
   1565       1.1  christos 
   1566      1.15  christos static const char *masterformat_enums[] = { "raw", "text", NULL };
   1567       1.1  christos static cfg_type_t cfg_type_masterformat = {
   1568       1.8  christos 	"masterformat", cfg_parse_enum,	 cfg_print_ustring,
   1569       1.8  christos 	cfg_doc_enum,	&cfg_rep_string, &masterformat_enums
   1570       1.1  christos };
   1571       1.1  christos 
   1572       1.1  christos static const char *masterstyle_enums[] = { "full", "relative", NULL };
   1573       1.1  christos static cfg_type_t cfg_type_masterstyle = {
   1574       1.8  christos 	"masterstyle", cfg_parse_enum,	cfg_print_ustring,
   1575       1.8  christos 	cfg_doc_enum,  &cfg_rep_string, &masterstyle_enums
   1576       1.1  christos };
   1577       1.1  christos 
   1578       1.1  christos static keyword_type_t blocksize_kw = { "block-size", &cfg_type_uint32 };
   1579       1.1  christos 
   1580       1.8  christos static cfg_type_t cfg_type_blocksize = { "blocksize",	  parse_keyvalue,
   1581       1.8  christos 					 print_keyvalue,  doc_keyvalue,
   1582       1.8  christos 					 &cfg_rep_uint32, &blocksize_kw };
   1583       1.1  christos 
   1584       1.1  christos static cfg_tuplefielddef_t resppadding_fields[] = {
   1585       1.1  christos 	{ "acl", &cfg_type_bracketed_aml, 0 },
   1586       1.1  christos 	{ "block-size", &cfg_type_blocksize, 0 },
   1587       1.1  christos 	{ NULL, NULL, 0 }
   1588       1.1  christos };
   1589       1.1  christos 
   1590       1.1  christos static cfg_type_t cfg_type_resppadding = {
   1591       1.8  christos 	"resppadding", cfg_parse_tuple, cfg_print_tuple,
   1592       1.8  christos 	cfg_doc_tuple, &cfg_rep_tuple,	resppadding_fields
   1593       1.1  christos };
   1594       1.1  christos 
   1595       1.1  christos /*%
   1596       1.1  christos  *  dnstap {
   1597       1.1  christos  *      &lt;message type&gt; [query | response] ;
   1598       1.1  christos  *      ...
   1599       1.1  christos  *  }
   1600       1.1  christos  *
   1601       1.3  christos  *  ... where message type is one of: client, resolver, auth, forwarder,
   1602       1.3  christos  *                                    update, all
   1603       1.1  christos  */
   1604       1.8  christos static const char *dnstap_types[] = { "all",	   "auth",     "client",
   1605       1.8  christos 				      "forwarder", "resolver", "update",
   1606       1.8  christos 				      NULL };
   1607       1.1  christos 
   1608       1.1  christos static const char *dnstap_modes[] = { "query", "response", NULL };
   1609       1.1  christos 
   1610       1.8  christos static cfg_type_t cfg_type_dnstap_type = { "dnstap_type",     cfg_parse_enum,
   1611       1.8  christos 					   cfg_print_ustring, cfg_doc_enum,
   1612       1.8  christos 					   &cfg_rep_string,   dnstap_types };
   1613       1.1  christos 
   1614       1.1  christos static cfg_type_t cfg_type_dnstap_mode = {
   1615       1.8  christos 	"dnstap_mode",	   parse_optional_enum, cfg_print_ustring,
   1616       1.8  christos 	doc_optional_enum, &cfg_rep_string,	dnstap_modes
   1617       1.1  christos };
   1618       1.1  christos 
   1619       1.1  christos static cfg_tuplefielddef_t dnstap_fields[] = {
   1620       1.1  christos 	{ "type", &cfg_type_dnstap_type, 0 },
   1621       1.1  christos 	{ "mode", &cfg_type_dnstap_mode, 0 },
   1622       1.1  christos 	{ NULL, NULL, 0 }
   1623       1.1  christos };
   1624       1.1  christos 
   1625       1.8  christos static cfg_type_t cfg_type_dnstap_entry = { "dnstap_value",  cfg_parse_tuple,
   1626       1.8  christos 					    cfg_print_tuple, cfg_doc_tuple,
   1627       1.8  christos 					    &cfg_rep_tuple,  dnstap_fields };
   1628       1.8  christos 
   1629       1.8  christos static cfg_type_t cfg_type_dnstap = { "dnstap",
   1630       1.8  christos 				      cfg_parse_bracketed_list,
   1631       1.8  christos 				      cfg_print_bracketed_list,
   1632       1.8  christos 				      cfg_doc_bracketed_list,
   1633       1.8  christos 				      &cfg_rep_list,
   1634       1.8  christos 				      &cfg_type_dnstap_entry };
   1635       1.1  christos 
   1636       1.1  christos /*%
   1637       1.1  christos  * dnstap-output
   1638       1.1  christos  */
   1639       1.1  christos static isc_result_t
   1640       1.1  christos parse_dtout(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   1641       1.1  christos 	isc_result_t result;
   1642       1.1  christos 	cfg_obj_t *obj = NULL;
   1643       1.1  christos 	const cfg_tuplefielddef_t *fields = type->of;
   1644       1.1  christos 
   1645       1.1  christos 	CHECK(cfg_create_tuple(pctx, type, &obj));
   1646       1.1  christos 
   1647       1.1  christos 	/* Parse the mandatory "mode" and "path" fields */
   1648       1.1  christos 	CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
   1649       1.1  christos 	CHECK(cfg_parse_obj(pctx, fields[1].type, &obj->value.tuple[1]));
   1650       1.1  christos 
   1651       1.1  christos 	/* Parse "versions" and "size" fields in any order. */
   1652       1.1  christos 	for (;;) {
   1653       1.1  christos 		CHECK(cfg_peektoken(pctx, 0));
   1654       1.1  christos 		if (pctx->token.type == isc_tokentype_string) {
   1655       1.1  christos 			CHECK(cfg_gettoken(pctx, 0));
   1656       1.8  christos 			if (strcasecmp(TOKEN_STRING(pctx), "size") == 0 &&
   1657      1.14  christos 			    obj->value.tuple[2] == NULL)
   1658      1.14  christos 			{
   1659       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[2].type,
   1660       1.1  christos 						    &obj->value.tuple[2]));
   1661       1.8  christos 			} else if (strcasecmp(TOKEN_STRING(pctx), "versions") ==
   1662       1.8  christos 					   0 &&
   1663       1.1  christos 				   obj->value.tuple[3] == NULL)
   1664       1.1  christos 			{
   1665       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[3].type,
   1666       1.1  christos 						    &obj->value.tuple[3]));
   1667       1.8  christos 			} else if (strcasecmp(TOKEN_STRING(pctx), "suffix") ==
   1668       1.8  christos 					   0 &&
   1669       1.8  christos 				   obj->value.tuple[4] == NULL)
   1670       1.8  christos 			{
   1671       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[4].type,
   1672       1.8  christos 						    &obj->value.tuple[4]));
   1673       1.1  christos 			} else {
   1674       1.1  christos 				cfg_parser_error(pctx, CFG_LOG_NEAR,
   1675       1.1  christos 						 "unexpected token");
   1676       1.1  christos 				result = ISC_R_UNEXPECTEDTOKEN;
   1677       1.1  christos 				goto cleanup;
   1678       1.1  christos 			}
   1679       1.1  christos 		} else {
   1680       1.1  christos 			break;
   1681       1.1  christos 		}
   1682       1.1  christos 	}
   1683       1.1  christos 
   1684       1.1  christos 	/* Create void objects for missing optional values. */
   1685       1.8  christos 	if (obj->value.tuple[2] == NULL) {
   1686       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
   1687       1.8  christos 	}
   1688       1.8  christos 	if (obj->value.tuple[3] == NULL) {
   1689       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[3]));
   1690       1.8  christos 	}
   1691       1.8  christos 	if (obj->value.tuple[4] == NULL) {
   1692       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[4]));
   1693       1.8  christos 	}
   1694       1.1  christos 
   1695       1.1  christos 	*ret = obj;
   1696  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   1697       1.1  christos 
   1698       1.8  christos cleanup:
   1699       1.1  christos 	CLEANUP_OBJ(obj);
   1700  1.15.2.1  perseant 	return result;
   1701       1.1  christos }
   1702       1.1  christos 
   1703       1.1  christos static void
   1704       1.1  christos print_dtout(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1705       1.1  christos 	cfg_print_obj(pctx, obj->value.tuple[0]); /* mode */
   1706       1.1  christos 	cfg_print_obj(pctx, obj->value.tuple[1]); /* file */
   1707       1.1  christos 	if (obj->value.tuple[2]->type->print != cfg_print_void) {
   1708       1.1  christos 		cfg_print_cstr(pctx, " size ");
   1709       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[2]);
   1710       1.1  christos 	}
   1711       1.1  christos 	if (obj->value.tuple[3]->type->print != cfg_print_void) {
   1712       1.1  christos 		cfg_print_cstr(pctx, " versions ");
   1713       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[3]);
   1714       1.1  christos 	}
   1715       1.1  christos 	if (obj->value.tuple[4]->type->print != cfg_print_void) {
   1716       1.1  christos 		cfg_print_cstr(pctx, " suffix ");
   1717       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[4]);
   1718       1.1  christos 	}
   1719       1.1  christos }
   1720       1.1  christos 
   1721       1.1  christos static void
   1722       1.1  christos doc_dtout(cfg_printer_t *pctx, const cfg_type_t *type) {
   1723       1.1  christos 	UNUSED(type);
   1724       1.1  christos 	cfg_print_cstr(pctx, "( file | unix ) <quoted_string>");
   1725       1.1  christos 	cfg_print_cstr(pctx, " ");
   1726       1.1  christos 	cfg_print_cstr(pctx, "[ size ( unlimited | <size> ) ]");
   1727       1.1  christos 	cfg_print_cstr(pctx, " ");
   1728       1.1  christos 	cfg_print_cstr(pctx, "[ versions ( unlimited | <integer> ) ]");
   1729       1.1  christos 	cfg_print_cstr(pctx, " ");
   1730       1.1  christos 	cfg_print_cstr(pctx, "[ suffix ( increment | timestamp ) ]");
   1731       1.1  christos }
   1732       1.1  christos 
   1733       1.1  christos static const char *dtoutmode_enums[] = { "file", "unix", NULL };
   1734       1.8  christos static cfg_type_t cfg_type_dtmode = { "dtmode",		 cfg_parse_enum,
   1735       1.8  christos 				      cfg_print_ustring, cfg_doc_enum,
   1736       1.8  christos 				      &cfg_rep_string,	 &dtoutmode_enums };
   1737       1.1  christos 
   1738       1.1  christos static cfg_tuplefielddef_t dtout_fields[] = {
   1739       1.1  christos 	{ "mode", &cfg_type_dtmode, 0 },
   1740       1.1  christos 	{ "path", &cfg_type_qstring, 0 },
   1741       1.1  christos 	{ "size", &cfg_type_sizenodefault, 0 },
   1742       1.1  christos 	{ "versions", &cfg_type_logversions, 0 },
   1743       1.1  christos 	{ "suffix", &cfg_type_logsuffix, 0 },
   1744       1.1  christos 	{ NULL, NULL, 0 }
   1745       1.1  christos };
   1746       1.1  christos 
   1747       1.8  christos static cfg_type_t cfg_type_dnstapoutput = { "dnstapoutput", parse_dtout,
   1748       1.8  christos 					    print_dtout,    doc_dtout,
   1749       1.8  christos 					    &cfg_rep_tuple, dtout_fields };
   1750       1.1  christos 
   1751       1.1  christos /*%
   1752       1.1  christos  *  response-policy {
   1753       1.1  christos  *	zone &lt;string&gt; [ policy (given|disabled|passthru|drop|tcp-only|
   1754       1.1  christos  *					nxdomain|nodata|cname &lt;domain&gt; ) ]
   1755       1.1  christos  *		      [ recursive-only yes|no ] [ log yes|no ]
   1756       1.1  christos  *		      [ max-policy-ttl number ]
   1757       1.1  christos  *		      [ nsip-enable yes|no ] [ nsdname-enable yes|no ];
   1758       1.1  christos  *  } [ recursive-only yes|no ] [ max-policy-ttl number ]
   1759       1.1  christos  *	 [ min-update-interval number ]
   1760       1.1  christos  *	 [ break-dnssec yes|no ] [ min-ns-dots number ]
   1761       1.1  christos  *	 [ qname-wait-recurse yes|no ]
   1762       1.1  christos  *	 [ nsip-enable yes|no ] [ nsdname-enable yes|no ]
   1763       1.1  christos  *	 [ dnsrps-enable yes|no ]
   1764       1.1  christos  *	 [ dnsrps-options { DNSRPS configuration string } ];
   1765       1.1  christos  */
   1766       1.1  christos 
   1767       1.1  christos static void
   1768       1.1  christos doc_rpz_policy(cfg_printer_t *pctx, const cfg_type_t *type) {
   1769       1.8  christos 	const char *const *p;
   1770       1.1  christos 	/*
   1771       1.1  christos 	 * This is cfg_doc_enum() without the trailing " )".
   1772       1.1  christos 	 */
   1773       1.1  christos 	cfg_print_cstr(pctx, "( ");
   1774       1.1  christos 	for (p = type->of; *p != NULL; p++) {
   1775       1.1  christos 		cfg_print_cstr(pctx, *p);
   1776       1.8  christos 		if (p[1] != NULL) {
   1777       1.1  christos 			cfg_print_cstr(pctx, " | ");
   1778       1.8  christos 		}
   1779       1.1  christos 	}
   1780       1.1  christos }
   1781       1.1  christos 
   1782       1.1  christos static void
   1783       1.1  christos doc_rpz_cname(cfg_printer_t *pctx, const cfg_type_t *type) {
   1784       1.1  christos 	cfg_doc_terminal(pctx, type);
   1785       1.1  christos 	cfg_print_cstr(pctx, " )");
   1786       1.1  christos }
   1787       1.1  christos 
   1788       1.1  christos /*
   1789       1.1  christos  * Parse
   1790       1.1  christos  *	given|disabled|passthru|drop|tcp-only|nxdomain|nodata|cname <domain>
   1791       1.1  christos  */
   1792       1.1  christos static isc_result_t
   1793       1.1  christos cfg_parse_rpz_policy(cfg_parser_t *pctx, const cfg_type_t *type,
   1794       1.8  christos 		     cfg_obj_t **ret) {
   1795       1.1  christos 	isc_result_t result;
   1796       1.1  christos 	cfg_obj_t *obj = NULL;
   1797       1.1  christos 	const cfg_tuplefielddef_t *fields;
   1798       1.1  christos 
   1799       1.1  christos 	CHECK(cfg_create_tuple(pctx, type, &obj));
   1800       1.1  christos 
   1801       1.1  christos 	fields = type->of;
   1802       1.1  christos 	CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
   1803       1.1  christos 	/*
   1804       1.1  christos 	 * parse cname domain only after "policy cname"
   1805       1.1  christos 	 */
   1806       1.1  christos 	if (strcasecmp("cname", cfg_obj_asstring(obj->value.tuple[0])) != 0) {
   1807       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
   1808       1.1  christos 	} else {
   1809       1.1  christos 		CHECK(cfg_parse_obj(pctx, fields[1].type,
   1810       1.1  christos 				    &obj->value.tuple[1]));
   1811       1.1  christos 	}
   1812       1.1  christos 
   1813       1.1  christos 	*ret = obj;
   1814  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   1815       1.1  christos 
   1816       1.1  christos cleanup:
   1817       1.1  christos 	CLEANUP_OBJ(obj);
   1818  1.15.2.1  perseant 	return result;
   1819       1.1  christos }
   1820       1.1  christos 
   1821       1.1  christos /*
   1822       1.1  christos  * Parse a tuple consisting of any kind of required field followed
   1823       1.1  christos  * by 2 or more optional keyvalues that can be in any order.
   1824       1.1  christos  */
   1825       1.1  christos static isc_result_t
   1826       1.1  christos cfg_parse_kv_tuple(cfg_parser_t *pctx, const cfg_type_t *type,
   1827       1.8  christos 		   cfg_obj_t **ret) {
   1828       1.1  christos 	const cfg_tuplefielddef_t *fields, *f;
   1829       1.1  christos 	cfg_obj_t *obj = NULL;
   1830       1.1  christos 	int fn;
   1831       1.1  christos 	isc_result_t result;
   1832       1.1  christos 
   1833       1.1  christos 	CHECK(cfg_create_tuple(pctx, type, &obj));
   1834       1.1  christos 
   1835       1.1  christos 	/*
   1836       1.1  christos 	 * The zone first field is required and always first.
   1837       1.1  christos 	 */
   1838       1.1  christos 	fields = type->of;
   1839       1.1  christos 	CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
   1840       1.1  christos 
   1841       1.1  christos 	for (;;) {
   1842       1.1  christos 		CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
   1843       1.8  christos 		if (pctx->token.type != isc_tokentype_string) {
   1844       1.1  christos 			break;
   1845       1.8  christos 		}
   1846       1.1  christos 
   1847       1.8  christos 		for (fn = 1, f = &fields[1];; ++fn, ++f) {
   1848       1.1  christos 			if (f->name == NULL) {
   1849       1.1  christos 				cfg_parser_error(pctx, 0, "unexpected '%s'",
   1850       1.1  christos 						 TOKEN_STRING(pctx));
   1851       1.1  christos 				result = ISC_R_UNEXPECTEDTOKEN;
   1852       1.1  christos 				goto cleanup;
   1853       1.1  christos 			}
   1854       1.1  christos 			if (obj->value.tuple[fn] == NULL &&
   1855       1.1  christos 			    strcasecmp(f->name, TOKEN_STRING(pctx)) == 0)
   1856       1.8  christos 			{
   1857       1.1  christos 				break;
   1858       1.8  christos 			}
   1859       1.1  christos 		}
   1860       1.1  christos 
   1861       1.1  christos 		CHECK(cfg_gettoken(pctx, 0));
   1862       1.1  christos 		CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[fn]));
   1863       1.1  christos 	}
   1864       1.1  christos 
   1865       1.1  christos 	for (fn = 1, f = &fields[1]; f->name != NULL; ++fn, ++f) {
   1866       1.8  christos 		if (obj->value.tuple[fn] == NULL) {
   1867       1.1  christos 			CHECK(cfg_parse_void(pctx, NULL,
   1868       1.1  christos 					     &obj->value.tuple[fn]));
   1869       1.8  christos 		}
   1870       1.1  christos 	}
   1871       1.1  christos 
   1872       1.1  christos 	*ret = obj;
   1873  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   1874       1.1  christos 
   1875       1.1  christos cleanup:
   1876       1.1  christos 	CLEANUP_OBJ(obj);
   1877  1.15.2.1  perseant 	return result;
   1878       1.1  christos }
   1879       1.1  christos 
   1880       1.1  christos static void
   1881       1.1  christos cfg_print_kv_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   1882       1.1  christos 	unsigned int i;
   1883       1.1  christos 	const cfg_tuplefielddef_t *fields, *f;
   1884       1.1  christos 	const cfg_obj_t *fieldobj;
   1885       1.1  christos 
   1886       1.1  christos 	fields = obj->type->of;
   1887       1.1  christos 	for (f = fields, i = 0; f->name != NULL; f++, i++) {
   1888       1.1  christos 		fieldobj = obj->value.tuple[i];
   1889       1.8  christos 		if (fieldobj->type->print == cfg_print_void) {
   1890       1.1  christos 			continue;
   1891       1.8  christos 		}
   1892       1.1  christos 		if (i != 0) {
   1893       1.1  christos 			cfg_print_cstr(pctx, " ");
   1894       1.1  christos 			cfg_print_cstr(pctx, f->name);
   1895       1.1  christos 			cfg_print_cstr(pctx, " ");
   1896       1.1  christos 		}
   1897       1.1  christos 		cfg_print_obj(pctx, fieldobj);
   1898       1.1  christos 	}
   1899       1.1  christos }
   1900       1.1  christos 
   1901       1.1  christos static void
   1902       1.1  christos cfg_doc_kv_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
   1903       1.1  christos 	const cfg_tuplefielddef_t *fields, *f;
   1904       1.1  christos 
   1905       1.1  christos 	fields = type->of;
   1906       1.1  christos 	for (f = fields; f->name != NULL; f++) {
   1907      1.15  christos 		if ((f->flags & CFG_CLAUSEFLAG_NODOC) != 0) {
   1908      1.15  christos 			continue;
   1909      1.15  christos 		}
   1910       1.1  christos 		if (f != fields) {
   1911       1.1  christos 			cfg_print_cstr(pctx, " [ ");
   1912       1.1  christos 			cfg_print_cstr(pctx, f->name);
   1913       1.8  christos 			if (f->type->doc != cfg_doc_void) {
   1914       1.1  christos 				cfg_print_cstr(pctx, " ");
   1915       1.8  christos 			}
   1916       1.1  christos 		}
   1917       1.1  christos 		cfg_doc_obj(pctx, f->type);
   1918       1.8  christos 		if (f != fields) {
   1919       1.1  christos 			cfg_print_cstr(pctx, " ]");
   1920       1.8  christos 		}
   1921       1.1  christos 	}
   1922       1.1  christos }
   1923       1.1  christos 
   1924       1.8  christos static keyword_type_t zone_kw = { "zone", &cfg_type_astring };
   1925       1.8  christos static cfg_type_t cfg_type_rpz_zone = { "zone",		 parse_keyvalue,
   1926       1.8  christos 					print_keyvalue,	 doc_keyvalue,
   1927       1.8  christos 					&cfg_rep_string, &zone_kw };
   1928       1.1  christos /*
   1929       1.1  christos  * "no-op" is an obsolete equivalent of "passthru".
   1930       1.1  christos  */
   1931       1.8  christos static const char *rpz_policies[] = { "cname",	  "disabled", "drop",
   1932       1.8  christos 				      "given",	  "no-op",    "nodata",
   1933       1.8  christos 				      "nxdomain", "passthru", "tcp-only",
   1934       1.8  christos 				      NULL };
   1935       1.1  christos static cfg_type_t cfg_type_rpz_policy_name = {
   1936       1.8  christos 	"policy name",	cfg_parse_enum,	 cfg_print_ustring,
   1937       1.8  christos 	doc_rpz_policy, &cfg_rep_string, &rpz_policies
   1938       1.1  christos };
   1939       1.1  christos static cfg_type_t cfg_type_rpz_cname = {
   1940       1.1  christos 	"quoted_string", cfg_parse_astring, NULL,
   1941       1.8  christos 	doc_rpz_cname,	 &cfg_rep_string,   NULL
   1942       1.1  christos };
   1943       1.1  christos static cfg_tuplefielddef_t rpz_policy_fields[] = {
   1944       1.1  christos 	{ "policy name", &cfg_type_rpz_policy_name, 0 },
   1945       1.1  christos 	{ "cname", &cfg_type_rpz_cname, 0 },
   1946       1.1  christos 	{ NULL, NULL, 0 }
   1947       1.1  christos };
   1948       1.8  christos static cfg_type_t cfg_type_rpz_policy = { "policy tuple",  cfg_parse_rpz_policy,
   1949       1.8  christos 					  cfg_print_tuple, cfg_doc_tuple,
   1950       1.8  christos 					  &cfg_rep_tuple,  rpz_policy_fields };
   1951       1.1  christos static cfg_tuplefielddef_t rpz_zone_fields[] = {
   1952       1.1  christos 	{ "zone name", &cfg_type_rpz_zone, 0 },
   1953       1.5  christos 	{ "add-soa", &cfg_type_boolean, 0 },
   1954       1.1  christos 	{ "log", &cfg_type_boolean, 0 },
   1955       1.8  christos 	{ "max-policy-ttl", &cfg_type_duration, 0 },
   1956       1.8  christos 	{ "min-update-interval", &cfg_type_duration, 0 },
   1957       1.1  christos 	{ "policy", &cfg_type_rpz_policy, 0 },
   1958       1.1  christos 	{ "recursive-only", &cfg_type_boolean, 0 },
   1959       1.1  christos 	{ "nsip-enable", &cfg_type_boolean, 0 },
   1960       1.1  christos 	{ "nsdname-enable", &cfg_type_boolean, 0 },
   1961  1.15.2.1  perseant 	{ "ede", &cfg_type_ustring, 0 },
   1962       1.1  christos 	{ NULL, NULL, 0 }
   1963       1.1  christos };
   1964       1.8  christos static cfg_type_t cfg_type_rpz_tuple = { "rpz tuple",	     cfg_parse_kv_tuple,
   1965       1.8  christos 					 cfg_print_kv_tuple, cfg_doc_kv_tuple,
   1966       1.8  christos 					 &cfg_rep_tuple,     rpz_zone_fields };
   1967       1.8  christos static cfg_type_t cfg_type_rpz_list = { "zone list",
   1968       1.8  christos 					cfg_parse_bracketed_list,
   1969       1.8  christos 					cfg_print_bracketed_list,
   1970       1.8  christos 					cfg_doc_bracketed_list,
   1971       1.8  christos 					&cfg_rep_list,
   1972       1.8  christos 					&cfg_type_rpz_tuple };
   1973       1.1  christos static cfg_tuplefielddef_t rpz_fields[] = {
   1974       1.1  christos 	{ "zone list", &cfg_type_rpz_list, 0 },
   1975       1.5  christos 	{ "add-soa", &cfg_type_boolean, 0 },
   1976       1.1  christos 	{ "break-dnssec", &cfg_type_boolean, 0 },
   1977       1.8  christos 	{ "max-policy-ttl", &cfg_type_duration, 0 },
   1978       1.8  christos 	{ "min-update-interval", &cfg_type_duration, 0 },
   1979       1.1  christos 	{ "min-ns-dots", &cfg_type_uint32, 0 },
   1980       1.1  christos 	{ "nsip-wait-recurse", &cfg_type_boolean, 0 },
   1981      1.15  christos 	{ "nsdname-wait-recurse", &cfg_type_boolean, 0 },
   1982       1.1  christos 	{ "qname-wait-recurse", &cfg_type_boolean, 0 },
   1983       1.1  christos 	{ "recursive-only", &cfg_type_boolean, 0 },
   1984       1.1  christos 	{ "nsip-enable", &cfg_type_boolean, 0 },
   1985       1.1  christos 	{ "nsdname-enable", &cfg_type_boolean, 0 },
   1986       1.1  christos #ifdef USE_DNSRPS
   1987       1.1  christos 	{ "dnsrps-enable", &cfg_type_boolean, 0 },
   1988       1.1  christos 	{ "dnsrps-options", &cfg_type_bracketed_text, 0 },
   1989       1.8  christos #else  /* ifdef USE_DNSRPS */
   1990       1.1  christos 	{ "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
   1991       1.1  christos 	{ "dnsrps-options", &cfg_type_bracketed_text,
   1992       1.8  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   1993       1.8  christos #endif /* ifdef USE_DNSRPS */
   1994       1.1  christos 	{ NULL, NULL, 0 }
   1995       1.1  christos };
   1996       1.8  christos static cfg_type_t cfg_type_rpz = { "rpz",
   1997       1.8  christos 				   cfg_parse_kv_tuple,
   1998       1.8  christos 				   cfg_print_kv_tuple,
   1999       1.8  christos 				   cfg_doc_kv_tuple,
   2000       1.8  christos 				   &cfg_rep_tuple,
   2001       1.8  christos 				   rpz_fields };
   2002       1.1  christos 
   2003       1.1  christos /*
   2004       1.1  christos  * Catalog zones
   2005       1.1  christos  */
   2006       1.8  christos static cfg_type_t cfg_type_catz_zone = { "zone",	  parse_keyvalue,
   2007       1.8  christos 					 print_keyvalue,  doc_keyvalue,
   2008       1.8  christos 					 &cfg_rep_string, &zone_kw };
   2009       1.1  christos 
   2010       1.1  christos static cfg_tuplefielddef_t catz_zone_fields[] = {
   2011       1.1  christos 	{ "zone name", &cfg_type_catz_zone, 0 },
   2012      1.15  christos 	{ "default-masters", &cfg_type_namesockaddrkeylist,
   2013      1.15  christos 	  CFG_CLAUSEFLAG_NODOC },
   2014      1.15  christos 	{ "default-primaries", &cfg_type_namesockaddrkeylist, 0 },
   2015       1.1  christos 	{ "zone-directory", &cfg_type_qstring, 0 },
   2016       1.1  christos 	{ "in-memory", &cfg_type_boolean, 0 },
   2017       1.8  christos 	{ "min-update-interval", &cfg_type_duration, 0 },
   2018       1.1  christos 	{ NULL, NULL, 0 }
   2019       1.1  christos };
   2020       1.1  christos static cfg_type_t cfg_type_catz_tuple = {
   2021       1.8  christos 	"catz tuple",	  cfg_parse_kv_tuple, cfg_print_kv_tuple,
   2022       1.8  christos 	cfg_doc_kv_tuple, &cfg_rep_tuple,     catz_zone_fields
   2023       1.1  christos };
   2024       1.8  christos static cfg_type_t cfg_type_catz_list = { "zone list",
   2025       1.8  christos 					 cfg_parse_bracketed_list,
   2026       1.8  christos 					 cfg_print_bracketed_list,
   2027       1.8  christos 					 cfg_doc_bracketed_list,
   2028       1.8  christos 					 &cfg_rep_list,
   2029       1.8  christos 					 &cfg_type_catz_tuple };
   2030       1.1  christos static cfg_tuplefielddef_t catz_fields[] = {
   2031       1.8  christos 	{ "zone list", &cfg_type_catz_list, 0 }, { NULL, NULL, 0 }
   2032       1.1  christos };
   2033       1.1  christos static cfg_type_t cfg_type_catz = {
   2034       1.8  christos 	"catz",		  cfg_parse_kv_tuple, cfg_print_kv_tuple,
   2035       1.8  christos 	cfg_doc_kv_tuple, &cfg_rep_tuple,     catz_fields
   2036       1.1  christos };
   2037       1.1  christos 
   2038       1.1  christos /*
   2039       1.1  christos  * rate-limit
   2040       1.1  christos  */
   2041       1.1  christos static cfg_clausedef_t rrl_clauses[] = {
   2042       1.1  christos 	{ "all-per-second", &cfg_type_uint32, 0 },
   2043       1.1  christos 	{ "errors-per-second", &cfg_type_uint32, 0 },
   2044       1.1  christos 	{ "exempt-clients", &cfg_type_bracketed_aml, 0 },
   2045       1.1  christos 	{ "ipv4-prefix-length", &cfg_type_uint32, 0 },
   2046       1.1  christos 	{ "ipv6-prefix-length", &cfg_type_uint32, 0 },
   2047       1.1  christos 	{ "log-only", &cfg_type_boolean, 0 },
   2048       1.1  christos 	{ "max-table-size", &cfg_type_uint32, 0 },
   2049       1.1  christos 	{ "min-table-size", &cfg_type_uint32, 0 },
   2050       1.1  christos 	{ "nodata-per-second", &cfg_type_uint32, 0 },
   2051       1.1  christos 	{ "nxdomains-per-second", &cfg_type_uint32, 0 },
   2052       1.1  christos 	{ "qps-scale", &cfg_type_uint32, 0 },
   2053       1.1  christos 	{ "referrals-per-second", &cfg_type_uint32, 0 },
   2054       1.1  christos 	{ "responses-per-second", &cfg_type_uint32, 0 },
   2055       1.1  christos 	{ "slip", &cfg_type_uint32, 0 },
   2056       1.1  christos 	{ "window", &cfg_type_uint32, 0 },
   2057       1.1  christos 	{ NULL, NULL, 0 }
   2058       1.1  christos };
   2059       1.1  christos 
   2060       1.8  christos static cfg_clausedef_t *rrl_clausesets[] = { rrl_clauses, NULL };
   2061       1.1  christos 
   2062       1.8  christos static cfg_type_t cfg_type_rrl = { "rate-limit", cfg_parse_map, cfg_print_map,
   2063       1.8  christos 				   cfg_doc_map,	 &cfg_rep_map,	rrl_clausesets };
   2064       1.1  christos 
   2065       1.1  christos static isc_result_t
   2066       1.1  christos parse_optional_uint32(cfg_parser_t *pctx, const cfg_type_t *type,
   2067       1.8  christos 		      cfg_obj_t **ret) {
   2068       1.1  christos 	isc_result_t result;
   2069       1.1  christos 	UNUSED(type);
   2070       1.1  christos 
   2071       1.1  christos 	CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
   2072       1.1  christos 	if (pctx->token.type == isc_tokentype_number) {
   2073       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_uint32, ret));
   2074       1.1  christos 	} else {
   2075       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
   2076       1.1  christos 	}
   2077       1.8  christos cleanup:
   2078  1.15.2.1  perseant 	return result;
   2079       1.1  christos }
   2080       1.1  christos 
   2081       1.1  christos static void
   2082       1.1  christos doc_optional_uint32(cfg_printer_t *pctx, const cfg_type_t *type) {
   2083       1.1  christos 	UNUSED(type);
   2084       1.1  christos 	cfg_print_cstr(pctx, "[ <integer> ]");
   2085       1.1  christos }
   2086       1.1  christos 
   2087       1.8  christos static cfg_type_t cfg_type_optional_uint32 = { "optional_uint32",
   2088       1.8  christos 					       parse_optional_uint32,
   2089       1.8  christos 					       NULL,
   2090       1.8  christos 					       doc_optional_uint32,
   2091       1.8  christos 					       NULL,
   2092       1.8  christos 					       NULL };
   2093       1.1  christos 
   2094       1.1  christos static cfg_tuplefielddef_t prefetch_fields[] = {
   2095       1.1  christos 	{ "trigger", &cfg_type_uint32, 0 },
   2096       1.1  christos 	{ "eligible", &cfg_type_optional_uint32, 0 },
   2097       1.1  christos 	{ NULL, NULL, 0 }
   2098       1.1  christos };
   2099       1.1  christos 
   2100       1.8  christos static cfg_type_t cfg_type_prefetch = { "prefetch",	 cfg_parse_tuple,
   2101       1.8  christos 					cfg_print_tuple, cfg_doc_tuple,
   2102       1.8  christos 					&cfg_rep_tuple,	 prefetch_fields };
   2103       1.1  christos /*
   2104       1.1  christos  * DNS64.
   2105       1.1  christos  */
   2106       1.8  christos static cfg_clausedef_t dns64_clauses[] = {
   2107       1.1  christos 	{ "break-dnssec", &cfg_type_boolean, 0 },
   2108       1.1  christos 	{ "clients", &cfg_type_bracketed_aml, 0 },
   2109       1.1  christos 	{ "exclude", &cfg_type_bracketed_aml, 0 },
   2110       1.1  christos 	{ "mapped", &cfg_type_bracketed_aml, 0 },
   2111       1.1  christos 	{ "recursive-only", &cfg_type_boolean, 0 },
   2112       1.1  christos 	{ "suffix", &cfg_type_netaddr6, 0 },
   2113       1.1  christos 	{ NULL, NULL, 0 },
   2114       1.1  christos };
   2115       1.1  christos 
   2116       1.8  christos static cfg_clausedef_t *dns64_clausesets[] = { dns64_clauses, NULL };
   2117       1.1  christos 
   2118       1.8  christos static cfg_type_t cfg_type_dns64 = { "dns64",	    cfg_parse_netprefix_map,
   2119       1.8  christos 				     cfg_print_map, cfg_doc_map,
   2120       1.8  christos 				     &cfg_rep_map,  dns64_clausesets };
   2121       1.1  christos 
   2122       1.9  christos static const char *staleanswerclienttimeout_enums[] = { "disabled", "off",
   2123       1.9  christos 							NULL };
   2124       1.9  christos static isc_result_t
   2125       1.9  christos parse_staleanswerclienttimeout(cfg_parser_t *pctx, const cfg_type_t *type,
   2126       1.9  christos 			       cfg_obj_t **ret) {
   2127  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_uint32, ret);
   2128       1.9  christos }
   2129       1.9  christos 
   2130       1.9  christos static void
   2131       1.9  christos doc_staleanswerclienttimeout(cfg_printer_t *pctx, const cfg_type_t *type) {
   2132       1.9  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_uint32);
   2133       1.9  christos }
   2134       1.9  christos 
   2135       1.9  christos static cfg_type_t cfg_type_staleanswerclienttimeout = {
   2136       1.9  christos 	"staleanswerclienttimeout",
   2137       1.9  christos 	parse_staleanswerclienttimeout,
   2138       1.9  christos 	cfg_print_ustring,
   2139       1.9  christos 	doc_staleanswerclienttimeout,
   2140       1.9  christos 	&cfg_rep_string,
   2141       1.9  christos 	staleanswerclienttimeout_enums
   2142       1.9  christos };
   2143       1.9  christos 
   2144       1.1  christos /*%
   2145       1.1  christos  * Clauses that can be found within the 'view' statement,
   2146       1.1  christos  * with defaults in the 'options' statement.
   2147       1.1  christos  */
   2148       1.1  christos 
   2149       1.8  christos static cfg_clausedef_t view_clauses[] = {
   2150      1.15  christos 	{ "acache-cleaning-interval", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2151      1.15  christos 	{ "acache-enable", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2152      1.15  christos 	{ "additional-from-auth", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2153      1.15  christos 	{ "additional-from-cache", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2154       1.1  christos 	{ "allow-new-zones", &cfg_type_boolean, 0 },
   2155  1.15.2.1  perseant 	{ "allow-proxy", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_EXPERIMENTAL },
   2156  1.15.2.1  perseant 	{ "allow-proxy-on", &cfg_type_bracketed_aml,
   2157  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_EXPERIMENTAL },
   2158       1.1  christos 	{ "allow-query-cache", &cfg_type_bracketed_aml, 0 },
   2159       1.1  christos 	{ "allow-query-cache-on", &cfg_type_bracketed_aml, 0 },
   2160       1.1  christos 	{ "allow-recursion", &cfg_type_bracketed_aml, 0 },
   2161       1.1  christos 	{ "allow-recursion-on", &cfg_type_bracketed_aml, 0 },
   2162      1.15  christos 	{ "allow-v6-synthesis", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2163       1.1  christos 	{ "attach-cache", &cfg_type_astring, 0 },
   2164      1.15  christos 	{ "auth-nxdomain", &cfg_type_boolean, 0 },
   2165      1.15  christos 	{ "cache-file", &cfg_type_qstring, CFG_CLAUSEFLAG_ANCIENT },
   2166       1.1  christos 	{ "catalog-zones", &cfg_type_catz, 0 },
   2167       1.1  christos 	{ "check-names", &cfg_type_checknames, CFG_CLAUSEFLAG_MULTI },
   2168      1.15  christos 	{ "cleaning-interval", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2169       1.1  christos 	{ "clients-per-query", &cfg_type_uint32, 0 },
   2170       1.1  christos 	{ "deny-answer-addresses", &cfg_type_denyaddresses, 0 },
   2171       1.1  christos 	{ "deny-answer-aliases", &cfg_type_denyaliases, 0 },
   2172       1.1  christos 	{ "disable-algorithms", &cfg_type_disablealgorithm,
   2173       1.1  christos 	  CFG_CLAUSEFLAG_MULTI },
   2174       1.1  christos 	{ "disable-ds-digests", &cfg_type_disabledsdigest,
   2175       1.1  christos 	  CFG_CLAUSEFLAG_MULTI },
   2176       1.1  christos 	{ "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
   2177       1.1  christos 	{ "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
   2178       1.1  christos 	{ "dns64-contact", &cfg_type_astring, 0 },
   2179       1.1  christos 	{ "dns64-server", &cfg_type_astring, 0 },
   2180       1.1  christos #ifdef USE_DNSRPS
   2181       1.1  christos 	{ "dnsrps-enable", &cfg_type_boolean, 0 },
   2182       1.1  christos 	{ "dnsrps-options", &cfg_type_bracketed_text, 0 },
   2183       1.8  christos #else  /* ifdef USE_DNSRPS */
   2184       1.1  christos 	{ "dnsrps-enable", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTCONFIGURED },
   2185       1.1  christos 	{ "dnsrps-options", &cfg_type_bracketed_text,
   2186       1.8  christos 	  CFG_CLAUSEFLAG_NOTCONFIGURED },
   2187       1.8  christos #endif /* ifdef USE_DNSRPS */
   2188       1.1  christos 	{ "dnssec-accept-expired", &cfg_type_boolean, 0 },
   2189      1.15  christos 	{ "dnssec-enable", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2190      1.15  christos 	{ "dnssec-lookaside", NULL,
   2191      1.15  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_ANCIENT },
   2192       1.8  christos 	{ "dnssec-must-be-secure", &cfg_type_mustbesecure,
   2193      1.15  christos 	  CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_DEPRECATED },
   2194       1.1  christos 	{ "dnssec-validation", &cfg_type_boolorauto, 0 },
   2195       1.1  christos #ifdef HAVE_DNSTAP
   2196       1.1  christos 	{ "dnstap", &cfg_type_dnstap, 0 },
   2197       1.8  christos #else  /* ifdef HAVE_DNSTAP */
   2198       1.1  christos 	{ "dnstap", &cfg_type_dnstap, CFG_CLAUSEFLAG_NOTCONFIGURED },
   2199       1.1  christos #endif /* HAVE_DNSTAP */
   2200       1.1  christos 	{ "dual-stack-servers", &cfg_type_nameportiplist, 0 },
   2201       1.1  christos 	{ "edns-udp-size", &cfg_type_uint32, 0 },
   2202       1.1  christos 	{ "empty-contact", &cfg_type_astring, 0 },
   2203       1.1  christos 	{ "empty-server", &cfg_type_astring, 0 },
   2204       1.1  christos 	{ "empty-zones-enable", &cfg_type_boolean, 0 },
   2205      1.15  christos 	{ "fetch-glue", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2206       1.1  christos 	{ "fetch-quota-params", &cfg_type_fetchquota, 0 },
   2207       1.1  christos 	{ "fetches-per-server", &cfg_type_fetchesper, 0 },
   2208       1.1  christos 	{ "fetches-per-zone", &cfg_type_fetchesper, 0 },
   2209      1.15  christos 	{ "filter-aaaa", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_ANCIENT },
   2210      1.15  christos 	{ "filter-aaaa-on-v4", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT },
   2211      1.15  christos 	{ "filter-aaaa-on-v6", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT },
   2212  1.15.2.1  perseant 	{ "glue-cache", &cfg_type_boolean, CFG_CLAUSEFLAG_ANCIENT },
   2213      1.15  christos 	{ "ipv4only-enable", &cfg_type_boolean, 0 },
   2214      1.15  christos 	{ "ipv4only-contact", &cfg_type_astring, 0 },
   2215      1.15  christos 	{ "ipv4only-server", &cfg_type_astring, 0 },
   2216       1.1  christos 	{ "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
   2217       1.8  christos 	{ "lame-ttl", &cfg_type_duration, 0 },
   2218       1.1  christos #ifdef HAVE_LMDB
   2219       1.1  christos 	{ "lmdb-mapsize", &cfg_type_sizeval, 0 },
   2220       1.8  christos #else  /* ifdef HAVE_LMDB */
   2221      1.15  christos 	{ "lmdb-mapsize", &cfg_type_sizeval, CFG_CLAUSEFLAG_NOTCONFIGURED },
   2222       1.8  christos #endif /* ifdef HAVE_LMDB */
   2223      1.15  christos 	{ "max-acache-size", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2224       1.1  christos 	{ "max-cache-size", &cfg_type_sizeorpercent, 0 },
   2225       1.8  christos 	{ "max-cache-ttl", &cfg_type_duration, 0 },
   2226       1.1  christos 	{ "max-clients-per-query", &cfg_type_uint32, 0 },
   2227       1.8  christos 	{ "max-ncache-ttl", &cfg_type_duration, 0 },
   2228       1.1  christos 	{ "max-recursion-depth", &cfg_type_uint32, 0 },
   2229       1.1  christos 	{ "max-recursion-queries", &cfg_type_uint32, 0 },
   2230  1.15.2.1  perseant 	{ "max-query-count", &cfg_type_uint32, 0 },
   2231  1.15.2.1  perseant 	{ "max-query-restarts", &cfg_type_uint32, 0 },
   2232       1.8  christos 	{ "max-stale-ttl", &cfg_type_duration, 0 },
   2233       1.1  christos 	{ "max-udp-size", &cfg_type_uint32, 0 },
   2234  1.15.2.1  perseant 	{ "max-validations-per-fetch", &cfg_type_uint32,
   2235  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_EXPERIMENTAL },
   2236  1.15.2.1  perseant 	{ "max-validation-failures-per-fetch", &cfg_type_uint32,
   2237  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_EXPERIMENTAL },
   2238       1.1  christos 	{ "message-compression", &cfg_type_boolean, 0 },
   2239       1.8  christos 	{ "min-cache-ttl", &cfg_type_duration, 0 },
   2240       1.8  christos 	{ "min-ncache-ttl", &cfg_type_duration, 0 },
   2241      1.15  christos 	{ "min-roots", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2242       1.1  christos 	{ "minimal-any", &cfg_type_boolean, 0 },
   2243       1.1  christos 	{ "minimal-responses", &cfg_type_minimal, 0 },
   2244       1.1  christos 	{ "new-zones-directory", &cfg_type_qstring, 0 },
   2245       1.1  christos 	{ "no-case-compress", &cfg_type_bracketed_aml, 0 },
   2246       1.1  christos 	{ "nocookie-udp-size", &cfg_type_uint32, 0 },
   2247      1.15  christos 	{ "nosit-udp-size", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2248       1.8  christos 	{ "nta-lifetime", &cfg_type_duration, 0 },
   2249       1.8  christos 	{ "nta-recheck", &cfg_type_duration, 0 },
   2250       1.1  christos 	{ "nxdomain-redirect", &cfg_type_astring, 0 },
   2251       1.1  christos 	{ "preferred-glue", &cfg_type_astring, 0 },
   2252       1.1  christos 	{ "prefetch", &cfg_type_prefetch, 0 },
   2253       1.1  christos 	{ "provide-ixfr", &cfg_type_boolean, 0 },
   2254       1.3  christos 	{ "qname-minimization", &cfg_type_qminmethod, 0 },
   2255       1.1  christos 	/*
   2256       1.1  christos 	 * Note that the query-source option syntax is different
   2257       1.1  christos 	 * from the other -source options.
   2258       1.1  christos 	 */
   2259       1.1  christos 	{ "query-source", &cfg_type_querysource4, 0 },
   2260       1.1  christos 	{ "query-source-v6", &cfg_type_querysource6, 0 },
   2261      1.15  christos 	{ "queryport-pool-ports", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2262      1.15  christos 	{ "queryport-pool-updateinterval", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2263       1.1  christos 	{ "rate-limit", &cfg_type_rrl, 0 },
   2264       1.1  christos 	{ "recursion", &cfg_type_boolean, 0 },
   2265       1.1  christos 	{ "request-nsid", &cfg_type_boolean, 0 },
   2266      1.15  christos 	{ "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2267       1.1  christos 	{ "require-server-cookie", &cfg_type_boolean, 0 },
   2268      1.15  christos 	{ "resolver-nonbackoff-tries", &cfg_type_uint32,
   2269  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_ANCIENT },
   2270       1.1  christos 	{ "resolver-query-timeout", &cfg_type_uint32, 0 },
   2271  1.15.2.1  perseant 	{ "resolver-retry-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_ANCIENT },
   2272       1.1  christos 	{ "response-padding", &cfg_type_resppadding, 0 },
   2273       1.1  christos 	{ "response-policy", &cfg_type_rpz, 0 },
   2274      1.15  christos 	{ "rfc2308-type1", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2275      1.15  christos 	{ "root-delegation-only", &cfg_type_optional_exclude,
   2276  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_ANCIENT },
   2277       1.1  christos 	{ "root-key-sentinel", &cfg_type_boolean, 0 },
   2278       1.1  christos 	{ "rrset-order", &cfg_type_rrsetorder, 0 },
   2279       1.1  christos 	{ "send-cookie", &cfg_type_boolean, 0 },
   2280       1.8  christos 	{ "servfail-ttl", &cfg_type_duration, 0 },
   2281  1.15.2.1  perseant 	{ "sig0key-checks-limit", &cfg_type_uint32, 0 },
   2282  1.15.2.1  perseant 	{ "sig0message-checks-limit", &cfg_type_uint32, 0 },
   2283  1.15.2.1  perseant 	{ "sortlist", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_DEPRECATED },
   2284       1.1  christos 	{ "stale-answer-enable", &cfg_type_boolean, 0 },
   2285       1.9  christos 	{ "stale-answer-client-timeout", &cfg_type_staleanswerclienttimeout,
   2286       1.9  christos 	  0 },
   2287       1.8  christos 	{ "stale-answer-ttl", &cfg_type_duration, 0 },
   2288       1.9  christos 	{ "stale-cache-enable", &cfg_type_boolean, 0 },
   2289       1.9  christos 	{ "stale-refresh-time", &cfg_type_duration, 0 },
   2290      1.15  christos 	{ "suppress-initial-notify", &cfg_type_boolean,
   2291  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_ANCIENT },
   2292       1.1  christos 	{ "synth-from-dnssec", &cfg_type_boolean, 0 },
   2293      1.15  christos 	{ "topology", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2294       1.1  christos 	{ "transfer-format", &cfg_type_transferformat, 0 },
   2295      1.15  christos 	{ "trust-anchor-telemetry", &cfg_type_boolean, 0 },
   2296  1.15.2.1  perseant 	{ "resolver-use-dns64", &cfg_type_boolean, 0 },
   2297      1.15  christos 	{ "use-queryport-pool", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2298       1.3  christos 	{ "validate-except", &cfg_type_namelist, 0 },
   2299       1.1  christos 	{ "v6-bias", &cfg_type_uint32, 0 },
   2300       1.1  christos 	{ "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
   2301       1.1  christos 	{ NULL, NULL, 0 }
   2302       1.1  christos };
   2303       1.1  christos 
   2304       1.1  christos /*%
   2305       1.1  christos  * Clauses that can be found within the 'view' statement only.
   2306       1.1  christos  */
   2307       1.8  christos static cfg_clausedef_t view_only_clauses[] = {
   2308       1.1  christos 	{ "match-clients", &cfg_type_bracketed_aml, 0 },
   2309       1.1  christos 	{ "match-destinations", &cfg_type_bracketed_aml, 0 },
   2310       1.1  christos 	{ "match-recursive-only", &cfg_type_boolean, 0 },
   2311       1.1  christos 	{ NULL, NULL, 0 }
   2312       1.1  christos };
   2313       1.1  christos 
   2314       1.1  christos /*%
   2315       1.1  christos  * Sig-validity-interval.
   2316       1.1  christos  */
   2317       1.1  christos 
   2318       1.1  christos static cfg_tuplefielddef_t validityinterval_fields[] = {
   2319       1.1  christos 	{ "validity", &cfg_type_uint32, 0 },
   2320       1.1  christos 	{ "re-sign", &cfg_type_optional_uint32, 0 },
   2321       1.1  christos 	{ NULL, NULL, 0 }
   2322       1.1  christos };
   2323       1.1  christos 
   2324       1.1  christos static cfg_type_t cfg_type_validityinterval = {
   2325       1.8  christos 	"validityinterval", cfg_parse_tuple, cfg_print_tuple,
   2326       1.8  christos 	cfg_doc_tuple,	    &cfg_rep_tuple,  validityinterval_fields
   2327       1.8  christos };
   2328       1.8  christos 
   2329       1.8  christos /*%
   2330  1.15.2.1  perseant  * Checkds type.
   2331  1.15.2.1  perseant  */
   2332  1.15.2.1  perseant static const char *checkds_enums[] = { "explicit", NULL };
   2333  1.15.2.1  perseant static isc_result_t
   2334  1.15.2.1  perseant parse_checkds_type(cfg_parser_t *pctx, const cfg_type_t *type,
   2335  1.15.2.1  perseant 		   cfg_obj_t **ret) {
   2336  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   2337  1.15.2.1  perseant }
   2338  1.15.2.1  perseant static void
   2339  1.15.2.1  perseant doc_checkds_type(cfg_printer_t *pctx, const cfg_type_t *type) {
   2340  1.15.2.1  perseant 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   2341  1.15.2.1  perseant }
   2342  1.15.2.1  perseant static cfg_type_t cfg_type_checkdstype = {
   2343  1.15.2.1  perseant 	"checkdstype",	  parse_checkds_type, cfg_print_ustring,
   2344  1.15.2.1  perseant 	doc_checkds_type, &cfg_rep_string,    checkds_enums,
   2345  1.15.2.1  perseant };
   2346  1.15.2.1  perseant 
   2347  1.15.2.1  perseant /*%
   2348       1.8  christos  * Clauses that can be found in a 'dnssec-policy' statement.
   2349       1.8  christos  */
   2350       1.8  christos static cfg_clausedef_t dnssecpolicy_clauses[] = {
   2351  1.15.2.1  perseant 	{ "cdnskey", &cfg_type_boolean, 0 },
   2352  1.15.2.1  perseant 	{ "cds-digest-types", &cfg_type_algorithmlist, 0 },
   2353       1.8  christos 	{ "dnskey-ttl", &cfg_type_duration, 0 },
   2354  1.15.2.1  perseant 	{ "inline-signing", &cfg_type_boolean, 0 },
   2355       1.8  christos 	{ "keys", &cfg_type_kaspkeys, 0 },
   2356       1.8  christos 	{ "max-zone-ttl", &cfg_type_duration, 0 },
   2357       1.9  christos 	{ "nsec3param", &cfg_type_nsec3, 0 },
   2358  1.15.2.1  perseant 	{ "offline-ksk", &cfg_type_boolean, 0 },
   2359       1.8  christos 	{ "parent-ds-ttl", &cfg_type_duration, 0 },
   2360       1.8  christos 	{ "parent-propagation-delay", &cfg_type_duration, 0 },
   2361       1.9  christos 	{ "parent-registration-delay", &cfg_type_duration,
   2362  1.15.2.1  perseant 	  CFG_CLAUSEFLAG_ANCIENT },
   2363       1.8  christos 	{ "publish-safety", &cfg_type_duration, 0 },
   2364      1.11  christos 	{ "purge-keys", &cfg_type_duration, 0 },
   2365       1.8  christos 	{ "retire-safety", &cfg_type_duration, 0 },
   2366  1.15.2.1  perseant 	{ "signatures-jitter", &cfg_type_duration, 0 },
   2367       1.8  christos 	{ "signatures-refresh", &cfg_type_duration, 0 },
   2368       1.8  christos 	{ "signatures-validity", &cfg_type_duration, 0 },
   2369       1.8  christos 	{ "signatures-validity-dnskey", &cfg_type_duration, 0 },
   2370       1.8  christos 	{ "zone-propagation-delay", &cfg_type_duration, 0 },
   2371       1.8  christos 	{ NULL, NULL, 0 }
   2372       1.1  christos };
   2373       1.1  christos 
   2374  1.15.2.1  perseant /*
   2375  1.15.2.1  perseant  * For min-transfer-rate-in.
   2376  1.15.2.1  perseant  */
   2377  1.15.2.1  perseant static cfg_tuplefielddef_t min_transfer_rate_fields[] = {
   2378  1.15.2.1  perseant 	{ "traffic_bytes", &cfg_type_uint32, 0 },
   2379  1.15.2.1  perseant 	{ "time_minutes", &cfg_type_uint32, 0 },
   2380  1.15.2.1  perseant 	{ NULL, NULL, 0 }
   2381  1.15.2.1  perseant };
   2382  1.15.2.1  perseant 
   2383  1.15.2.1  perseant static cfg_type_t cfg_type_min_transfer_rate_in = {
   2384  1.15.2.1  perseant 	"min-transfer-rate-in", cfg_parse_tuple, cfg_print_tuple,
   2385  1.15.2.1  perseant 	cfg_doc_tuple,		&cfg_rep_tuple,	 min_transfer_rate_fields
   2386  1.15.2.1  perseant };
   2387  1.15.2.1  perseant 
   2388       1.1  christos /*%
   2389       1.1  christos  * Clauses that can be found in a 'zone' statement,
   2390       1.1  christos  * with defaults in the 'view' or 'options' statement.
   2391       1.1  christos  *
   2392       1.1  christos  * Note: CFG_ZONE_* options indicate in which zone types this clause is
   2393       1.1  christos  * legal.
   2394       1.1  christos  */
   2395      1.15  christos /*
   2396      1.15  christos  * NOTE: To enable syntax which allows specifying port and protocol
   2397      1.15  christos  * within 'allow-*' clauses, replace 'cfg_type_bracketed_aml' with
   2398      1.15  christos  * 'cfg_type_transport_acl'.
   2399      1.15  christos  *
   2400      1.15  christos  * Example: allow-transfer port 853 protocol tls { ... };
   2401      1.15  christos  */
   2402       1.8  christos static cfg_clausedef_t zone_clauses[] = {
   2403       1.1  christos 	{ "allow-notify", &cfg_type_bracketed_aml,
   2404      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2405       1.1  christos 	{ "allow-query", &cfg_type_bracketed_aml,
   2406      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2407      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB },
   2408       1.1  christos 	{ "allow-query-on", &cfg_type_bracketed_aml,
   2409      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2410      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_REDIRECT | CFG_ZONE_STATICSTUB },
   2411      1.15  christos 	{ "allow-transfer", &cfg_type_transport_acl,
   2412      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2413      1.13  christos 	{ "allow-update", &cfg_type_bracketed_aml, CFG_ZONE_PRIMARY },
   2414       1.1  christos 	{ "allow-update-forwarding", &cfg_type_bracketed_aml,
   2415      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2416       1.1  christos 	{ "also-notify", &cfg_type_namesockaddrkeylist,
   2417      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2418       1.1  christos 	{ "alt-transfer-source", &cfg_type_sockaddr4wild,
   2419      1.15  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2420  1.15.2.1  perseant 		  CFG_CLAUSEFLAG_ANCIENT },
   2421       1.1  christos 	{ "alt-transfer-source-v6", &cfg_type_sockaddr6wild,
   2422      1.15  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2423  1.15.2.1  perseant 		  CFG_CLAUSEFLAG_ANCIENT },
   2424       1.1  christos 	{ "auto-dnssec", &cfg_type_autodnssec,
   2425  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_ANCIENT },
   2426      1.13  christos 	{ "check-dup-records", &cfg_type_checkmode, CFG_ZONE_PRIMARY },
   2427      1.13  christos 	{ "check-integrity", &cfg_type_boolean, CFG_ZONE_PRIMARY },
   2428      1.13  christos 	{ "check-mx", &cfg_type_checkmode, CFG_ZONE_PRIMARY },
   2429      1.13  christos 	{ "check-mx-cname", &cfg_type_checkmode, CFG_ZONE_PRIMARY },
   2430      1.13  christos 	{ "check-sibling", &cfg_type_boolean, CFG_ZONE_PRIMARY },
   2431      1.13  christos 	{ "check-spf", &cfg_type_warn, CFG_ZONE_PRIMARY },
   2432      1.13  christos 	{ "check-srv-cname", &cfg_type_checkmode, CFG_ZONE_PRIMARY },
   2433  1.15.2.1  perseant 	{ "check-svcb", &cfg_type_boolean, CFG_ZONE_PRIMARY },
   2434      1.13  christos 	{ "check-wildcard", &cfg_type_boolean, CFG_ZONE_PRIMARY },
   2435       1.1  christos 	{ "dialup", &cfg_type_dialuptype,
   2436      1.15  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_STUB |
   2437      1.15  christos 		  CFG_CLAUSEFLAG_DEPRECATED },
   2438       1.1  christos 	{ "dnssec-dnskey-kskonly", &cfg_type_boolean,
   2439  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_OBSOLETE },
   2440       1.1  christos 	{ "dnssec-loadkeys-interval", &cfg_type_uint32,
   2441      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2442       1.8  christos 	{ "dnssec-policy", &cfg_type_astring,
   2443      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2444  1.15.2.1  perseant 	{ "dnssec-secure-to-insecure", &cfg_type_boolean,
   2445  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_CLAUSEFLAG_OBSOLETE },
   2446       1.1  christos 	{ "dnssec-update-mode", &cfg_type_dnssecupdatemode,
   2447  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_OBSOLETE },
   2448       1.1  christos 	{ "forward", &cfg_type_forwardtype,
   2449      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_STUB |
   2450       1.8  christos 		  CFG_ZONE_STATICSTUB | CFG_ZONE_FORWARD },
   2451       1.1  christos 	{ "forwarders", &cfg_type_portiplist,
   2452      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_STUB |
   2453       1.8  christos 		  CFG_ZONE_STATICSTUB | CFG_ZONE_FORWARD },
   2454       1.1  christos 	{ "key-directory", &cfg_type_qstring,
   2455      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2456      1.15  christos 	{ "maintain-ixfr-base", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2457       1.1  christos 	{ "masterfile-format", &cfg_type_masterformat,
   2458      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2459      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_REDIRECT },
   2460       1.1  christos 	{ "masterfile-style", &cfg_type_masterstyle,
   2461      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2462      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_REDIRECT },
   2463      1.15  christos 	{ "max-ixfr-log-size", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2464       1.9  christos 	{ "max-ixfr-ratio", &cfg_type_ixfrratio,
   2465      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2466       1.1  christos 	{ "max-journal-size", &cfg_type_size,
   2467      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2468       1.1  christos 	{ "max-records", &cfg_type_uint32,
   2469      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2470      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
   2471  1.15.2.1  perseant 	{ "max-records-per-type", &cfg_type_uint32,
   2472  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2473  1.15.2.1  perseant 		  CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
   2474  1.15.2.1  perseant 	{ "max-types-per-name", &cfg_type_uint32,
   2475  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2476  1.15.2.1  perseant 		  CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
   2477       1.1  christos 	{ "max-refresh-time", &cfg_type_uint32,
   2478      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2479       1.1  christos 	{ "max-retry-time", &cfg_type_uint32,
   2480      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2481  1.15.2.1  perseant 	{ "min-transfer-rate-in", &cfg_type_min_transfer_rate_in,
   2482  1.15.2.1  perseant 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2483       1.1  christos 	{ "max-transfer-idle-in", &cfg_type_uint32,
   2484      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2485       1.1  christos 	{ "max-transfer-idle-out", &cfg_type_uint32,
   2486      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_MIRROR | CFG_ZONE_SECONDARY },
   2487       1.1  christos 	{ "max-transfer-time-in", &cfg_type_uint32,
   2488      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2489       1.1  christos 	{ "max-transfer-time-out", &cfg_type_uint32,
   2490      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_MIRROR | CFG_ZONE_SECONDARY },
   2491       1.8  christos 	{ "max-zone-ttl", &cfg_type_maxduration,
   2492  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_REDIRECT | CFG_CLAUSEFLAG_DEPRECATED },
   2493       1.1  christos 	{ "min-refresh-time", &cfg_type_uint32,
   2494      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2495       1.1  christos 	{ "min-retry-time", &cfg_type_uint32,
   2496      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2497       1.1  christos 	{ "multi-master", &cfg_type_boolean,
   2498      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2499       1.1  christos 	{ "notify", &cfg_type_notifytype,
   2500      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2501  1.15.2.1  perseant 	{ "notify-defer", &cfg_type_uint32,
   2502  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2503       1.1  christos 	{ "notify-delay", &cfg_type_uint32,
   2504      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2505       1.1  christos 	{ "notify-source", &cfg_type_sockaddr4wild,
   2506      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2507       1.1  christos 	{ "notify-source-v6", &cfg_type_sockaddr6wild,
   2508      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2509       1.1  christos 	{ "notify-to-soa", &cfg_type_boolean,
   2510      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2511       1.1  christos 	{ "nsec3-test-zone", &cfg_type_boolean,
   2512      1.13  christos 	  CFG_CLAUSEFLAG_TESTONLY | CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2513      1.12  christos 	{ "parental-source", &cfg_type_sockaddr4wild,
   2514      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2515      1.12  christos 	{ "parental-source-v6", &cfg_type_sockaddr6wild,
   2516      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2517       1.1  christos 	{ "request-expire", &cfg_type_boolean,
   2518      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2519      1.13  christos 	{ "request-ixfr", &cfg_type_boolean,
   2520      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2521      1.13  christos 	{ "serial-update-method", &cfg_type_updatemethod, CFG_ZONE_PRIMARY },
   2522       1.1  christos 	{ "sig-signing-nodes", &cfg_type_uint32,
   2523      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2524       1.1  christos 	{ "sig-signing-signatures", &cfg_type_uint32,
   2525      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2526       1.1  christos 	{ "sig-signing-type", &cfg_type_uint32,
   2527      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2528       1.1  christos 	{ "sig-validity-interval", &cfg_type_validityinterval,
   2529  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_OBSOLETE },
   2530       1.3  christos 	{ "dnskey-sig-validity", &cfg_type_uint32,
   2531  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_OBSOLETE },
   2532       1.1  christos 	{ "transfer-source", &cfg_type_sockaddr4wild,
   2533      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2534       1.1  christos 	{ "transfer-source-v6", &cfg_type_sockaddr6wild,
   2535      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
   2536       1.1  christos 	{ "try-tcp-refresh", &cfg_type_boolean,
   2537      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2538       1.1  christos 	{ "update-check-ksk", &cfg_type_boolean,
   2539  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_CLAUSEFLAG_OBSOLETE },
   2540       1.1  christos 	{ "use-alt-transfer-source", &cfg_type_boolean,
   2541      1.15  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB |
   2542  1.15.2.1  perseant 		  CFG_CLAUSEFLAG_ANCIENT },
   2543       1.1  christos 	{ "zero-no-soa-ttl", &cfg_type_boolean,
   2544      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2545       1.1  christos 	{ "zone-statistics", &cfg_type_zonestat,
   2546      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2547      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
   2548       1.1  christos 	{ NULL, NULL, 0 }
   2549       1.1  christos };
   2550       1.1  christos 
   2551       1.1  christos /*%
   2552       1.1  christos  * Clauses that can be found in a 'zone' statement only.
   2553       1.1  christos  *
   2554       1.1  christos  * Note: CFG_ZONE_* options indicate in which zone types this clause is
   2555       1.1  christos  * legal.
   2556       1.1  christos  */
   2557       1.8  christos static cfg_clausedef_t zone_only_clauses[] = {
   2558       1.1  christos 	/*
   2559       1.1  christos 	 * Note that the format of the check-names option is different between
   2560       1.1  christos 	 * the zone options and the global/view options.  Ugh.
   2561       1.1  christos 	 */
   2562       1.1  christos 	{ "type", &cfg_type_zonetype,
   2563      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2564      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_DELEGATION |
   2565      1.13  christos 		  CFG_ZONE_HINT | CFG_ZONE_REDIRECT | CFG_ZONE_FORWARD },
   2566       1.1  christos 	{ "check-names", &cfg_type_checkmode,
   2567      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2568      1.13  christos 		  CFG_ZONE_HINT | CFG_ZONE_STUB },
   2569  1.15.2.1  perseant 	{ "checkds", &cfg_type_checkdstype,
   2570  1.15.2.1  perseant 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2571      1.13  christos 	{ "database", &cfg_type_astring,
   2572      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2573       1.8  christos 		  CFG_ZONE_STUB },
   2574       1.1  christos 	{ "delegation-only", &cfg_type_boolean,
   2575      1.15  christos 	  CFG_ZONE_HINT | CFG_ZONE_STUB | CFG_ZONE_FORWARD |
   2576  1.15.2.1  perseant 		  CFG_CLAUSEFLAG_ANCIENT },
   2577       1.1  christos 	{ "dlz", &cfg_type_astring,
   2578      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_REDIRECT },
   2579       1.1  christos 	{ "file", &cfg_type_qstring,
   2580      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
   2581      1.13  christos 		  CFG_ZONE_STUB | CFG_ZONE_HINT | CFG_ZONE_REDIRECT },
   2582       1.8  christos 	{ "in-view", &cfg_type_astring, CFG_ZONE_INVIEW },
   2583      1.12  christos 	{ "inline-signing", &cfg_type_boolean,
   2584      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2585      1.15  christos 	{ "ixfr-base", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2586       1.1  christos 	{ "ixfr-from-differences", &cfg_type_boolean,
   2587      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2588      1.15  christos 	{ "ixfr-tmp-file", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2589       1.1  christos 	{ "journal", &cfg_type_qstring,
   2590      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
   2591       1.1  christos 	{ "masters", &cfg_type_namesockaddrkeylist,
   2592      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB |
   2593      1.15  christos 		  CFG_ZONE_REDIRECT | CFG_CLAUSEFLAG_NODOC },
   2594      1.12  christos 	{ "parental-agents", &cfg_type_namesockaddrkeylist,
   2595      1.13  christos 	  CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
   2596       1.9  christos 	{ "primaries", &cfg_type_namesockaddrkeylist,
   2597      1.13  christos 	  CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB |
   2598       1.9  christos 		  CFG_ZONE_REDIRECT },
   2599      1.15  christos 	{ "pubkey", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2600       1.3  christos 	{ "server-addresses", &cfg_type_bracketed_netaddrlist,
   2601       1.8  christos 	  CFG_ZONE_STATICSTUB },
   2602       1.8  christos 	{ "server-names", &cfg_type_namelist, CFG_ZONE_STATICSTUB },
   2603      1.13  christos 	{ "update-policy", &cfg_type_updatepolicy, CFG_ZONE_PRIMARY },
   2604       1.1  christos 	{ NULL, NULL, 0 }
   2605       1.1  christos };
   2606       1.1  christos 
   2607       1.1  christos /*% The top-level named.conf syntax. */
   2608       1.1  christos 
   2609       1.8  christos static cfg_clausedef_t *namedconf_clausesets[] = { namedconf_clauses,
   2610       1.8  christos 						   namedconf_or_view_clauses,
   2611       1.8  christos 						   NULL };
   2612      1.15  christos cfg_type_t cfg_type_namedconf = { "namedconf",	     cfg_parse_mapbody,
   2613      1.15  christos 				  cfg_print_mapbody, cfg_doc_mapbody,
   2614      1.15  christos 				  &cfg_rep_map,	     namedconf_clausesets };
   2615       1.1  christos 
   2616       1.8  christos /*% The bind.keys syntax (trust-anchors/managed-keys/trusted-keys only). */
   2617       1.8  christos static cfg_clausedef_t *bindkeys_clausesets[] = { bindkeys_clauses, NULL };
   2618      1.15  christos cfg_type_t cfg_type_bindkeys = { "bindkeys",	    cfg_parse_mapbody,
   2619      1.15  christos 				 cfg_print_mapbody, cfg_doc_mapbody,
   2620      1.15  christos 				 &cfg_rep_map,	    bindkeys_clausesets };
   2621       1.1  christos 
   2622       1.1  christos /*% The "options" statement syntax. */
   2623       1.1  christos 
   2624       1.8  christos static cfg_clausedef_t *options_clausesets[] = { options_clauses, view_clauses,
   2625       1.8  christos 						 zone_clauses, NULL };
   2626       1.8  christos static cfg_type_t cfg_type_options = { "options",     cfg_parse_map,
   2627       1.8  christos 				       cfg_print_map, cfg_doc_map,
   2628       1.8  christos 				       &cfg_rep_map,  options_clausesets };
   2629       1.1  christos 
   2630       1.1  christos /*% The "view" statement syntax. */
   2631       1.1  christos 
   2632       1.8  christos static cfg_clausedef_t *view_clausesets[] = { view_only_clauses,
   2633       1.8  christos 					      namedconf_or_view_clauses,
   2634       1.8  christos 					      view_clauses, zone_clauses,
   2635       1.8  christos 					      NULL };
   2636       1.8  christos 
   2637       1.8  christos static cfg_type_t cfg_type_viewopts = { "view",	       cfg_parse_map,
   2638       1.8  christos 					cfg_print_map, cfg_doc_map,
   2639       1.8  christos 					&cfg_rep_map,  view_clausesets };
   2640       1.8  christos 
   2641       1.8  christos /*% The "zone" statement syntax. */
   2642       1.1  christos 
   2643       1.8  christos static cfg_clausedef_t *zone_clausesets[] = { zone_only_clauses, zone_clauses,
   2644       1.8  christos 					      NULL };
   2645      1.15  christos cfg_type_t cfg_type_zoneopts = { "zoneopts",  cfg_parse_map, cfg_print_map,
   2646      1.15  christos 				 cfg_doc_map, &cfg_rep_map,  zone_clausesets };
   2647       1.1  christos 
   2648       1.8  christos /*% The "dnssec-policy" statement syntax. */
   2649       1.8  christos static cfg_clausedef_t *dnssecpolicy_clausesets[] = { dnssecpolicy_clauses,
   2650       1.8  christos 						      NULL };
   2651      1.15  christos cfg_type_t cfg_type_dnssecpolicyopts = {
   2652       1.8  christos 	"dnssecpolicyopts", cfg_parse_map, cfg_print_map,
   2653       1.8  christos 	cfg_doc_map,	    &cfg_rep_map,  dnssecpolicy_clausesets
   2654       1.1  christos };
   2655       1.1  christos 
   2656       1.1  christos /*% The "dynamically loadable zones" statement syntax. */
   2657       1.1  christos 
   2658       1.8  christos static cfg_clausedef_t dlz_clauses[] = { { "database", &cfg_type_astring, 0 },
   2659       1.8  christos 					 { "search", &cfg_type_boolean, 0 },
   2660       1.8  christos 					 { NULL, NULL, 0 } };
   2661       1.8  christos static cfg_clausedef_t *dlz_clausesets[] = { dlz_clauses, NULL };
   2662       1.8  christos static cfg_type_t cfg_type_dlz = { "dlz",	  cfg_parse_named_map,
   2663       1.8  christos 				   cfg_print_map, cfg_doc_map,
   2664       1.8  christos 				   &cfg_rep_map,  dlz_clausesets };
   2665       1.1  christos 
   2666       1.1  christos /*%
   2667       1.1  christos  * The "dyndb" statement syntax.
   2668       1.1  christos  */
   2669       1.1  christos 
   2670       1.1  christos static cfg_tuplefielddef_t dyndb_fields[] = {
   2671       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   2672       1.1  christos 	{ "library", &cfg_type_qstring, 0 },
   2673       1.1  christos 	{ "parameters", &cfg_type_bracketed_text, 0 },
   2674       1.1  christos 	{ NULL, NULL, 0 }
   2675       1.1  christos };
   2676       1.1  christos 
   2677       1.8  christos static cfg_type_t cfg_type_dyndb = { "dyndb",	      cfg_parse_tuple,
   2678       1.8  christos 				     cfg_print_tuple, cfg_doc_tuple,
   2679       1.8  christos 				     &cfg_rep_tuple,  dyndb_fields };
   2680       1.1  christos 
   2681       1.1  christos /*%
   2682       1.3  christos  * The "plugin" statement syntax.
   2683       1.3  christos  * Currently only one plugin type is supported: query.
   2684       1.3  christos  */
   2685       1.3  christos 
   2686       1.8  christos static const char *plugin_enums[] = { "query", NULL };
   2687       1.8  christos static cfg_type_t cfg_type_plugintype = { "plugintype",	     cfg_parse_enum,
   2688       1.8  christos 					  cfg_print_ustring, cfg_doc_enum,
   2689       1.8  christos 					  &cfg_rep_string,   plugin_enums };
   2690       1.3  christos static cfg_tuplefielddef_t plugin_fields[] = {
   2691       1.3  christos 	{ "type", &cfg_type_plugintype, 0 },
   2692       1.3  christos 	{ "library", &cfg_type_astring, 0 },
   2693       1.3  christos 	{ "parameters", &cfg_type_optional_bracketed_text, 0 },
   2694       1.3  christos 	{ NULL, NULL, 0 }
   2695       1.3  christos };
   2696       1.8  christos static cfg_type_t cfg_type_plugin = { "plugin",	       cfg_parse_tuple,
   2697       1.8  christos 				      cfg_print_tuple, cfg_doc_tuple,
   2698       1.8  christos 				      &cfg_rep_tuple,  plugin_fields };
   2699       1.3  christos 
   2700       1.3  christos /*%
   2701       1.1  christos  * Clauses that can be found within the 'key' statement.
   2702       1.1  christos  */
   2703       1.8  christos static cfg_clausedef_t key_clauses[] = { { "algorithm", &cfg_type_astring, 0 },
   2704       1.8  christos 					 { "secret", &cfg_type_sstring, 0 },
   2705       1.8  christos 					 { NULL, NULL, 0 } };
   2706       1.8  christos 
   2707       1.8  christos static cfg_clausedef_t *key_clausesets[] = { key_clauses, NULL };
   2708       1.8  christos static cfg_type_t cfg_type_key = { "key",	  cfg_parse_named_map,
   2709       1.8  christos 				   cfg_print_map, cfg_doc_map,
   2710       1.8  christos 				   &cfg_rep_map,  key_clausesets };
   2711       1.1  christos 
   2712       1.1  christos /*%
   2713  1.15.2.1  perseant  * A key-store statement.
   2714  1.15.2.1  perseant  */
   2715  1.15.2.1  perseant static cfg_clausedef_t keystore_clauses[] = {
   2716  1.15.2.1  perseant 	{ "directory", &cfg_type_astring, 0 },
   2717  1.15.2.1  perseant 	{ "pkcs11-uri", &cfg_type_qstring, 0 },
   2718  1.15.2.1  perseant 	{ NULL, NULL, 0 }
   2719  1.15.2.1  perseant };
   2720  1.15.2.1  perseant 
   2721  1.15.2.1  perseant static cfg_clausedef_t *keystore_clausesets[] = { keystore_clauses, NULL };
   2722  1.15.2.1  perseant static cfg_type_t cfg_type_keystoreopts = {
   2723  1.15.2.1  perseant 	"keystoreopts", cfg_parse_map, cfg_print_map,
   2724  1.15.2.1  perseant 	cfg_doc_map,	&cfg_rep_map,  keystore_clausesets
   2725  1.15.2.1  perseant };
   2726  1.15.2.1  perseant 
   2727  1.15.2.1  perseant static cfg_tuplefielddef_t keystore_fields[] = {
   2728  1.15.2.1  perseant 	{ "name", &cfg_type_astring, 0 },
   2729  1.15.2.1  perseant 	{ "options", &cfg_type_keystoreopts, 0 },
   2730  1.15.2.1  perseant 	{ NULL, NULL, 0 }
   2731  1.15.2.1  perseant };
   2732  1.15.2.1  perseant static cfg_type_t cfg_type_keystore = { "key-store",	 cfg_parse_tuple,
   2733  1.15.2.1  perseant 					cfg_print_tuple, cfg_doc_tuple,
   2734  1.15.2.1  perseant 					&cfg_rep_tuple,	 keystore_fields };
   2735  1.15.2.1  perseant 
   2736  1.15.2.1  perseant /*%
   2737       1.1  christos  * Clauses that can be found in a 'server' statement.
   2738      1.15  christos  *
   2739  1.15.2.1  perseant  * Please update lib/isccfg/check.c and
   2740      1.15  christos  * bin/tests/system/checkconf/good-server-christmas-tree.conf.in to
   2741      1.15  christos  * exercise the new clause when adding new clauses.
   2742       1.1  christos  */
   2743       1.8  christos static cfg_clausedef_t server_clauses[] = {
   2744       1.1  christos 	{ "bogus", &cfg_type_boolean, 0 },
   2745       1.1  christos 	{ "edns", &cfg_type_boolean, 0 },
   2746       1.1  christos 	{ "edns-udp-size", &cfg_type_uint32, 0 },
   2747       1.1  christos 	{ "edns-version", &cfg_type_uint32, 0 },
   2748       1.1  christos 	{ "keys", &cfg_type_server_key_kludge, 0 },
   2749       1.1  christos 	{ "max-udp-size", &cfg_type_uint32, 0 },
   2750       1.1  christos 	{ "notify-source", &cfg_type_sockaddr4wild, 0 },
   2751       1.1  christos 	{ "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
   2752       1.1  christos 	{ "padding", &cfg_type_uint32, 0 },
   2753       1.1  christos 	{ "provide-ixfr", &cfg_type_boolean, 0 },
   2754  1.15.2.1  perseant 	{ "query-source", &cfg_type_server_querysource4, 0 },
   2755  1.15.2.1  perseant 	{ "query-source-v6", &cfg_type_server_querysource6, 0 },
   2756       1.1  christos 	{ "request-expire", &cfg_type_boolean, 0 },
   2757       1.1  christos 	{ "request-ixfr", &cfg_type_boolean, 0 },
   2758       1.1  christos 	{ "request-nsid", &cfg_type_boolean, 0 },
   2759      1.15  christos 	{ "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2760  1.15.2.1  perseant 	{ "require-cookie", &cfg_type_boolean, 0 },
   2761       1.1  christos 	{ "send-cookie", &cfg_type_boolean, 0 },
   2762      1.15  christos 	{ "support-ixfr", NULL, CFG_CLAUSEFLAG_ANCIENT },
   2763       1.1  christos 	{ "tcp-keepalive", &cfg_type_boolean, 0 },
   2764       1.1  christos 	{ "tcp-only", &cfg_type_boolean, 0 },
   2765       1.1  christos 	{ "transfer-format", &cfg_type_transferformat, 0 },
   2766       1.1  christos 	{ "transfer-source", &cfg_type_sockaddr4wild, 0 },
   2767       1.1  christos 	{ "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
   2768       1.1  christos 	{ "transfers", &cfg_type_uint32, 0 },
   2769       1.1  christos 	{ NULL, NULL, 0 }
   2770       1.1  christos };
   2771       1.8  christos static cfg_clausedef_t *server_clausesets[] = { server_clauses, NULL };
   2772       1.8  christos static cfg_type_t cfg_type_server = { "server",	     cfg_parse_netprefix_map,
   2773       1.8  christos 				      cfg_print_map, cfg_doc_map,
   2774       1.8  christos 				      &cfg_rep_map,  server_clausesets };
   2775       1.1  christos 
   2776       1.1  christos /*%
   2777       1.1  christos  * Clauses that can be found in a 'channel' clause in the
   2778       1.1  christos  * 'logging' statement.
   2779       1.1  christos  *
   2780       1.1  christos  * These have some additional constraints that need to be
   2781       1.1  christos  * checked after parsing:
   2782       1.1  christos  *  - There must exactly one of file/syslog/null/stderr
   2783       1.1  christos  */
   2784       1.1  christos 
   2785       1.8  christos static const char *printtime_enums[] = { "iso8601", "iso8601-utc", "local",
   2786       1.8  christos 					 NULL };
   2787       1.1  christos static isc_result_t
   2788       1.1  christos parse_printtime(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   2789  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   2790       1.1  christos }
   2791       1.1  christos static void
   2792       1.1  christos doc_printtime(cfg_printer_t *pctx, const cfg_type_t *type) {
   2793       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   2794       1.1  christos }
   2795       1.8  christos static cfg_type_t cfg_type_printtime = { "printtime",	    parse_printtime,
   2796       1.8  christos 					 cfg_print_ustring, doc_printtime,
   2797       1.8  christos 					 &cfg_rep_string,   printtime_enums };
   2798       1.1  christos 
   2799       1.8  christos static cfg_clausedef_t channel_clauses[] = {
   2800       1.1  christos 	/* Destinations.  We no longer require these to be first. */
   2801       1.1  christos 	{ "file", &cfg_type_logfile, 0 },
   2802       1.1  christos 	{ "syslog", &cfg_type_optional_facility, 0 },
   2803       1.1  christos 	{ "null", &cfg_type_void, 0 },
   2804       1.1  christos 	{ "stderr", &cfg_type_void, 0 },
   2805       1.1  christos 	/* Options.  We now accept these for the null channel, too. */
   2806       1.1  christos 	{ "severity", &cfg_type_logseverity, 0 },
   2807       1.1  christos 	{ "print-time", &cfg_type_printtime, 0 },
   2808       1.1  christos 	{ "print-severity", &cfg_type_boolean, 0 },
   2809       1.1  christos 	{ "print-category", &cfg_type_boolean, 0 },
   2810       1.1  christos 	{ "buffered", &cfg_type_boolean, 0 },
   2811       1.1  christos 	{ NULL, NULL, 0 }
   2812       1.1  christos };
   2813       1.8  christos static cfg_clausedef_t *channel_clausesets[] = { channel_clauses, NULL };
   2814       1.8  christos static cfg_type_t cfg_type_channel = { "channel",     cfg_parse_named_map,
   2815       1.8  christos 				       cfg_print_map, cfg_doc_map,
   2816       1.8  christos 				       &cfg_rep_map,  channel_clausesets };
   2817       1.1  christos 
   2818       1.1  christos /*% A list of log destination, used in the "category" clause. */
   2819       1.8  christos static cfg_type_t cfg_type_destinationlist = { "destinationlist",
   2820       1.8  christos 					       cfg_parse_bracketed_list,
   2821       1.8  christos 					       cfg_print_bracketed_list,
   2822       1.8  christos 					       cfg_doc_bracketed_list,
   2823       1.8  christos 					       &cfg_rep_list,
   2824       1.8  christos 					       &cfg_type_astring };
   2825       1.1  christos 
   2826       1.1  christos /*%
   2827       1.1  christos  * Clauses that can be found in a 'logging' statement.
   2828       1.1  christos  */
   2829       1.1  christos static cfg_clausedef_t logging_clauses[] = {
   2830       1.1  christos 	{ "channel", &cfg_type_channel, CFG_CLAUSEFLAG_MULTI },
   2831       1.1  christos 	{ "category", &cfg_type_category, CFG_CLAUSEFLAG_MULTI },
   2832       1.1  christos 	{ NULL, NULL, 0 }
   2833       1.1  christos };
   2834       1.8  christos static cfg_clausedef_t *logging_clausesets[] = { logging_clauses, NULL };
   2835       1.8  christos static cfg_type_t cfg_type_logging = { "logging",     cfg_parse_map,
   2836       1.8  christos 				       cfg_print_map, cfg_doc_map,
   2837       1.8  christos 				       &cfg_rep_map,  logging_clausesets };
   2838       1.1  christos 
   2839       1.1  christos /*%
   2840       1.1  christos  * For parsing an 'addzone' statement
   2841       1.1  christos  */
   2842       1.1  christos static cfg_tuplefielddef_t addzone_fields[] = {
   2843       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   2844       1.1  christos 	{ "class", &cfg_type_optional_class, 0 },
   2845       1.1  christos 	{ "view", &cfg_type_optional_class, 0 },
   2846       1.1  christos 	{ "options", &cfg_type_zoneopts, 0 },
   2847       1.1  christos 	{ NULL, NULL, 0 }
   2848       1.1  christos };
   2849       1.8  christos static cfg_type_t cfg_type_addzone = { "zone",		cfg_parse_tuple,
   2850       1.8  christos 				       cfg_print_tuple, cfg_doc_tuple,
   2851       1.8  christos 				       &cfg_rep_tuple,	addzone_fields };
   2852       1.1  christos 
   2853       1.8  christos static cfg_clausedef_t addzoneconf_clauses[] = {
   2854       1.8  christos 	{ "zone", &cfg_type_addzone, CFG_CLAUSEFLAG_MULTI }, { NULL, NULL, 0 }
   2855       1.1  christos };
   2856       1.1  christos 
   2857       1.8  christos static cfg_clausedef_t *addzoneconf_clausesets[] = { addzoneconf_clauses,
   2858       1.8  christos 						     NULL };
   2859       1.1  christos 
   2860      1.15  christos cfg_type_t cfg_type_addzoneconf = { "addzoneconf",     cfg_parse_mapbody,
   2861      1.15  christos 				    cfg_print_mapbody, cfg_doc_mapbody,
   2862      1.15  christos 				    &cfg_rep_map,      addzoneconf_clausesets };
   2863       1.1  christos 
   2864       1.1  christos static isc_result_t
   2865  1.15.2.1  perseant parse_unitstring(char *str, uint64_t *valuep) {
   2866       1.1  christos 	char *endp;
   2867       1.1  christos 	unsigned int len;
   2868       1.3  christos 	uint64_t value;
   2869       1.3  christos 	uint64_t unit;
   2870       1.1  christos 
   2871       1.3  christos 	value = strtoull(str, &endp, 10);
   2872       1.1  christos 	if (*endp == 0) {
   2873       1.1  christos 		*valuep = value;
   2874  1.15.2.1  perseant 		return ISC_R_SUCCESS;
   2875       1.1  christos 	}
   2876       1.1  christos 
   2877       1.1  christos 	len = strlen(str);
   2878       1.8  christos 	if (len < 2 || endp[1] != '\0') {
   2879  1.15.2.1  perseant 		return ISC_R_FAILURE;
   2880       1.8  christos 	}
   2881       1.1  christos 
   2882       1.1  christos 	switch (str[len - 1]) {
   2883       1.1  christos 	case 'k':
   2884       1.1  christos 	case 'K':
   2885       1.1  christos 		unit = 1024;
   2886       1.1  christos 		break;
   2887       1.1  christos 	case 'm':
   2888       1.1  christos 	case 'M':
   2889       1.1  christos 		unit = 1024 * 1024;
   2890       1.1  christos 		break;
   2891       1.1  christos 	case 'g':
   2892       1.1  christos 	case 'G':
   2893       1.1  christos 		unit = 1024 * 1024 * 1024;
   2894       1.1  christos 		break;
   2895       1.1  christos 	default:
   2896  1.15.2.1  perseant 		return ISC_R_FAILURE;
   2897       1.1  christos 	}
   2898       1.7  christos 	if (value > ((uint64_t)UINT64_MAX / unit)) {
   2899  1.15.2.1  perseant 		return ISC_R_FAILURE;
   2900       1.7  christos 	}
   2901       1.1  christos 	*valuep = value * unit;
   2902  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   2903       1.1  christos }
   2904       1.1  christos 
   2905       1.1  christos static isc_result_t
   2906       1.1  christos parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   2907       1.1  christos 	isc_result_t result;
   2908       1.1  christos 	cfg_obj_t *obj = NULL;
   2909       1.3  christos 	uint64_t val;
   2910       1.1  christos 
   2911       1.1  christos 	UNUSED(type);
   2912       1.1  christos 
   2913       1.1  christos 	CHECK(cfg_gettoken(pctx, 0));
   2914       1.1  christos 	if (pctx->token.type != isc_tokentype_string) {
   2915       1.1  christos 		result = ISC_R_UNEXPECTEDTOKEN;
   2916       1.1  christos 		goto cleanup;
   2917       1.1  christos 	}
   2918       1.1  christos 	CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
   2919       1.1  christos 
   2920       1.1  christos 	CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
   2921       1.1  christos 	obj->value.uint64 = val;
   2922       1.1  christos 	*ret = obj;
   2923  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   2924       1.1  christos 
   2925       1.8  christos cleanup:
   2926       1.1  christos 	cfg_parser_error(pctx, CFG_LOG_NEAR,
   2927       1.1  christos 			 "expected integer and optional unit");
   2928  1.15.2.1  perseant 	return result;
   2929       1.1  christos }
   2930       1.1  christos 
   2931       1.1  christos static isc_result_t
   2932       1.1  christos parse_sizeval_percent(cfg_parser_t *pctx, const cfg_type_t *type,
   2933       1.8  christos 		      cfg_obj_t **ret) {
   2934       1.1  christos 	char *endp;
   2935       1.8  christos 	isc_result_t result;
   2936       1.1  christos 	cfg_obj_t *obj = NULL;
   2937       1.3  christos 	uint64_t val;
   2938       1.3  christos 	uint64_t percent;
   2939       1.1  christos 
   2940       1.1  christos 	UNUSED(type);
   2941       1.1  christos 
   2942       1.1  christos 	CHECK(cfg_gettoken(pctx, 0));
   2943       1.1  christos 	if (pctx->token.type != isc_tokentype_string) {
   2944       1.1  christos 		result = ISC_R_UNEXPECTEDTOKEN;
   2945       1.1  christos 		goto cleanup;
   2946       1.1  christos 	}
   2947       1.1  christos 
   2948       1.3  christos 	percent = strtoull(TOKEN_STRING(pctx), &endp, 10);
   2949       1.1  christos 
   2950       1.8  christos 	if (*endp == '%' && *(endp + 1) == 0) {
   2951       1.1  christos 		CHECK(cfg_create_obj(pctx, &cfg_type_percentage, &obj));
   2952       1.3  christos 		obj->value.uint32 = (uint32_t)percent;
   2953       1.1  christos 		*ret = obj;
   2954  1.15.2.1  perseant 		return ISC_R_SUCCESS;
   2955       1.1  christos 	} else {
   2956       1.1  christos 		CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
   2957       1.1  christos 		CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
   2958       1.1  christos 		obj->value.uint64 = val;
   2959       1.1  christos 		*ret = obj;
   2960  1.15.2.1  perseant 		return ISC_R_SUCCESS;
   2961       1.1  christos 	}
   2962       1.1  christos 
   2963       1.8  christos cleanup:
   2964       1.1  christos 	cfg_parser_error(pctx, CFG_LOG_NEAR,
   2965       1.1  christos 			 "expected integer and optional unit or percent");
   2966  1.15.2.1  perseant 	return result;
   2967       1.1  christos }
   2968       1.1  christos 
   2969       1.1  christos static void
   2970       1.1  christos doc_sizeval_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
   2971       1.1  christos 	UNUSED(type);
   2972       1.1  christos 
   2973       1.1  christos 	cfg_print_cstr(pctx, "( ");
   2974       1.1  christos 	cfg_doc_terminal(pctx, &cfg_type_size);
   2975       1.1  christos 	cfg_print_cstr(pctx, " | ");
   2976       1.1  christos 	cfg_doc_terminal(pctx, &cfg_type_percentage);
   2977       1.1  christos 	cfg_print_cstr(pctx, " )");
   2978       1.1  christos }
   2979       1.1  christos 
   2980       1.1  christos /*%
   2981       1.1  christos  * A size value (number + optional unit).
   2982       1.1  christos  */
   2983       1.8  christos static cfg_type_t cfg_type_sizeval = { "sizeval",	 parse_sizeval,
   2984       1.8  christos 				       cfg_print_uint64, cfg_doc_terminal,
   2985       1.8  christos 				       &cfg_rep_uint64,	 NULL };
   2986       1.1  christos 
   2987       1.1  christos /*%
   2988       1.1  christos  * A size, "unlimited", or "default".
   2989       1.1  christos  */
   2990       1.1  christos 
   2991       1.1  christos static isc_result_t
   2992       1.1  christos parse_size(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   2993  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_sizeval, ret);
   2994       1.1  christos }
   2995       1.1  christos 
   2996       1.1  christos static void
   2997       1.1  christos doc_size(cfg_printer_t *pctx, const cfg_type_t *type) {
   2998       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_sizeval);
   2999       1.1  christos }
   3000       1.1  christos 
   3001       1.1  christos static const char *size_enums[] = { "default", "unlimited", NULL };
   3002       1.1  christos static cfg_type_t cfg_type_size = {
   3003       1.8  christos 	"size",	  parse_size,	   cfg_print_ustring,
   3004       1.8  christos 	doc_size, &cfg_rep_string, size_enums
   3005       1.1  christos };
   3006       1.1  christos 
   3007       1.1  christos /*%
   3008       1.1  christos  * A size or "unlimited", but not "default".
   3009       1.1  christos  */
   3010       1.1  christos static const char *sizenodefault_enums[] = { "unlimited", NULL };
   3011       1.1  christos static cfg_type_t cfg_type_sizenodefault = {
   3012       1.8  christos 	"size_no_default", parse_size,	    cfg_print_ustring,
   3013       1.8  christos 	doc_size,	   &cfg_rep_string, sizenodefault_enums
   3014       1.1  christos };
   3015       1.1  christos 
   3016       1.1  christos /*%
   3017       1.1  christos  * A size in absolute values or percents.
   3018       1.1  christos  */
   3019       1.1  christos static cfg_type_t cfg_type_sizeval_percent = {
   3020       1.8  christos 	"sizeval_percent",   parse_sizeval_percent, cfg_print_ustring,
   3021       1.8  christos 	doc_sizeval_percent, &cfg_rep_string,	    NULL
   3022       1.1  christos };
   3023       1.1  christos 
   3024       1.1  christos /*%
   3025       1.1  christos  * A size in absolute values or percents, or "unlimited", or "default"
   3026       1.1  christos  */
   3027       1.1  christos 
   3028       1.1  christos static isc_result_t
   3029       1.1  christos parse_size_or_percent(cfg_parser_t *pctx, const cfg_type_t *type,
   3030       1.8  christos 		      cfg_obj_t **ret) {
   3031  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_sizeval_percent,
   3032  1.15.2.1  perseant 				       ret);
   3033       1.1  christos }
   3034       1.1  christos 
   3035       1.1  christos static void
   3036       1.1  christos doc_parse_size_or_percent(cfg_printer_t *pctx, const cfg_type_t *type) {
   3037       1.3  christos 	UNUSED(type);
   3038       1.3  christos 	cfg_print_cstr(pctx, "( default | unlimited | ");
   3039       1.3  christos 	cfg_doc_terminal(pctx, &cfg_type_sizeval);
   3040       1.3  christos 	cfg_print_cstr(pctx, " | ");
   3041       1.3  christos 	cfg_doc_terminal(pctx, &cfg_type_percentage);
   3042       1.3  christos 	cfg_print_cstr(pctx, " )");
   3043       1.1  christos }
   3044       1.1  christos 
   3045       1.1  christos static const char *sizeorpercent_enums[] = { "default", "unlimited", NULL };
   3046       1.1  christos static cfg_type_t cfg_type_sizeorpercent = {
   3047       1.8  christos 	"size_or_percent",	   parse_size_or_percent, cfg_print_ustring,
   3048       1.8  christos 	doc_parse_size_or_percent, &cfg_rep_string,	  sizeorpercent_enums
   3049       1.1  christos };
   3050       1.1  christos 
   3051       1.1  christos /*%
   3052       1.9  christos  * An IXFR size ratio: percentage, or "unlimited".
   3053       1.9  christos  */
   3054       1.9  christos 
   3055       1.9  christos static isc_result_t
   3056       1.9  christos parse_ixfrratio(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3057  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_percentage, ret);
   3058       1.9  christos }
   3059       1.9  christos 
   3060       1.9  christos static void
   3061       1.9  christos doc_ixfrratio(cfg_printer_t *pctx, const cfg_type_t *type) {
   3062       1.9  christos 	UNUSED(type);
   3063       1.9  christos 	cfg_print_cstr(pctx, "( unlimited | ");
   3064       1.9  christos 	cfg_doc_terminal(pctx, &cfg_type_percentage);
   3065       1.9  christos 	cfg_print_cstr(pctx, " )");
   3066       1.9  christos }
   3067       1.9  christos 
   3068       1.9  christos static const char *ixfrratio_enums[] = { "unlimited", NULL };
   3069       1.9  christos static cfg_type_t cfg_type_ixfrratio = { "ixfr_ratio", parse_ixfrratio,
   3070       1.9  christos 					 NULL,	       doc_ixfrratio,
   3071       1.9  christos 					 NULL,	       ixfrratio_enums };
   3072       1.9  christos 
   3073       1.9  christos /*%
   3074       1.1  christos  * optional_keyvalue
   3075       1.1  christos  */
   3076       1.1  christos static isc_result_t
   3077       1.1  christos parse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
   3078       1.8  christos 			      bool optional, cfg_obj_t **ret) {
   3079       1.1  christos 	isc_result_t result;
   3080       1.1  christos 	cfg_obj_t *obj = NULL;
   3081       1.1  christos 	const keyword_type_t *kw = type->of;
   3082       1.1  christos 
   3083       1.1  christos 	CHECK(cfg_peektoken(pctx, 0));
   3084       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
   3085       1.8  christos 	    strcasecmp(TOKEN_STRING(pctx), kw->name) == 0)
   3086       1.8  christos 	{
   3087       1.1  christos 		CHECK(cfg_gettoken(pctx, 0));
   3088       1.1  christos 		CHECK(kw->type->parse(pctx, kw->type, &obj));
   3089       1.1  christos 		obj->type = type; /* XXX kludge */
   3090       1.1  christos 	} else {
   3091       1.1  christos 		if (optional) {
   3092       1.1  christos 			CHECK(cfg_parse_void(pctx, NULL, &obj));
   3093       1.1  christos 		} else {
   3094       1.1  christos 			cfg_parser_error(pctx, CFG_LOG_NEAR, "expected '%s'",
   3095       1.8  christos 					 kw->name);
   3096       1.1  christos 			result = ISC_R_UNEXPECTEDTOKEN;
   3097       1.1  christos 			goto cleanup;
   3098       1.1  christos 		}
   3099       1.1  christos 	}
   3100       1.1  christos 	*ret = obj;
   3101       1.8  christos cleanup:
   3102  1.15.2.1  perseant 	return result;
   3103       1.1  christos }
   3104       1.1  christos 
   3105       1.1  christos static isc_result_t
   3106       1.1  christos parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3107  1.15.2.1  perseant 	return parse_maybe_optional_keyvalue(pctx, type, false, ret);
   3108       1.1  christos }
   3109       1.1  christos 
   3110       1.1  christos static isc_result_t
   3111       1.1  christos parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
   3112       1.8  christos 			cfg_obj_t **ret) {
   3113  1.15.2.1  perseant 	return parse_maybe_optional_keyvalue(pctx, type, true, ret);
   3114       1.1  christos }
   3115       1.1  christos 
   3116       1.1  christos static void
   3117       1.1  christos print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   3118       1.1  christos 	const keyword_type_t *kw = obj->type->of;
   3119       1.1  christos 	cfg_print_cstr(pctx, kw->name);
   3120       1.1  christos 	cfg_print_cstr(pctx, " ");
   3121       1.1  christos 	kw->type->print(pctx, obj);
   3122       1.1  christos }
   3123       1.1  christos 
   3124       1.1  christos static void
   3125       1.1  christos doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
   3126       1.1  christos 	const keyword_type_t *kw = type->of;
   3127       1.1  christos 	cfg_print_cstr(pctx, kw->name);
   3128       1.1  christos 	cfg_print_cstr(pctx, " ");
   3129       1.1  christos 	cfg_doc_obj(pctx, kw->type);
   3130       1.1  christos }
   3131       1.1  christos 
   3132       1.1  christos static void
   3133       1.1  christos doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
   3134       1.1  christos 	const keyword_type_t *kw = type->of;
   3135       1.1  christos 	cfg_print_cstr(pctx, "[ ");
   3136       1.1  christos 	cfg_print_cstr(pctx, kw->name);
   3137       1.1  christos 	cfg_print_cstr(pctx, " ");
   3138       1.1  christos 	cfg_doc_obj(pctx, kw->type);
   3139       1.1  christos 	cfg_print_cstr(pctx, " ]");
   3140       1.1  christos }
   3141       1.1  christos 
   3142       1.8  christos static const char *dialup_enums[] = { "notify", "notify-passive", "passive",
   3143       1.8  christos 				      "refresh", NULL };
   3144       1.1  christos static isc_result_t
   3145       1.8  christos parse_dialup_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3146  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   3147       1.1  christos }
   3148       1.1  christos static void
   3149       1.1  christos doc_dialup_type(cfg_printer_t *pctx, const cfg_type_t *type) {
   3150       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   3151       1.1  christos }
   3152       1.8  christos static cfg_type_t cfg_type_dialuptype = { "dialuptype",	     parse_dialup_type,
   3153       1.8  christos 					  cfg_print_ustring, doc_dialup_type,
   3154       1.8  christos 					  &cfg_rep_string,   dialup_enums };
   3155       1.1  christos 
   3156       1.9  christos static const char *notify_enums[] = { "explicit", "master-only", "primary-only",
   3157       1.9  christos 				      NULL };
   3158       1.1  christos static isc_result_t
   3159       1.8  christos parse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3160  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   3161       1.1  christos }
   3162       1.1  christos static void
   3163       1.1  christos doc_notify_type(cfg_printer_t *pctx, const cfg_type_t *type) {
   3164       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   3165       1.1  christos }
   3166       1.1  christos static cfg_type_t cfg_type_notifytype = {
   3167       1.8  christos 	"notifytype",	 parse_notify_type, cfg_print_ustring,
   3168       1.8  christos 	doc_notify_type, &cfg_rep_string,   notify_enums,
   3169       1.1  christos };
   3170       1.1  christos 
   3171       1.1  christos static const char *minimal_enums[] = { "no-auth", "no-auth-recursive", NULL };
   3172       1.1  christos static isc_result_t
   3173       1.1  christos parse_minimal(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3174  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   3175       1.1  christos }
   3176       1.1  christos static void
   3177       1.1  christos doc_minimal(cfg_printer_t *pctx, const cfg_type_t *type) {
   3178       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   3179       1.1  christos }
   3180       1.1  christos static cfg_type_t cfg_type_minimal = {
   3181       1.8  christos 	"minimal",   parse_minimal,   cfg_print_ustring,
   3182       1.8  christos 	doc_minimal, &cfg_rep_string, minimal_enums,
   3183       1.1  christos };
   3184       1.1  christos 
   3185       1.8  christos static const char *ixfrdiff_enums[] = { "primary", "master", "secondary",
   3186       1.8  christos 					"slave", NULL };
   3187       1.1  christos static isc_result_t
   3188       1.1  christos parse_ixfrdiff_type(cfg_parser_t *pctx, const cfg_type_t *type,
   3189       1.8  christos 		    cfg_obj_t **ret) {
   3190  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_boolean, ret);
   3191       1.1  christos }
   3192       1.1  christos static void
   3193       1.1  christos doc_ixfrdiff_type(cfg_printer_t *pctx, const cfg_type_t *type) {
   3194       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_boolean);
   3195       1.1  christos }
   3196       1.1  christos static cfg_type_t cfg_type_ixfrdifftype = {
   3197       1.8  christos 	"ixfrdiff",	   parse_ixfrdiff_type, cfg_print_ustring,
   3198       1.8  christos 	doc_ixfrdiff_type, &cfg_rep_string,	ixfrdiff_enums,
   3199       1.1  christos };
   3200       1.1  christos 
   3201       1.1  christos static keyword_type_t key_kw = { "key", &cfg_type_astring };
   3202       1.1  christos 
   3203      1.15  christos cfg_type_t cfg_type_keyref = { "keyref",     parse_keyvalue,  print_keyvalue,
   3204      1.15  christos 			       doc_keyvalue, &cfg_rep_string, &key_kw };
   3205       1.1  christos 
   3206       1.1  christos static cfg_type_t cfg_type_optional_keyref = {
   3207       1.8  christos 	"optional_keyref",     parse_optional_keyvalue, print_keyvalue,
   3208       1.8  christos 	doc_optional_keyvalue, &cfg_rep_string,		&key_kw
   3209       1.1  christos };
   3210       1.1  christos 
   3211       1.8  christos static const char *qminmethod_enums[] = { "strict", "relaxed", "disabled",
   3212       1.8  christos 					  "off", NULL };
   3213       1.1  christos 
   3214       1.8  christos static cfg_type_t cfg_type_qminmethod = { "qminmethod",	     cfg_parse_enum,
   3215       1.8  christos 					  cfg_print_ustring, cfg_doc_enum,
   3216       1.8  christos 					  &cfg_rep_string,   qminmethod_enums };
   3217       1.1  christos 
   3218       1.1  christos /*%
   3219       1.1  christos  * A "controls" statement is represented as a map with the multivalued
   3220       1.1  christos  * "inet" and "unix" clauses.
   3221       1.1  christos  */
   3222       1.1  christos 
   3223       1.8  christos static keyword_type_t controls_allow_kw = { "allow", &cfg_type_bracketed_aml };
   3224       1.1  christos 
   3225       1.1  christos static cfg_type_t cfg_type_controls_allow = {
   3226       1.8  christos 	"controls_allow", parse_keyvalue, print_keyvalue,
   3227       1.8  christos 	doc_keyvalue,	  &cfg_rep_list,  &controls_allow_kw
   3228       1.1  christos };
   3229       1.1  christos 
   3230       1.8  christos static keyword_type_t controls_keys_kw = { "keys", &cfg_type_keylist };
   3231       1.1  christos 
   3232       1.1  christos static cfg_type_t cfg_type_controls_keys = {
   3233       1.8  christos 	"controls_keys",       parse_optional_keyvalue, print_keyvalue,
   3234       1.8  christos 	doc_optional_keyvalue, &cfg_rep_list,		&controls_keys_kw
   3235       1.1  christos };
   3236       1.1  christos 
   3237       1.8  christos static keyword_type_t controls_readonly_kw = { "read-only", &cfg_type_boolean };
   3238       1.1  christos 
   3239       1.1  christos static cfg_type_t cfg_type_controls_readonly = {
   3240       1.8  christos 	"controls_readonly",   parse_optional_keyvalue, print_keyvalue,
   3241       1.8  christos 	doc_optional_keyvalue, &cfg_rep_boolean,	&controls_readonly_kw
   3242       1.1  christos };
   3243       1.1  christos 
   3244       1.1  christos static cfg_tuplefielddef_t inetcontrol_fields[] = {
   3245       1.1  christos 	{ "address", &cfg_type_controls_sockaddr, 0 },
   3246       1.1  christos 	{ "allow", &cfg_type_controls_allow, 0 },
   3247       1.1  christos 	{ "keys", &cfg_type_controls_keys, 0 },
   3248       1.1  christos 	{ "read-only", &cfg_type_controls_readonly, 0 },
   3249       1.1  christos 	{ NULL, NULL, 0 }
   3250       1.1  christos };
   3251       1.1  christos 
   3252       1.1  christos static cfg_type_t cfg_type_inetcontrol = {
   3253       1.8  christos 	"inetcontrol", cfg_parse_tuple, cfg_print_tuple,
   3254       1.8  christos 	cfg_doc_tuple, &cfg_rep_tuple,	inetcontrol_fields
   3255       1.1  christos };
   3256       1.1  christos 
   3257       1.8  christos static keyword_type_t controls_perm_kw = { "perm", &cfg_type_uint32 };
   3258       1.1  christos 
   3259       1.1  christos static cfg_type_t cfg_type_controls_perm = {
   3260       1.8  christos 	"controls_perm", parse_keyvalue,  print_keyvalue,
   3261       1.8  christos 	doc_keyvalue,	 &cfg_rep_uint32, &controls_perm_kw
   3262       1.1  christos };
   3263       1.1  christos 
   3264       1.8  christos static keyword_type_t controls_owner_kw = { "owner", &cfg_type_uint32 };
   3265       1.1  christos 
   3266       1.1  christos static cfg_type_t cfg_type_controls_owner = {
   3267       1.8  christos 	"controls_owner", parse_keyvalue,  print_keyvalue,
   3268       1.8  christos 	doc_keyvalue,	  &cfg_rep_uint32, &controls_owner_kw
   3269       1.1  christos };
   3270       1.1  christos 
   3271       1.8  christos static keyword_type_t controls_group_kw = { "group", &cfg_type_uint32 };
   3272       1.1  christos 
   3273       1.1  christos static cfg_type_t cfg_type_controls_group = {
   3274       1.8  christos 	"controls_allow", parse_keyvalue,  print_keyvalue,
   3275       1.8  christos 	doc_keyvalue,	  &cfg_rep_uint32, &controls_group_kw
   3276       1.1  christos };
   3277       1.1  christos 
   3278       1.1  christos static cfg_tuplefielddef_t unixcontrol_fields[] = {
   3279       1.1  christos 	{ "path", &cfg_type_qstring, 0 },
   3280       1.1  christos 	{ "perm", &cfg_type_controls_perm, 0 },
   3281       1.1  christos 	{ "owner", &cfg_type_controls_owner, 0 },
   3282       1.1  christos 	{ "group", &cfg_type_controls_group, 0 },
   3283       1.1  christos 	{ "keys", &cfg_type_controls_keys, 0 },
   3284       1.1  christos 	{ "read-only", &cfg_type_controls_readonly, 0 },
   3285       1.1  christos 	{ NULL, NULL, 0 }
   3286       1.1  christos };
   3287       1.1  christos 
   3288       1.1  christos static cfg_type_t cfg_type_unixcontrol = {
   3289       1.8  christos 	"unixcontrol", cfg_parse_tuple, cfg_print_tuple,
   3290       1.8  christos 	cfg_doc_tuple, &cfg_rep_tuple,	unixcontrol_fields
   3291       1.1  christos };
   3292       1.1  christos 
   3293       1.8  christos static cfg_clausedef_t controls_clauses[] = {
   3294       1.1  christos 	{ "inet", &cfg_type_inetcontrol, CFG_CLAUSEFLAG_MULTI },
   3295       1.1  christos 	{ "unix", &cfg_type_unixcontrol, CFG_CLAUSEFLAG_MULTI },
   3296       1.1  christos 	{ NULL, NULL, 0 }
   3297       1.1  christos };
   3298       1.1  christos 
   3299       1.8  christos static cfg_clausedef_t *controls_clausesets[] = { controls_clauses, NULL };
   3300       1.8  christos static cfg_type_t cfg_type_controls = { "controls",    cfg_parse_map,
   3301       1.8  christos 					cfg_print_map, cfg_doc_map,
   3302       1.8  christos 					&cfg_rep_map,  &controls_clausesets };
   3303       1.1  christos 
   3304       1.1  christos /*%
   3305       1.1  christos  * A "statistics-channels" statement is represented as a map with the
   3306       1.1  christos  * multivalued "inet" clauses.
   3307       1.1  christos  */
   3308       1.1  christos static void
   3309       1.1  christos doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
   3310       1.1  christos 	const keyword_type_t *kw = type->of;
   3311       1.1  christos 	cfg_print_cstr(pctx, "[ ");
   3312       1.1  christos 	cfg_print_cstr(pctx, kw->name);
   3313       1.1  christos 	cfg_print_cstr(pctx, " ");
   3314       1.1  christos 	cfg_doc_obj(pctx, kw->type);
   3315       1.1  christos 	cfg_print_cstr(pctx, " ]");
   3316       1.1  christos }
   3317       1.1  christos 
   3318       1.1  christos static cfg_type_t cfg_type_optional_allow = {
   3319       1.8  christos 	"optional_allow", parse_optional_keyvalue,
   3320       1.8  christos 	print_keyvalue,	  doc_optional_bracketed_list,
   3321       1.8  christos 	&cfg_rep_list,	  &controls_allow_kw
   3322       1.1  christos };
   3323       1.1  christos 
   3324       1.1  christos static cfg_tuplefielddef_t statserver_fields[] = {
   3325       1.1  christos 	{ "address", &cfg_type_controls_sockaddr, 0 }, /* reuse controls def */
   3326       1.1  christos 	{ "allow", &cfg_type_optional_allow, 0 },
   3327       1.1  christos 	{ NULL, NULL, 0 }
   3328       1.1  christos };
   3329       1.1  christos 
   3330       1.1  christos static cfg_type_t cfg_type_statschannel = {
   3331       1.8  christos 	"statschannel", cfg_parse_tuple, cfg_print_tuple,
   3332       1.8  christos 	cfg_doc_tuple,	&cfg_rep_tuple,	 statserver_fields
   3333       1.1  christos };
   3334       1.1  christos 
   3335       1.8  christos static cfg_clausedef_t statservers_clauses[] = {
   3336       1.1  christos 	{ "inet", &cfg_type_statschannel, CFG_CLAUSEFLAG_MULTI },
   3337       1.1  christos 	{ NULL, NULL, 0 }
   3338       1.1  christos };
   3339       1.1  christos 
   3340       1.8  christos static cfg_clausedef_t *statservers_clausesets[] = { statservers_clauses,
   3341       1.8  christos 						     NULL };
   3342       1.1  christos 
   3343       1.1  christos static cfg_type_t cfg_type_statschannels = {
   3344       1.8  christos 	"statistics-channels", cfg_parse_map, cfg_print_map,
   3345       1.8  christos 	cfg_doc_map,	       &cfg_rep_map,  &statservers_clausesets
   3346       1.1  christos };
   3347       1.1  christos 
   3348       1.1  christos /*%
   3349       1.1  christos  * An optional class, as used in view and zone statements.
   3350       1.1  christos  */
   3351       1.1  christos static isc_result_t
   3352       1.1  christos parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type,
   3353       1.8  christos 		     cfg_obj_t **ret) {
   3354       1.1  christos 	isc_result_t result;
   3355       1.1  christos 	UNUSED(type);
   3356       1.1  christos 	CHECK(cfg_peektoken(pctx, 0));
   3357       1.8  christos 	if (pctx->token.type == isc_tokentype_string) {
   3358       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_ustring, ret));
   3359       1.8  christos 	} else {
   3360       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
   3361       1.8  christos 	}
   3362       1.8  christos cleanup:
   3363  1.15.2.1  perseant 	return result;
   3364       1.1  christos }
   3365       1.1  christos 
   3366       1.1  christos static void
   3367       1.1  christos doc_optional_class(cfg_printer_t *pctx, const cfg_type_t *type) {
   3368       1.1  christos 	UNUSED(type);
   3369       1.1  christos 	cfg_print_cstr(pctx, "[ <class> ]");
   3370       1.1  christos }
   3371       1.1  christos 
   3372       1.8  christos static cfg_type_t cfg_type_optional_class = { "optional_class",
   3373       1.8  christos 					      parse_optional_class,
   3374       1.8  christos 					      NULL,
   3375       1.8  christos 					      doc_optional_class,
   3376       1.8  christos 					      NULL,
   3377       1.8  christos 					      NULL };
   3378       1.1  christos 
   3379       1.1  christos static isc_result_t
   3380       1.8  christos parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3381       1.1  christos 	isc_result_t result;
   3382       1.1  christos 	cfg_obj_t *obj = NULL;
   3383       1.1  christos 	isc_netaddr_t netaddr;
   3384       1.1  christos 	in_port_t port = 0;
   3385       1.1  christos 	unsigned int have_address = 0;
   3386       1.1  christos 	unsigned int have_port = 0;
   3387  1.15.2.1  perseant 	unsigned int have_tls = 0;
   3388  1.15.2.1  perseant 	bool has_none = false;
   3389       1.1  christos 	const unsigned int *flagp = type->of;
   3390       1.1  christos 
   3391       1.3  christos 	if ((*flagp & CFG_ADDR_V4OK) != 0) {
   3392       1.1  christos 		isc_netaddr_any(&netaddr);
   3393       1.3  christos 	} else if ((*flagp & CFG_ADDR_V6OK) != 0) {
   3394       1.1  christos 		isc_netaddr_any6(&netaddr);
   3395       1.3  christos 	} else {
   3396      1.13  christos 		UNREACHABLE();
   3397       1.3  christos 	}
   3398       1.1  christos 
   3399       1.1  christos 	for (;;) {
   3400       1.1  christos 		CHECK(cfg_peektoken(pctx, 0));
   3401       1.1  christos 		if (pctx->token.type == isc_tokentype_string) {
   3402  1.15.2.1  perseant 			if (strcasecmp(TOKEN_STRING(pctx), "none") == 0) {
   3403  1.15.2.1  perseant 				CHECK(cfg_gettoken(pctx, 0));
   3404  1.15.2.1  perseant 				has_none = true;
   3405  1.15.2.1  perseant 			} else if (strcasecmp(TOKEN_STRING(pctx), "address") ==
   3406  1.15.2.1  perseant 				   0)
   3407  1.15.2.1  perseant 			{
   3408       1.1  christos 				/* read "address" */
   3409       1.1  christos 				CHECK(cfg_gettoken(pctx, 0));
   3410  1.15.2.1  perseant 
   3411  1.15.2.1  perseant 				CHECK(cfg_peektoken(pctx, 0));
   3412  1.15.2.1  perseant 				if (strcasecmp(TOKEN_STRING(pctx), "none") == 0)
   3413  1.15.2.1  perseant 				{
   3414  1.15.2.1  perseant 					CHECK(cfg_gettoken(pctx, 0));
   3415  1.15.2.1  perseant 					has_none = true;
   3416  1.15.2.1  perseant 				} else {
   3417  1.15.2.1  perseant 					CHECK(cfg_parse_rawaddr(pctx, *flagp,
   3418  1.15.2.1  perseant 								&netaddr));
   3419  1.15.2.1  perseant 					have_address++;
   3420  1.15.2.1  perseant 				}
   3421       1.1  christos 			} else if (strcasecmp(TOKEN_STRING(pctx), "port") == 0)
   3422       1.1  christos 			{
   3423       1.1  christos 				/* read "port" */
   3424      1.15  christos 				if ((pctx->flags & CFG_PCTX_NODEPRECATED) == 0)
   3425      1.15  christos 				{
   3426      1.15  christos 					cfg_parser_warning(
   3427      1.15  christos 						pctx, 0,
   3428      1.15  christos 						"token 'port' is deprecated");
   3429      1.15  christos 				}
   3430       1.1  christos 				CHECK(cfg_gettoken(pctx, 0));
   3431       1.8  christos 				CHECK(cfg_parse_rawport(pctx, CFG_ADDR_WILDOK,
   3432       1.1  christos 							&port));
   3433       1.1  christos 				have_port++;
   3434  1.15.2.1  perseant 			} else if (strcasecmp(TOKEN_STRING(pctx), "tls") == 0) {
   3435  1.15.2.1  perseant 				/* We do not expect TLS here, not parsing. */
   3436  1.15.2.1  perseant 				++have_tls;
   3437  1.15.2.1  perseant 			} else if (have_port == 0 && have_tls == 0 &&
   3438      1.14  christos 				   have_address == 0)
   3439      1.14  christos 			{
   3440  1.15.2.1  perseant 				CHECK(cfg_parse_rawaddr(pctx, *flagp,
   3441  1.15.2.1  perseant 							&netaddr));
   3442  1.15.2.1  perseant 				have_address++;
   3443       1.1  christos 			} else {
   3444       1.1  christos 				cfg_parser_error(pctx, CFG_LOG_NEAR,
   3445      1.15  christos 						 "expected 'address' "
   3446      1.15  christos 						 "or 'port'");
   3447  1.15.2.1  perseant 				return ISC_R_UNEXPECTEDTOKEN;
   3448       1.1  christos 			}
   3449       1.8  christos 		} else {
   3450       1.1  christos 			break;
   3451       1.8  christos 		}
   3452       1.1  christos 	}
   3453       1.1  christos 
   3454  1.15.2.1  perseant 	if (!has_none) {
   3455  1.15.2.1  perseant 		if (have_address > 1 || have_port > 1 ||
   3456  1.15.2.1  perseant 		    have_address + have_port == 0)
   3457  1.15.2.1  perseant 		{
   3458  1.15.2.1  perseant 			cfg_parser_error(pctx, 0,
   3459  1.15.2.1  perseant 					 "expected one address and/or port");
   3460  1.15.2.1  perseant 			return ISC_R_UNEXPECTEDTOKEN;
   3461  1.15.2.1  perseant 		}
   3462  1.15.2.1  perseant 		if (have_tls > 0) {
   3463  1.15.2.1  perseant 			cfg_parser_error(pctx, 0, "unexpected tls");
   3464  1.15.2.1  perseant 			return ISC_R_UNEXPECTEDTOKEN;
   3465  1.15.2.1  perseant 		}
   3466  1.15.2.1  perseant 		CHECK(cfg_create_obj(pctx, &cfg_type_querysource, &obj));
   3467  1.15.2.1  perseant 		isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
   3468       1.1  christos 
   3469  1.15.2.1  perseant 	} else {
   3470  1.15.2.1  perseant 		CHECK(cfg_create_obj(pctx, &cfg_type_none, &obj));
   3471  1.15.2.1  perseant 	}
   3472       1.1  christos 	*ret = obj;
   3473  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   3474       1.1  christos 
   3475       1.8  christos cleanup:
   3476       1.1  christos 	cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid query source");
   3477       1.1  christos 	CLEANUP_OBJ(obj);
   3478  1.15.2.1  perseant 
   3479  1.15.2.1  perseant 	return result;
   3480       1.1  christos }
   3481       1.1  christos 
   3482       1.1  christos static void
   3483       1.1  christos print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   3484       1.1  christos 	isc_netaddr_t na;
   3485       1.1  christos 	isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr);
   3486       1.1  christos 	cfg_print_rawaddr(pctx, &na);
   3487       1.1  christos 	cfg_print_cstr(pctx, " port ");
   3488       1.1  christos 	cfg_print_rawuint(pctx, isc_sockaddr_getport(&obj->value.sockaddr));
   3489       1.1  christos }
   3490       1.1  christos 
   3491       1.1  christos static void
   3492  1.15.2.1  perseant doc__querysource(cfg_printer_t *pctx, const cfg_type_t *type, bool has_none) {
   3493       1.1  christos 	const unsigned int *flagp = type->of;
   3494       1.1  christos 
   3495      1.15  christos 	cfg_print_cstr(pctx, "[ address ] ( ");
   3496  1.15.2.1  perseant 
   3497       1.3  christos 	if ((*flagp & CFG_ADDR_V4OK) != 0) {
   3498       1.1  christos 		cfg_print_cstr(pctx, "<ipv4_address>");
   3499       1.3  christos 	} else if ((*flagp & CFG_ADDR_V6OK) != 0) {
   3500       1.1  christos 		cfg_print_cstr(pctx, "<ipv6_address>");
   3501       1.3  christos 	} else {
   3502      1.13  christos 		UNREACHABLE();
   3503       1.3  christos 	}
   3504  1.15.2.1  perseant 
   3505  1.15.2.1  perseant 	cfg_print_cstr(pctx, " | *");
   3506  1.15.2.1  perseant 	if (has_none) {
   3507  1.15.2.1  perseant 		cfg_print_cstr(pctx, " | none");
   3508  1.15.2.1  perseant 	}
   3509  1.15.2.1  perseant 	cfg_print_cstr(pctx, " )");
   3510       1.1  christos }
   3511       1.1  christos 
   3512  1.15.2.1  perseant static void
   3513  1.15.2.1  perseant doc_querysource(cfg_printer_t *pctx, const cfg_type_t *type) {
   3514  1.15.2.1  perseant 	doc__querysource(pctx, type, true);
   3515  1.15.2.1  perseant }
   3516  1.15.2.1  perseant 
   3517  1.15.2.1  perseant static void
   3518  1.15.2.1  perseant doc_serverquerysource(cfg_printer_t *pctx, const cfg_type_t *type) {
   3519  1.15.2.1  perseant 	doc__querysource(pctx, type, false);
   3520  1.15.2.1  perseant }
   3521  1.15.2.1  perseant 
   3522  1.15.2.1  perseant static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK;
   3523  1.15.2.1  perseant static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK;
   3524       1.1  christos 
   3525       1.1  christos static cfg_type_t cfg_type_querysource4 = {
   3526       1.8  christos 	"querysource4", parse_querysource,   NULL, doc_querysource,
   3527       1.8  christos 	NULL,		&sockaddr4wild_flags
   3528       1.1  christos };
   3529       1.1  christos 
   3530       1.1  christos static cfg_type_t cfg_type_querysource6 = {
   3531       1.8  christos 	"querysource6", parse_querysource,   NULL, doc_querysource,
   3532       1.8  christos 	NULL,		&sockaddr6wild_flags
   3533       1.1  christos };
   3534       1.1  christos 
   3535  1.15.2.1  perseant static unsigned int querysource4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK;
   3536  1.15.2.1  perseant static unsigned int querysource6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK;
   3537  1.15.2.1  perseant 
   3538  1.15.2.1  perseant static cfg_type_t cfg_type_server_querysource4 = {
   3539  1.15.2.1  perseant 	"querysource4", parse_querysource,	NULL, doc_serverquerysource,
   3540  1.15.2.1  perseant 	NULL,		&querysource4wild_flags
   3541  1.15.2.1  perseant };
   3542  1.15.2.1  perseant 
   3543  1.15.2.1  perseant static cfg_type_t cfg_type_server_querysource6 = {
   3544  1.15.2.1  perseant 	"querysource6", parse_querysource,	NULL, doc_serverquerysource,
   3545  1.15.2.1  perseant 	NULL,		&querysource6wild_flags
   3546  1.15.2.1  perseant };
   3547  1.15.2.1  perseant 
   3548       1.8  christos static cfg_type_t cfg_type_querysource = { "querysource",     NULL,
   3549       1.8  christos 					   print_querysource, NULL,
   3550       1.8  christos 					   &cfg_rep_sockaddr, NULL };
   3551       1.1  christos 
   3552       1.1  christos /*%
   3553       1.1  christos  * The socket address syntax in the "controls" statement is silly.
   3554       1.1  christos  * It allows both socket address families, but also allows "*",
   3555       1.8  christos  * which is gratuitously interpreted as the IPv4 wildcard address.
   3556       1.1  christos  */
   3557       1.8  christos static unsigned int controls_sockaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK |
   3558      1.15  christos 					      CFG_ADDR_WILDOK | CFG_ADDR_PORTOK;
   3559       1.1  christos static cfg_type_t cfg_type_controls_sockaddr = {
   3560       1.1  christos 	"controls_sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr,
   3561       1.8  christos 	cfg_doc_sockaddr,    &cfg_rep_sockaddr,	 &controls_sockaddr_flags
   3562       1.1  christos };
   3563       1.1  christos 
   3564       1.1  christos /*%
   3565       1.1  christos  * Handle the special kludge syntax of the "keys" clause in the "server"
   3566       1.1  christos  * statement, which takes a single key with or without braces and semicolon.
   3567       1.1  christos  */
   3568       1.1  christos static isc_result_t
   3569       1.1  christos parse_server_key_kludge(cfg_parser_t *pctx, const cfg_type_t *type,
   3570       1.8  christos 			cfg_obj_t **ret) {
   3571       1.1  christos 	isc_result_t result;
   3572       1.3  christos 	bool braces = false;
   3573       1.1  christos 	UNUSED(type);
   3574       1.1  christos 
   3575       1.1  christos 	/* Allow opening brace. */
   3576       1.1  christos 	CHECK(cfg_peektoken(pctx, 0));
   3577       1.1  christos 	if (pctx->token.type == isc_tokentype_special &&
   3578       1.8  christos 	    pctx->token.value.as_char == '{')
   3579       1.8  christos 	{
   3580       1.1  christos 		CHECK(cfg_gettoken(pctx, 0));
   3581       1.3  christos 		braces = true;
   3582       1.1  christos 	}
   3583       1.1  christos 
   3584       1.1  christos 	CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
   3585       1.1  christos 
   3586       1.1  christos 	if (braces) {
   3587       1.1  christos 		/* Skip semicolon if present. */
   3588       1.1  christos 		CHECK(cfg_peektoken(pctx, 0));
   3589       1.1  christos 		if (pctx->token.type == isc_tokentype_special &&
   3590       1.1  christos 		    pctx->token.value.as_char == ';')
   3591       1.8  christos 		{
   3592       1.1  christos 			CHECK(cfg_gettoken(pctx, 0));
   3593       1.8  christos 		}
   3594       1.1  christos 
   3595       1.1  christos 		CHECK(cfg_parse_special(pctx, '}'));
   3596       1.1  christos 	}
   3597       1.8  christos cleanup:
   3598  1.15.2.1  perseant 	return result;
   3599       1.1  christos }
   3600       1.1  christos static cfg_type_t cfg_type_server_key_kludge = {
   3601       1.8  christos 	"server_key", parse_server_key_kludge, NULL, cfg_doc_terminal, NULL,
   3602       1.8  christos 	NULL
   3603       1.1  christos };
   3604       1.1  christos 
   3605       1.1  christos /*%
   3606       1.1  christos  * An optional logging facility.
   3607       1.1  christos  */
   3608       1.1  christos 
   3609       1.1  christos static isc_result_t
   3610       1.1  christos parse_optional_facility(cfg_parser_t *pctx, const cfg_type_t *type,
   3611       1.8  christos 			cfg_obj_t **ret) {
   3612       1.1  christos 	isc_result_t result;
   3613       1.1  christos 	UNUSED(type);
   3614       1.1  christos 
   3615       1.1  christos 	CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
   3616       1.1  christos 	if (pctx->token.type == isc_tokentype_string ||
   3617       1.8  christos 	    pctx->token.type == isc_tokentype_qstring)
   3618       1.8  christos 	{
   3619       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
   3620       1.1  christos 	} else {
   3621       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
   3622       1.1  christos 	}
   3623       1.8  christos cleanup:
   3624  1.15.2.1  perseant 	return result;
   3625       1.1  christos }
   3626       1.1  christos 
   3627       1.1  christos static void
   3628       1.1  christos doc_optional_facility(cfg_printer_t *pctx, const cfg_type_t *type) {
   3629       1.1  christos 	UNUSED(type);
   3630       1.1  christos 	cfg_print_cstr(pctx, "[ <syslog_facility> ]");
   3631       1.1  christos }
   3632       1.1  christos 
   3633       1.8  christos static cfg_type_t cfg_type_optional_facility = { "optional_facility",
   3634       1.8  christos 						 parse_optional_facility,
   3635       1.8  christos 						 NULL,
   3636       1.8  christos 						 doc_optional_facility,
   3637       1.8  christos 						 NULL,
   3638       1.8  christos 						 NULL };
   3639       1.1  christos 
   3640       1.1  christos /*%
   3641       1.1  christos  * A log severity.  Return as a string, except "debug N",
   3642       1.1  christos  * which is returned as a keyword object.
   3643       1.1  christos  */
   3644       1.1  christos 
   3645       1.1  christos static keyword_type_t debug_kw = { "debug", &cfg_type_uint32 };
   3646       1.8  christos static cfg_type_t cfg_type_debuglevel = { "debuglevel",	   parse_keyvalue,
   3647       1.8  christos 					  print_keyvalue,  doc_keyvalue,
   3648       1.8  christos 					  &cfg_rep_uint32, &debug_kw };
   3649       1.1  christos 
   3650       1.1  christos static isc_result_t
   3651       1.8  christos parse_logseverity(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3652       1.1  christos 	isc_result_t result;
   3653       1.1  christos 	UNUSED(type);
   3654       1.1  christos 
   3655       1.1  christos 	CHECK(cfg_peektoken(pctx, 0));
   3656       1.1  christos 	if (pctx->token.type == isc_tokentype_string &&
   3657       1.8  christos 	    strcasecmp(TOKEN_STRING(pctx), "debug") == 0)
   3658       1.8  christos 	{
   3659       1.1  christos 		CHECK(cfg_gettoken(pctx, 0)); /* read "debug" */
   3660       1.1  christos 		CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER));
   3661       1.1  christos 		if (pctx->token.type == isc_tokentype_number) {
   3662       1.1  christos 			CHECK(cfg_parse_uint32(pctx, NULL, ret));
   3663       1.1  christos 		} else {
   3664       1.1  christos 			/*
   3665       1.1  christos 			 * The debug level is optional and defaults to 1.
   3666       1.1  christos 			 * This makes little sense, but we support it for
   3667       1.1  christos 			 * compatibility with BIND 8.
   3668       1.1  christos 			 */
   3669       1.1  christos 			CHECK(cfg_create_obj(pctx, &cfg_type_uint32, ret));
   3670       1.1  christos 			(*ret)->value.uint32 = 1;
   3671       1.1  christos 		}
   3672       1.1  christos 		(*ret)->type = &cfg_type_debuglevel; /* XXX kludge */
   3673       1.1  christos 	} else {
   3674       1.1  christos 		CHECK(cfg_parse_obj(pctx, &cfg_type_loglevel, ret));
   3675       1.1  christos 	}
   3676       1.8  christos cleanup:
   3677  1.15.2.1  perseant 	return result;
   3678       1.1  christos }
   3679       1.1  christos 
   3680       1.8  christos static cfg_type_t cfg_type_logseverity = { "log_severity", parse_logseverity,
   3681       1.8  christos 					   NULL,	   cfg_doc_terminal,
   3682       1.8  christos 					   NULL,	   NULL };
   3683       1.1  christos 
   3684       1.1  christos /*%
   3685       1.1  christos  * The "file" clause of the "channel" statement.
   3686       1.1  christos  * This is yet another special case.
   3687       1.1  christos  */
   3688       1.1  christos 
   3689       1.1  christos static const char *logversions_enums[] = { "unlimited", NULL };
   3690       1.1  christos static isc_result_t
   3691       1.8  christos parse_logversions(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3692  1.15.2.1  perseant 	return cfg_parse_enum_or_other(pctx, type, &cfg_type_uint32, ret);
   3693       1.1  christos }
   3694       1.1  christos 
   3695       1.1  christos static void
   3696       1.1  christos doc_logversions(cfg_printer_t *pctx, const cfg_type_t *type) {
   3697       1.3  christos 	cfg_doc_enum_or_other(pctx, type, &cfg_type_uint32);
   3698       1.1  christos }
   3699       1.1  christos 
   3700       1.1  christos static cfg_type_t cfg_type_logversions = {
   3701       1.8  christos 	"logversions",	 parse_logversions, cfg_print_ustring,
   3702       1.8  christos 	doc_logversions, &cfg_rep_string,   logversions_enums
   3703       1.1  christos };
   3704       1.1  christos 
   3705       1.1  christos static const char *logsuffix_enums[] = { "increment", "timestamp", NULL };
   3706       1.8  christos static cfg_type_t cfg_type_logsuffix = { "logsuffix",	    cfg_parse_enum,
   3707       1.8  christos 					 cfg_print_ustring, cfg_doc_enum,
   3708       1.8  christos 					 &cfg_rep_string,   &logsuffix_enums };
   3709       1.1  christos 
   3710       1.1  christos static cfg_tuplefielddef_t logfile_fields[] = {
   3711       1.1  christos 	{ "file", &cfg_type_qstring, 0 },
   3712       1.1  christos 	{ "versions", &cfg_type_logversions, 0 },
   3713       1.1  christos 	{ "size", &cfg_type_size, 0 },
   3714       1.1  christos 	{ "suffix", &cfg_type_logsuffix, 0 },
   3715       1.1  christos 	{ NULL, NULL, 0 }
   3716       1.1  christos };
   3717       1.1  christos 
   3718       1.1  christos static isc_result_t
   3719       1.1  christos parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
   3720       1.1  christos 	isc_result_t result;
   3721       1.1  christos 	cfg_obj_t *obj = NULL;
   3722       1.1  christos 	const cfg_tuplefielddef_t *fields = type->of;
   3723       1.1  christos 
   3724       1.1  christos 	CHECK(cfg_create_tuple(pctx, type, &obj));
   3725       1.1  christos 
   3726       1.1  christos 	/* Parse the mandatory "file" field */
   3727       1.1  christos 	CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
   3728       1.1  christos 
   3729       1.1  christos 	/* Parse "versions" and "size" fields in any order. */
   3730       1.1  christos 	for (;;) {
   3731       1.1  christos 		CHECK(cfg_peektoken(pctx, 0));
   3732       1.1  christos 		if (pctx->token.type == isc_tokentype_string) {
   3733       1.1  christos 			CHECK(cfg_gettoken(pctx, 0));
   3734       1.8  christos 			if (strcasecmp(TOKEN_STRING(pctx), "versions") == 0 &&
   3735       1.8  christos 			    obj->value.tuple[1] == NULL)
   3736       1.8  christos 			{
   3737       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[1].type,
   3738       1.8  christos 						    &obj->value.tuple[1]));
   3739       1.8  christos 			} else if (strcasecmp(TOKEN_STRING(pctx), "size") ==
   3740       1.8  christos 					   0 &&
   3741       1.8  christos 				   obj->value.tuple[2] == NULL)
   3742       1.8  christos 			{
   3743       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[2].type,
   3744       1.8  christos 						    &obj->value.tuple[2]));
   3745       1.8  christos 			} else if (strcasecmp(TOKEN_STRING(pctx), "suffix") ==
   3746       1.8  christos 					   0 &&
   3747       1.8  christos 				   obj->value.tuple[3] == NULL)
   3748       1.8  christos 			{
   3749       1.1  christos 				CHECK(cfg_parse_obj(pctx, fields[3].type,
   3750       1.8  christos 						    &obj->value.tuple[3]));
   3751       1.1  christos 			} else {
   3752       1.1  christos 				break;
   3753       1.1  christos 			}
   3754       1.1  christos 		} else {
   3755       1.1  christos 			break;
   3756       1.1  christos 		}
   3757       1.1  christos 	}
   3758       1.1  christos 
   3759       1.1  christos 	/* Create void objects for missing optional values. */
   3760       1.8  christos 	if (obj->value.tuple[1] == NULL) {
   3761       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
   3762       1.8  christos 	}
   3763       1.8  christos 	if (obj->value.tuple[2] == NULL) {
   3764       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
   3765       1.8  christos 	}
   3766       1.8  christos 	if (obj->value.tuple[3] == NULL) {
   3767       1.1  christos 		CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[3]));
   3768       1.8  christos 	}
   3769       1.1  christos 
   3770       1.1  christos 	*ret = obj;
   3771  1.15.2.1  perseant 	return ISC_R_SUCCESS;
   3772       1.1  christos 
   3773       1.8  christos cleanup:
   3774       1.1  christos 	CLEANUP_OBJ(obj);
   3775  1.15.2.1  perseant 	return result;
   3776       1.1  christos }
   3777       1.1  christos 
   3778       1.1  christos static void
   3779       1.1  christos print_logfile(cfg_printer_t *pctx, const cfg_obj_t *obj) {
   3780       1.1  christos 	cfg_print_obj(pctx, obj->value.tuple[0]); /* file */
   3781       1.1  christos 	if (obj->value.tuple[1]->type->print != cfg_print_void) {
   3782       1.1  christos 		cfg_print_cstr(pctx, " versions ");
   3783       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[1]);
   3784       1.1  christos 	}
   3785       1.1  christos 	if (obj->value.tuple[2]->type->print != cfg_print_void) {
   3786       1.1  christos 		cfg_print_cstr(pctx, " size ");
   3787       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[2]);
   3788       1.1  christos 	}
   3789       1.1  christos 	if (obj->value.tuple[3]->type->print != cfg_print_void) {
   3790       1.1  christos 		cfg_print_cstr(pctx, " suffix ");
   3791       1.1  christos 		cfg_print_obj(pctx, obj->value.tuple[3]);
   3792       1.1  christos 	}
   3793       1.1  christos }
   3794       1.1  christos 
   3795       1.1  christos static void
   3796       1.1  christos doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
   3797       1.1  christos 	UNUSED(type);
   3798       1.1  christos 	cfg_print_cstr(pctx, "<quoted_string>");
   3799       1.1  christos 	cfg_print_cstr(pctx, " ");
   3800       1.1  christos 	cfg_print_cstr(pctx, "[ versions ( unlimited | <integer> ) ]");
   3801       1.1  christos 	cfg_print_cstr(pctx, " ");
   3802       1.1  christos 	cfg_print_cstr(pctx, "[ size <size> ]");
   3803       1.1  christos 	cfg_print_cstr(pctx, " ");
   3804       1.1  christos 	cfg_print_cstr(pctx, "[ suffix ( increment | timestamp ) ]");
   3805       1.1  christos }
   3806       1.1  christos 
   3807       1.8  christos static cfg_type_t cfg_type_logfile = { "log_file",     parse_logfile,
   3808       1.8  christos 				       print_logfile,  doc_logfile,
   3809       1.8  christos 				       &cfg_rep_tuple, logfile_fields };
   3810       1.1  christos 
   3811      1.15  christos /*% An IPv4 address, "*" accepted as wildcard. */
   3812       1.1  christos static cfg_type_t cfg_type_sockaddr4wild = {
   3813       1.8  christos 	"sockaddr4wild",  cfg_parse_sockaddr, cfg_print_sockaddr,
   3814       1.8  christos 	cfg_doc_sockaddr, &cfg_rep_sockaddr,  &sockaddr4wild_flags
   3815       1.1  christos };
   3816       1.1  christos 
   3817      1.15  christos /*% An IPv6 address, "*" accepted as wildcard. */
   3818       1.1  christos static cfg_type_t cfg_type_sockaddr6wild = {
   3819       1.1  christos 	"v6addrportwild", cfg_parse_sockaddr, cfg_print_sockaddr,
   3820       1.8  christos 	cfg_doc_sockaddr, &cfg_rep_sockaddr,  &sockaddr6wild_flags
   3821       1.1  christos };
   3822       1.1  christos 
   3823  1.15.2.1  perseant static keyword_type_t sourceaddr4_kw = { "source", &cfg_type_sockaddr4wild };
   3824  1.15.2.1  perseant 
   3825  1.15.2.1  perseant static cfg_type_t cfg_type_optional_sourceaddr4 = {
   3826  1.15.2.1  perseant 	"optional_sourceaddr4", parse_optional_keyvalue, print_keyvalue,
   3827  1.15.2.1  perseant 	doc_optional_keyvalue,	&cfg_rep_sockaddr,	 &sourceaddr4_kw
   3828  1.15.2.1  perseant };
   3829  1.15.2.1  perseant 
   3830  1.15.2.1  perseant static keyword_type_t sourceaddr6_kw = { "source-v6", &cfg_type_sockaddr6wild };
   3831  1.15.2.1  perseant 
   3832  1.15.2.1  perseant static cfg_type_t cfg_type_optional_sourceaddr6 = {
   3833  1.15.2.1  perseant 	"optional_sourceaddr6", parse_optional_keyvalue, print_keyvalue,
   3834  1.15.2.1  perseant 	doc_optional_keyvalue,	&cfg_rep_sockaddr,	 &sourceaddr6_kw
   3835  1.15.2.1  perseant };
   3836  1.15.2.1  perseant 
   3837       1.1  christos /*%
   3838       1.1  christos  * rndc
   3839       1.1  christos  */
   3840       1.1  christos 
   3841       1.8  christos static cfg_clausedef_t rndcconf_options_clauses[] = {
   3842       1.1  christos 	{ "default-key", &cfg_type_astring, 0 },
   3843       1.1  christos 	{ "default-port", &cfg_type_uint32, 0 },
   3844       1.1  christos 	{ "default-server", &cfg_type_astring, 0 },
   3845       1.1  christos 	{ "default-source-address", &cfg_type_netaddr4wild, 0 },
   3846       1.1  christos 	{ "default-source-address-v6", &cfg_type_netaddr6wild, 0 },
   3847       1.1  christos 	{ NULL, NULL, 0 }
   3848       1.1  christos };
   3849       1.1  christos 
   3850       1.8  christos static cfg_clausedef_t *rndcconf_options_clausesets[] = {
   3851       1.8  christos 	rndcconf_options_clauses, NULL
   3852       1.1  christos };
   3853       1.1  christos 
   3854       1.1  christos static cfg_type_t cfg_type_rndcconf_options = {
   3855       1.8  christos 	"rndcconf_options", cfg_parse_map, cfg_print_map,
   3856       1.8  christos 	cfg_doc_map,	    &cfg_rep_map,  rndcconf_options_clausesets
   3857       1.1  christos };
   3858       1.1  christos 
   3859       1.8  christos static cfg_clausedef_t rndcconf_server_clauses[] = {
   3860       1.1  christos 	{ "key", &cfg_type_astring, 0 },
   3861       1.1  christos 	{ "port", &cfg_type_uint32, 0 },
   3862       1.1  christos 	{ "source-address", &cfg_type_netaddr4wild, 0 },
   3863       1.1  christos 	{ "source-address-v6", &cfg_type_netaddr6wild, 0 },
   3864       1.1  christos 	{ "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
   3865       1.1  christos 	{ NULL, NULL, 0 }
   3866       1.1  christos };
   3867       1.1  christos 
   3868       1.8  christos static cfg_clausedef_t *rndcconf_server_clausesets[] = {
   3869       1.8  christos 	rndcconf_server_clauses, NULL
   3870       1.1  christos };
   3871       1.1  christos 
   3872       1.1  christos static cfg_type_t cfg_type_rndcconf_server = {
   3873       1.8  christos 	"rndcconf_server", cfg_parse_named_map, cfg_print_map,
   3874       1.8  christos 	cfg_doc_map,	   &cfg_rep_map,	rndcconf_server_clausesets
   3875       1.1  christos };
   3876       1.1  christos 
   3877       1.8  christos static cfg_clausedef_t rndcconf_clauses[] = {
   3878       1.1  christos 	{ "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
   3879       1.1  christos 	{ "server", &cfg_type_rndcconf_server, CFG_CLAUSEFLAG_MULTI },
   3880       1.1  christos 	{ "options", &cfg_type_rndcconf_options, 0 },
   3881       1.1  christos 	{ NULL, NULL, 0 }
   3882       1.1  christos };
   3883       1.1  christos 
   3884       1.8  christos static cfg_clausedef_t *rndcconf_clausesets[] = { rndcconf_clauses, NULL };
   3885       1.1  christos 
   3886      1.15  christos cfg_type_t cfg_type_rndcconf = { "rndcconf",	    cfg_parse_mapbody,
   3887      1.15  christos 				 cfg_print_mapbody, cfg_doc_mapbody,
   3888      1.15  christos 				 &cfg_rep_map,	    rndcconf_clausesets };
   3889       1.1  christos 
   3890       1.8  christos static cfg_clausedef_t rndckey_clauses[] = { { "key", &cfg_type_key, 0 },
   3891       1.8  christos 					     { NULL, NULL, 0 } };
   3892       1.1  christos 
   3893       1.8  christos static cfg_clausedef_t *rndckey_clausesets[] = { rndckey_clauses, NULL };
   3894       1.1  christos 
   3895      1.15  christos cfg_type_t cfg_type_rndckey = { "rndckey",	   cfg_parse_mapbody,
   3896      1.15  christos 				cfg_print_mapbody, cfg_doc_mapbody,
   3897      1.15  christos 				&cfg_rep_map,	   rndckey_clausesets };
   3898       1.1  christos 
   3899       1.1  christos /*
   3900       1.1  christos  * session.key has exactly the same syntax as rndc.key, but it's defined
   3901       1.1  christos  * separately for clarity (and so we can extend it someday, if needed).
   3902       1.1  christos  */
   3903      1.15  christos cfg_type_t cfg_type_sessionkey = { "sessionkey",      cfg_parse_mapbody,
   3904      1.15  christos 				   cfg_print_mapbody, cfg_doc_mapbody,
   3905      1.15  christos 				   &cfg_rep_map,      rndckey_clausesets };
   3906       1.1  christos 
   3907       1.1  christos static cfg_tuplefielddef_t nameport_fields[] = {
   3908       1.1  christos 	{ "name", &cfg_type_astring, 0 },
   3909       1.1  christos 	{ "port", &cfg_type_optional_port, 0 },
   3910       1.1  christos 	{ NULL, NULL, 0 }
   3911       1.1  christos };
   3912       1.1  christos 
   3913       1.8  christos static cfg_type_t cfg_type_nameport = { "nameport",	 cfg_parse_tuple,
   3914       1.8  christos 					cfg_print_tuple, cfg_doc_tuple,
   3915       1.8  christos 					&cfg_rep_tuple,	 nameport_fields };
   3916       1.1  christos 
   3917       1.1  christos static void
   3918       1.1  christos doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
   3919       1.1  christos 	UNUSED(type);
   3920       1.1  christos 	cfg_print_cstr(pctx, "( ");
   3921       1.1  christos 	cfg_print_cstr(pctx, "<quoted_string>");
   3922       1.1  christos 	cfg_print_cstr(pctx, " ");
   3923       1.1  christos 	cfg_print_cstr(pctx, "[ port <integer> ]");
   3924       1.1  christos 	cfg_print_cstr(pctx, " | ");
   3925       1.1  christos 	cfg_print_cstr(pctx, "<ipv4_address>");
   3926       1.1  christos 	cfg_print_cstr(pctx, " ");
   3927       1.1  christos 	cfg_print_cstr(pctx, "[ port <integer> ]");
   3928       1.1  christos 	cfg_print_cstr(pctx, " | ");
   3929       1.1  christos 	cfg_print_cstr(pctx, "<ipv6_address>");
   3930       1.1  christos 	cfg_print_cstr(pctx, " ");
   3931       1.1  christos 	cfg_print_cstr(pctx, "[ port <integer> ]");
   3932       1.1  christos 	cfg_print_cstr(pctx, " )");
   3933       1.1  christos }
   3934       1.1  christos 
   3935       1.1  christos static isc_result_t
   3936       1.1  christos parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
   3937       1.8  christos 		       cfg_obj_t **ret) {
   3938       1.1  christos 	isc_result_t result;
   3939       1.1  christos 	UNUSED(type);
   3940       1.1  christos 
   3941       1.1  christos 	CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
   3942       1.1  christos 	if (pctx->token.type == isc_tokentype_string ||
   3943       1.8  christos 	    pctx->token.type == isc_tokentype_qstring)
   3944       1.8  christos 	{
   3945       1.1  christos 		if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
   3946       1.8  christos 		{
   3947       1.1  christos 			CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr,
   3948       1.1  christos 						 ret));
   3949       1.8  christos 		} else {
   3950  1.15.2.1  perseant 			CHECK(cfg_parse_tuple(pctx, &cfg_type_nameport, ret));
   3951       1.1  christos 		}
   3952       1.1  christos 	} else {
   3953       1.1  christos 		cfg_parser_error(pctx, CFG_LOG_NEAR,
   3954       1.8  christos 				 "expected IP address or hostname");
   3955  1.15.2.1  perseant 		return ISC_R_UNEXPECTEDTOKEN;
   3956       1.1  christos 	}
   3957       1.8  christos cleanup:
   3958  1.15.2.1  perseant 	return result;
   3959       1.1  christos }
   3960       1.1  christos 
   3961       1.8  christos static cfg_type_t cfg_type_sockaddrnameport = { "sockaddrnameport_element",
   3962       1.8  christos 						parse_sockaddrnameport,
   3963       1.8  christos 						NULL,
   3964       1.8  christos 						doc_sockaddrnameport,
   3965       1.8  christos 						NULL,
   3966       1.8  christos 						NULL };
   3967       1.1  christos 
   3968       1.1  christos static cfg_type_t cfg_type_bracketed_sockaddrnameportlist = {
   3969       1.8  christos 	"bracketed_sockaddrnameportlist",
   3970       1.8  christos 	cfg_parse_bracketed_list,
   3971       1.8  christos 	cfg_print_bracketed_list,
   3972       1.8  christos 	cfg_doc_bracketed_list,
   3973       1.8  christos 	&cfg_rep_list,
   3974       1.8  christos 	&cfg_type_sockaddrnameport
   3975       1.1  christos };
   3976       1.1  christos 
   3977       1.1  christos /*%
   3978       1.1  christos  * A list of socket addresses or name with an optional default port,
   3979       1.1  christos  * as used in the dual-stack-servers option.  E.g.,
   3980       1.1  christos  * "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
   3981       1.1  christos  */
   3982       1.1  christos static cfg_tuplefielddef_t nameportiplist_fields[] = {
   3983       1.1  christos 	{ "port", &cfg_type_optional_port, 0 },
   3984       1.1  christos 	{ "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
   3985       1.1  christos 	{ NULL, NULL, 0 }
   3986       1.1  christos };
   3987       1.1  christos 
   3988       1.1  christos static cfg_type_t cfg_type_nameportiplist = {
   3989       1.8  christos 	"nameportiplist", cfg_parse_tuple, cfg_print_tuple,
   3990       1.8  christos 	cfg_doc_tuple,	  &cfg_rep_tuple,  nameportiplist_fields
   3991       1.1  christos };
   3992       1.1  christos 
   3993       1.1  christos /*%
   3994      1.15  christos  * remote servers element.
   3995       1.1  christos  */
   3996       1.1  christos 
   3997       1.1  christos static void
   3998      1.12  christos doc_remoteselement(cfg_printer_t *pctx, const cfg_type_t *type) {
   3999       1.1  christos 	UNUSED(type);
   4000       1.1  christos 	cfg_print_cstr(pctx, "( ");
   4001  1.15.2.1  perseant 	cfg_print_cstr(pctx, "<server-list>");
   4002       1.1  christos 	cfg_print_cstr(pctx, " | ");
   4003       1.1  christos 	cfg_print_cstr(pctx, "<ipv4_address>");
   4004       1.1  christos 	cfg_print_cstr(pctx, " ");
   4005       1.1  christos 	cfg_print_cstr(pctx, "[ port <integer> ]");
   4006       1.1  christos 	cfg_print_cstr(pctx, " | ");
   4007       1.1  christos 	cfg_print_cstr(pctx, "<ipv6_address>");
   4008       1.1  christos 	cfg_print_cstr(pctx, " ");
   4009       1.1  christos 	cfg_print_cstr(pctx, "[ port <integer> ]");
   4010       1.1  christos 	cfg_print_cstr(pctx, " )");
   4011       1.1  christos }
   4012       1.1  christos 
   4013       1.1  christos static isc_result_t
   4014      1.12  christos parse_remoteselement(cfg_parser_t *pctx, const cfg_type_t *type,
   4015      1.12  christos 		     cfg_obj_t **ret) {
   4016       1.1  christos 	isc_result_t result;
   4017       1.1  christos 	cfg_obj_t *obj = NULL;
   4018       1.1  christos 	UNUSED(type);
   4019       1.1  christos 
   4020       1.1  christos 	CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
   4021       1.1  christos 	if (pctx->token.type == isc_tokentype_string ||
   4022       1.8  christos 	    pctx->token.type == isc_tokentype_qstring)
   4023       1.8  christos 	{
   4024       1.1  christos 		if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
   4025       1.8  christos 		{
   4026       1.1  christos 			CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr,
   4027       1.8  christos 						 ret));
   4028       1.8  christos 		} else {
   4029       1.1  christos 			CHECK(cfg_parse_astring(pctx, &cfg_type_astring, ret));
   4030       1.8  christos 		}
   4031       1.1  christos 	} else {
   4032       1.1  christos 		cfg_parser_error(pctx, CFG_LOG_NEAR,
   4033      1.12  christos 				 "expected IP address or remote servers list "
   4034      1.12  christos 				 "name");
   4035  1.15.2.1  perseant 		return ISC_R_UNEXPECTEDTOKEN;
   4036       1.1  christos 	}
   4037       1.8  christos cleanup:
   4038       1.1  christos 	CLEANUP_OBJ(obj);
   4039  1.15.2.1  perseant 	return result;
   4040       1.1  christos }
   4041       1.1  christos 
   4042      1.12  christos static cfg_type_t cfg_type_remoteselement = { "remotes_element",
   4043      1.12  christos 					      parse_remoteselement,
   4044      1.12  christos 					      NULL,
   4045      1.12  christos 					      doc_remoteselement,
   4046      1.12  christos 					      NULL,
   4047      1.12  christos 					      NULL };
   4048       1.1  christos 
   4049       1.8  christos static int
   4050       1.8  christos cmp_clause(const void *ap, const void *bp) {
   4051       1.1  christos 	const cfg_clausedef_t *a = (const cfg_clausedef_t *)ap;
   4052       1.1  christos 	const cfg_clausedef_t *b = (const cfg_clausedef_t *)bp;
   4053  1.15.2.1  perseant 	return strcmp(a->name, b->name);
   4054       1.1  christos }
   4055       1.1  christos 
   4056       1.3  christos bool
   4057       1.1  christos cfg_clause_validforzone(const char *name, unsigned int ztype) {
   4058       1.1  christos 	const cfg_clausedef_t *clause;
   4059       1.3  christos 	bool valid = false;
   4060       1.1  christos 
   4061       1.1  christos 	for (clause = zone_clauses; clause->name != NULL; clause++) {
   4062       1.1  christos 		if ((clause->flags & ztype) == 0 ||
   4063      1.14  christos 		    strcmp(clause->name, name) != 0)
   4064      1.14  christos 		{
   4065       1.1  christos 			continue;
   4066       1.1  christos 		}
   4067       1.3  christos 		valid = true;
   4068       1.1  christos 	}
   4069       1.1  christos 	for (clause = zone_only_clauses; clause->name != NULL; clause++) {
   4070       1.1  christos 		if ((clause->flags & ztype) == 0 ||
   4071      1.14  christos 		    strcmp(clause->name, name) != 0)
   4072      1.14  christos 		{
   4073       1.1  christos 			continue;
   4074       1.1  christos 		}
   4075       1.3  christos 		valid = true;
   4076       1.1  christos 	}
   4077       1.1  christos 
   4078  1.15.2.1  perseant 	return valid;
   4079       1.1  christos }
   4080       1.1  christos 
   4081       1.1  christos void
   4082       1.8  christos cfg_print_zonegrammar(const unsigned int zonetype, unsigned int flags,
   4083       1.1  christos 		      void (*f)(void *closure, const char *text, int textlen),
   4084       1.8  christos 		      void *closure) {
   4085       1.8  christos #define NCLAUSES                                               \
   4086       1.1  christos 	(((sizeof(zone_clauses) + sizeof(zone_only_clauses)) / \
   4087       1.8  christos 	  sizeof(clause[0])) -                                 \
   4088       1.8  christos 	 1)
   4089       1.1  christos 
   4090       1.1  christos 	cfg_printer_t pctx;
   4091       1.1  christos 	cfg_clausedef_t *clause = NULL;
   4092       1.1  christos 	cfg_clausedef_t clauses[NCLAUSES];
   4093       1.1  christos 
   4094       1.1  christos 	pctx.f = f;
   4095       1.1  christos 	pctx.closure = closure;
   4096       1.1  christos 	pctx.indent = 0;
   4097       1.8  christos 	pctx.flags = flags;
   4098       1.1  christos 
   4099       1.1  christos 	memmove(clauses, zone_clauses, sizeof(zone_clauses));
   4100       1.8  christos 	memmove(clauses + sizeof(zone_clauses) / sizeof(zone_clauses[0]) - 1,
   4101       1.1  christos 		zone_only_clauses, sizeof(zone_only_clauses));
   4102       1.1  christos 	qsort(clauses, NCLAUSES - 1, sizeof(clause[0]), cmp_clause);
   4103       1.1  christos 
   4104       1.1  christos 	cfg_print_cstr(&pctx, "zone <string> [ <class> ] {\n");
   4105       1.1  christos 	pctx.indent++;
   4106       1.1  christos 
   4107       1.1  christos 	switch (zonetype) {
   4108      1.13  christos 	case CFG_ZONE_PRIMARY:
   4109       1.1  christos 		cfg_print_indent(&pctx);
   4110      1.15  christos 		cfg_print_cstr(&pctx, "type primary;\n");
   4111       1.1  christos 		break;
   4112      1.13  christos 	case CFG_ZONE_SECONDARY:
   4113       1.1  christos 		cfg_print_indent(&pctx);
   4114      1.15  christos 		cfg_print_cstr(&pctx, "type secondary;\n");
   4115       1.1  christos 		break;
   4116       1.3  christos 	case CFG_ZONE_MIRROR:
   4117       1.3  christos 		cfg_print_indent(&pctx);
   4118       1.3  christos 		cfg_print_cstr(&pctx, "type mirror;\n");
   4119       1.3  christos 		break;
   4120       1.1  christos 	case CFG_ZONE_STUB:
   4121       1.1  christos 		cfg_print_indent(&pctx);
   4122       1.1  christos 		cfg_print_cstr(&pctx, "type stub;\n");
   4123       1.1  christos 		break;
   4124       1.1  christos 	case CFG_ZONE_HINT:
   4125       1.1  christos 		cfg_print_indent(&pctx);
   4126       1.1  christos 		cfg_print_cstr(&pctx, "type hint;\n");
   4127       1.1  christos 		break;
   4128       1.1  christos 	case CFG_ZONE_FORWARD:
   4129       1.1  christos 		cfg_print_indent(&pctx);
   4130       1.1  christos 		cfg_print_cstr(&pctx, "type forward;\n");
   4131       1.1  christos 		break;
   4132       1.1  christos 	case CFG_ZONE_STATICSTUB:
   4133       1.1  christos 		cfg_print_indent(&pctx);
   4134       1.1  christos 		cfg_print_cstr(&pctx, "type static-stub;\n");
   4135       1.1  christos 		break;
   4136       1.1  christos 	case CFG_ZONE_REDIRECT:
   4137       1.1  christos 		cfg_print_indent(&pctx);
   4138       1.1  christos 		cfg_print_cstr(&pctx, "type redirect;\n");
   4139       1.1  christos 		break;
   4140       1.1  christos 	case CFG_ZONE_INVIEW:
   4141       1.1  christos 		/* no zone type is specified for these */
   4142       1.1  christos 		break;
   4143       1.1  christos 	default:
   4144      1.13  christos 		UNREACHABLE();
   4145       1.1  christos 	}
   4146       1.1  christos 
   4147       1.1  christos 	for (clause = clauses; clause->name != NULL; clause++) {
   4148       1.8  christos 		if (((pctx.flags & CFG_PRINTER_ACTIVEONLY) != 0) &&
   4149       1.8  christos 		    (((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0) ||
   4150       1.8  christos 		     ((clause->flags & CFG_CLAUSEFLAG_TESTONLY) != 0)))
   4151       1.8  christos 		{
   4152       1.8  christos 			continue;
   4153       1.8  christos 		}
   4154      1.15  christos 		if ((clause->flags & CFG_CLAUSEFLAG_ANCIENT) != 0 ||
   4155      1.15  christos 		    (clause->flags & CFG_CLAUSEFLAG_NODOC) != 0)
   4156      1.15  christos 		{
   4157      1.15  christos 			continue;
   4158      1.15  christos 		}
   4159      1.15  christos 
   4160       1.1  christos 		if ((clause->flags & zonetype) == 0 ||
   4161      1.14  christos 		    strcasecmp(clause->name, "type") == 0)
   4162      1.14  christos 		{
   4163       1.1  christos 			continue;
   4164       1.1  christos 		}
   4165       1.1  christos 		cfg_print_indent(&pctx);
   4166       1.1  christos 		cfg_print_cstr(&pctx, clause->name);
   4167       1.1  christos 		cfg_print_cstr(&pctx, " ");
   4168       1.1  christos 		cfg_doc_obj(&pctx, clause->type);
   4169       1.1  christos 		cfg_print_cstr(&pctx, ";");
   4170       1.1  christos 		cfg_print_clauseflags(&pctx, clause->flags);
   4171       1.1  christos 		cfg_print_cstr(&pctx, "\n");
   4172       1.1  christos 	}
   4173       1.1  christos 
   4174       1.1  christos 	pctx.indent--;
   4175       1.1  christos 	cfg_print_cstr(&pctx, "};\n");
   4176       1.1  christos }
   4177      1.15  christos 
   4178      1.15  christos /*%
   4179      1.15  christos  * "tls" and related statement syntax.
   4180      1.15  christos  */
   4181      1.15  christos static cfg_type_t cfg_type_tlsprotos = { "tls_protocols",
   4182      1.15  christos 					 cfg_parse_bracketed_list,
   4183      1.15  christos 					 cfg_print_bracketed_list,
   4184      1.15  christos 					 cfg_doc_bracketed_list,
   4185      1.15  christos 					 &cfg_rep_list,
   4186      1.15  christos 					 &cfg_type_astring };
   4187      1.15  christos 
   4188      1.15  christos static cfg_clausedef_t tls_clauses[] = {
   4189      1.15  christos 	{ "key-file", &cfg_type_qstring, 0 },
   4190      1.15  christos 	{ "cert-file", &cfg_type_qstring, 0 },
   4191      1.15  christos 	{ "ca-file", &cfg_type_qstring, 0 },
   4192      1.15  christos 	{ "remote-hostname", &cfg_type_qstring, 0 },
   4193      1.15  christos 	{ "dhparam-file", &cfg_type_qstring, 0 },
   4194      1.15  christos 	{ "protocols", &cfg_type_tlsprotos, 0 },
   4195      1.15  christos 	{ "ciphers", &cfg_type_astring, 0 },
   4196  1.15.2.1  perseant #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
   4197  1.15.2.1  perseant 	{ "cipher-suites", &cfg_type_astring, 0 },
   4198  1.15.2.1  perseant #else
   4199  1.15.2.1  perseant 	{ "cipher-suites", &cfg_type_astring, CFG_CLAUSEFLAG_NOTCONFIGURED },
   4200  1.15.2.1  perseant #endif
   4201      1.15  christos 	{ "prefer-server-ciphers", &cfg_type_boolean, 0 },
   4202      1.15  christos 	{ "session-tickets", &cfg_type_boolean, 0 },
   4203      1.15  christos 	{ NULL, NULL, 0 }
   4204      1.15  christos };
   4205      1.15  christos 
   4206      1.15  christos static cfg_clausedef_t *tls_clausesets[] = { tls_clauses, NULL };
   4207      1.15  christos static cfg_type_t cfg_type_tlsconf = { "tlsconf",     cfg_parse_named_map,
   4208      1.15  christos 				       cfg_print_map, cfg_doc_map,
   4209      1.15  christos 				       &cfg_rep_map,  tls_clausesets };
   4210      1.15  christos 
   4211      1.15  christos static keyword_type_t tls_kw = { "tls", &cfg_type_astring };
   4212      1.15  christos static cfg_type_t cfg_type_optional_tls = {
   4213      1.15  christos 	"tlsoptional",	       parse_optional_keyvalue, print_keyvalue,
   4214      1.15  christos 	doc_optional_keyvalue, &cfg_rep_string,		&tls_kw
   4215      1.15  christos };
   4216      1.15  christos 
   4217      1.15  christos /* http and https */
   4218      1.15  christos 
   4219      1.15  christos static cfg_type_t cfg_type_bracketed_http_endpoint_list = {
   4220      1.15  christos 	"bracketed_http_endpoint_list",
   4221      1.15  christos 	cfg_parse_bracketed_list,
   4222      1.15  christos 	cfg_print_bracketed_list,
   4223      1.15  christos 	cfg_doc_bracketed_list,
   4224      1.15  christos 	&cfg_rep_list,
   4225      1.15  christos 	&cfg_type_qstring
   4226      1.15  christos };
   4227      1.15  christos 
   4228      1.15  christos static cfg_clausedef_t cfg_http_description_clauses[] = {
   4229      1.15  christos 	{ "endpoints", &cfg_type_bracketed_http_endpoint_list, 0 },
   4230      1.15  christos 	{ "listener-clients", &cfg_type_uint32, 0 },
   4231      1.15  christos 	{ "streams-per-connection", &cfg_type_uint32, 0 },
   4232      1.15  christos 	{ NULL, NULL, 0 }
   4233      1.15  christos };
   4234      1.15  christos 
   4235      1.15  christos static cfg_clausedef_t *http_description_clausesets[] = {
   4236      1.15  christos 	cfg_http_description_clauses, NULL
   4237      1.15  christos };
   4238      1.15  christos 
   4239      1.15  christos static cfg_type_t cfg_type_http_description = {
   4240      1.15  christos 	"http_desc", cfg_parse_named_map, cfg_print_map,
   4241      1.15  christos 	cfg_doc_map, &cfg_rep_map,	  http_description_clausesets
   4242      1.15  christos };
   4243