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