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