1 /* $NetBSD: grammar.h,v 1.10 2025/01/26 16:25:45 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #pragma once 17 18 /*! \file isccfg/grammar.h */ 19 20 #include <inttypes.h> 21 #include <stdbool.h> 22 23 #include <isc/lex.h> 24 #include <isc/netaddr.h> 25 #include <isc/region.h> 26 #include <isc/sockaddr.h> 27 #include <isc/types.h> 28 29 #include <isccfg/cfg.h> 30 #include <isccfg/duration.h> 31 32 /* 33 * Definitions shared between the configuration parser 34 * and the grammars; not visible to users of the parser. 35 */ 36 37 /*% Clause may occur multiple times (e.g., "zone") */ 38 #define CFG_CLAUSEFLAG_MULTI 0x00000001 39 /*% Clause is obsolete (logs a warning, but is not a fatal error) */ 40 #define CFG_CLAUSEFLAG_OBSOLETE 0x00000002 41 /* obsolete: #define CFG_CLAUSEFLAG_NOTIMP 0x00000004 */ 42 /* obsolete: #define CFG_CLAUSEFLAG_NYI 0x00000008 */ 43 /* obsolete: #define CFG_CLAUSEFLAG_NEWDEFAULT 0x00000010 */ 44 /*% 45 * Clause needs to be interpreted during parsing 46 * by calling a callback function, like the 47 * "directory" option. 48 */ 49 #define CFG_CLAUSEFLAG_CALLBACK 0x00000020 50 /*% An option that is only used in testing. */ 51 #define CFG_CLAUSEFLAG_TESTONLY 0x00000040 52 /*% A configuration option that was not configured at compile time. */ 53 #define CFG_CLAUSEFLAG_NOTCONFIGURED 0x00000080 54 /*% An option for an experimental feature. */ 55 #define CFG_CLAUSEFLAG_EXPERIMENTAL 0x00000100 56 /*% An option that should be omited from the documentation */ 57 #define CFG_CLAUSEFLAG_NODOC 0x00000200 58 /*% Clause will be obsolete in a future release (logs a warning) */ 59 #define CFG_CLAUSEFLAG_DEPRECATED 0x00000400 60 /*% Clause has been obsolete so long that it's now a fatal error */ 61 #define CFG_CLAUSEFLAG_ANCIENT 0x00000800 62 63 /*% 64 * Zone types for which a clause is valid: 65 * These share space with CFG_CLAUSEFLAG values, but count 66 * down from the top. 67 */ 68 #define CFG_ZONE_PRIMARY 0x80000000 69 #define CFG_ZONE_SECONDARY 0x40000000 70 #define CFG_ZONE_STUB 0x20000000 71 #define CFG_ZONE_HINT 0x10000000 72 #define CFG_ZONE_FORWARD 0x08000000 73 #define CFG_ZONE_STATICSTUB 0x04000000 74 #define CFG_ZONE_REDIRECT 0x02000000 75 #define CFG_ZONE_DELEGATION 0x01000000 76 #define CFG_ZONE_INVIEW 0x00800000 77 #define CFG_ZONE_MIRROR 0x00400000 78 79 typedef struct cfg_clausedef cfg_clausedef_t; 80 typedef struct cfg_tuplefielddef cfg_tuplefielddef_t; 81 typedef struct cfg_printer cfg_printer_t; 82 typedef ISC_LIST(cfg_listelt_t) cfg_list_t; 83 typedef struct cfg_map cfg_map_t; 84 typedef struct cfg_rep cfg_rep_t; 85 86 /* 87 * Function types for configuration object methods 88 */ 89 90 typedef isc_result_t (*cfg_parsefunc_t)(cfg_parser_t *, const cfg_type_t *type, 91 cfg_obj_t **); 92 typedef void (*cfg_printfunc_t)(cfg_printer_t *, const cfg_obj_t *); 93 typedef void (*cfg_docfunc_t)(cfg_printer_t *, const cfg_type_t *); 94 typedef void (*cfg_freefunc_t)(cfg_parser_t *, cfg_obj_t *); 95 96 /* 97 * Structure definitions 98 */ 99 100 /*% 101 * A configuration printer object. This is an abstract 102 * interface to a destination to which text can be printed 103 * by calling the function 'f'. 104 */ 105 struct cfg_printer { 106 void (*f)(void *closure, const char *text, int textlen); 107 void *closure; 108 int indent; 109 int flags; 110 }; 111 112 /*% A clause definition. */ 113 struct cfg_clausedef { 114 const char *name; 115 cfg_type_t *type; 116 unsigned int flags; 117 }; 118 119 /*% A tuple field definition. */ 120 struct cfg_tuplefielddef { 121 const char *name; 122 cfg_type_t *type; 123 unsigned int flags; 124 }; 125 126 /*% A configuration object type definition. */ 127 struct cfg_type { 128 const char *name; /*%< For debugging purposes only */ 129 cfg_parsefunc_t parse; 130 cfg_printfunc_t print; 131 cfg_docfunc_t doc; /*%< Print grammar description */ 132 cfg_rep_t *rep; /*%< Data representation */ 133 const void *of; /*%< Additional data for meta-types */ 134 }; 135 136 /*% A keyword-type definition, for things like "port <integer>". */ 137 typedef struct { 138 const char *name; 139 const cfg_type_t *type; 140 } keyword_type_t; 141 142 struct cfg_map { 143 cfg_obj_t *id; /*%< Used for 'named maps' like 144 * keys, zones, &c */ 145 const cfg_clausedef_t *const *clausesets; /*%< The clauses that 146 * can occur in this map; 147 * used for printing */ 148 isc_symtab_t *symtab; 149 }; 150 151 typedef struct cfg_netprefix cfg_netprefix_t; 152 153 struct cfg_netprefix { 154 isc_netaddr_t address; /* IP4/IP6 */ 155 unsigned int prefixlen; 156 }; 157 158 /*% 159 * A configuration data representation. 160 */ 161 struct cfg_rep { 162 const char *name; /*%< For debugging only */ 163 cfg_freefunc_t free; /*%< How to free this kind of data. */ 164 }; 165 166 /*% 167 * A configuration object. This is the main building block 168 * of the configuration parse tree. 169 */ 170 171 struct cfg_obj { 172 const cfg_type_t *type; 173 union { 174 uint32_t uint32; 175 uint64_t uint64; 176 isc_textregion_t string; /*%< null terminated, too */ 177 bool boolean; 178 cfg_map_t map; 179 cfg_list_t list; 180 cfg_obj_t **tuple; 181 isc_sockaddr_t sockaddr; 182 struct { 183 isc_sockaddr_t sockaddr; 184 isc_textregion_t tls; 185 } sockaddrtls; 186 cfg_netprefix_t netprefix; 187 isccfg_duration_t duration; 188 } value; 189 isc_refcount_t references; /*%< reference counter */ 190 const char *file; 191 unsigned int line; 192 cfg_parser_t *pctx; 193 }; 194 195 /*% A list element. */ 196 struct cfg_listelt { 197 cfg_obj_t *obj; 198 ISC_LINK(cfg_listelt_t) link; 199 }; 200 201 /*% The parser object. */ 202 struct cfg_parser { 203 isc_mem_t *mctx; 204 isc_log_t *lctx; 205 isc_lex_t *lexer; 206 unsigned int errors; 207 unsigned int warnings; 208 isc_token_t token; 209 210 /*% We are at the end of all input. */ 211 bool seen_eof; 212 213 /*% The current token has been pushed back. */ 214 bool ungotten; 215 216 /*% 217 * The stack of currently active files, represented 218 * as a configuration list of configuration strings. 219 * The head is the top-level file, subsequent elements 220 * (if any) are the nested include files, and the 221 * last element is the file currently being parsed. 222 */ 223 cfg_obj_t *open_files; 224 225 /*% 226 * Names of files that we have parsed and closed 227 * and were previously on the open_file list. 228 * We keep these objects around after closing 229 * the files because the file names may still be 230 * referenced from other configuration objects 231 * for use in reporting semantic errors after 232 * parsing is complete. 233 */ 234 cfg_obj_t *closed_files; 235 236 /*% 237 * Name of a buffer being parsed; used only for 238 * logging. 239 */ 240 char const *buf_name; 241 242 /*% 243 * Current line number. We maintain our own 244 * copy of this so that it is available even 245 * when a file has just been closed. 246 */ 247 unsigned int line; 248 249 /*% 250 * Parser context flags, used for maintaining state 251 * from one token to the next. 252 */ 253 unsigned int flags; 254 255 /*%< Reference counter */ 256 isc_refcount_t references; 257 258 cfg_parsecallback_t callback; 259 void *callbackarg; 260 }; 261 262 /* Parser context flags */ 263 #define CFG_PCTX_SKIP (1 << 0) 264 #define CFG_PCTX_NODEPRECATED (1 << 1) 265 #define CFG_PCTX_NOOBSOLETE (1 << 2) 266 #define CFG_PCTX_NOEXPERIMENTAL (1 << 3) 267 268 /*@{*/ 269 /*% 270 * Flags defining whether to accept certain types of network addresses. 271 */ 272 #define CFG_ADDR_V4OK 0x00000001 273 #define CFG_ADDR_V4PREFIXOK 0x00000002 274 #define CFG_ADDR_V6OK 0x00000004 275 #define CFG_ADDR_WILDOK 0x00000008 276 #define CFG_ADDR_PORTOK 0x00000010 277 #define CFG_ADDR_TLSOK 0x00000020 278 #define CFG_ADDR_MASK (CFG_ADDR_V6OK | CFG_ADDR_V4OK) 279 /*@}*/ 280 281 /*@{*/ 282 /*% 283 * Predefined data representation types. 284 */ 285 extern cfg_rep_t cfg_rep_uint32; 286 extern cfg_rep_t cfg_rep_uint64; 287 extern cfg_rep_t cfg_rep_string; 288 extern cfg_rep_t cfg_rep_boolean; 289 extern cfg_rep_t cfg_rep_map; 290 extern cfg_rep_t cfg_rep_list; 291 extern cfg_rep_t cfg_rep_tuple; 292 extern cfg_rep_t cfg_rep_sockaddr; 293 extern cfg_rep_t cfg_rep_sockaddrtls; 294 extern cfg_rep_t cfg_rep_netprefix; 295 extern cfg_rep_t cfg_rep_void; 296 extern cfg_rep_t cfg_rep_fixedpoint; 297 extern cfg_rep_t cfg_rep_percentage; 298 extern cfg_rep_t cfg_rep_duration; 299 /*@}*/ 300 301 /*@{*/ 302 /*% 303 * Predefined configuration object types. 304 */ 305 extern cfg_type_t cfg_type_boolean; 306 extern cfg_type_t cfg_type_uint32; 307 extern cfg_type_t cfg_type_uint64; 308 extern cfg_type_t cfg_type_qstring; 309 extern cfg_type_t cfg_type_astring; 310 extern cfg_type_t cfg_type_ustring; 311 extern cfg_type_t cfg_type_sstring; 312 extern cfg_type_t cfg_type_bracketed_aml; 313 extern cfg_type_t cfg_type_bracketed_text; 314 extern cfg_type_t cfg_type_optional_bracketed_text; 315 extern cfg_type_t cfg_type_keyref; 316 extern cfg_type_t cfg_type_sockaddr; 317 extern cfg_type_t cfg_type_sockaddrtls; 318 extern cfg_type_t cfg_type_netaddr; 319 extern cfg_type_t cfg_type_netaddr4; 320 extern cfg_type_t cfg_type_netaddr4wild; 321 extern cfg_type_t cfg_type_netaddr6; 322 extern cfg_type_t cfg_type_netaddr6wild; 323 extern cfg_type_t cfg_type_netprefix; 324 extern cfg_type_t cfg_type_void; 325 extern cfg_type_t cfg_type_token; 326 extern cfg_type_t cfg_type_unsupported; 327 extern cfg_type_t cfg_type_fixedpoint; 328 extern cfg_type_t cfg_type_percentage; 329 extern cfg_type_t cfg_type_duration; 330 extern cfg_type_t cfg_type_duration_or_unlimited; 331 /*@}*/ 332 333 isc_result_t 334 cfg_gettoken(cfg_parser_t *pctx, int options); 335 336 isc_result_t 337 cfg_peektoken(cfg_parser_t *pctx, int options); 338 339 void 340 cfg_ungettoken(cfg_parser_t *pctx); 341 342 #define CFG_LEXOPT_QSTRING (ISC_LEXOPT_QSTRING | ISC_LEXOPT_QSTRINGMULTILINE) 343 344 isc_result_t 345 cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 346 347 void 348 cfg_print_rawuint(cfg_printer_t *pctx, unsigned int u); 349 350 isc_result_t 351 cfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 352 353 void 354 cfg_print_uint32(cfg_printer_t *pctx, const cfg_obj_t *obj); 355 356 void 357 cfg_print_uint64(cfg_printer_t *pctx, const cfg_obj_t *obj); 358 359 isc_result_t 360 cfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 361 362 void 363 cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj); 364 365 isc_result_t 366 cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 367 368 isc_result_t 369 cfg_parse_sstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 370 371 isc_result_t 372 cfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na); 373 374 void 375 cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na); 376 377 bool 378 cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags); 379 380 isc_result_t 381 cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port); 382 383 isc_result_t 384 cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 385 386 isc_result_t 387 cfg_parse_sockaddrtls(cfg_parser_t *pctx, const cfg_type_t *type, 388 cfg_obj_t **ret); 389 390 isc_result_t 391 cfg_parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 392 393 void 394 cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj); 395 396 void 397 cfg_print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj); 398 399 void 400 cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type); 401 402 isc_result_t 403 cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type, 404 cfg_obj_t **ret); 405 406 isc_result_t 407 cfg_parse_special(cfg_parser_t *pctx, int special); 408 /*%< Parse a required special character 'special'. */ 409 410 isc_result_t 411 cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 412 413 isc_result_t 414 cfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 415 416 void 417 cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj); 418 419 void 420 cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type); 421 422 isc_result_t 423 cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); 424 425 isc_result_t 426 cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype, 427 cfg_listelt_t **ret); 428 429 isc_result_t 430 cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, 431 cfg_obj_t **ret); 432 433 void 434 cfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj); 435 436 void 437 cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type); 438 439 isc_result_t 440 cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *type, 441 cfg_obj_t **ret); 442 443 void 444 cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj); 445 446 isc_result_t 447 cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 448 449 void 450 cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type); 451 452 isc_result_t 453 cfg_parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype, 454 const cfg_type_t *othertype, cfg_obj_t **ret); 455 456 void 457 cfg_doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *enumtype, 458 const cfg_type_t *othertype); 459 460 void 461 cfg_print_chars(cfg_printer_t *pctx, const char *text, int len); 462 /*%< Print 'len' characters at 'text' */ 463 464 void 465 cfg_print_cstr(cfg_printer_t *pctx, const char *s); 466 /*%< Print the null-terminated string 's' */ 467 468 isc_result_t 469 cfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 470 471 isc_result_t 472 cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, 473 cfg_obj_t **ret); 474 475 isc_result_t 476 cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, 477 cfg_obj_t **ret); 478 479 isc_result_t 480 cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, 481 cfg_obj_t **ret); 482 483 void 484 cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj); 485 486 void 487 cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type); 488 489 isc_result_t 490 cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 491 492 void 493 cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj); 494 495 void 496 cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type); 497 498 isc_result_t 499 cfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 500 501 void 502 cfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj); 503 504 void 505 cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type); 506 507 isc_result_t 508 cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type, 509 cfg_obj_t **ret); 510 511 void 512 cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj); 513 514 isc_result_t 515 cfg_parse_percentage(cfg_parser_t *pctx, const cfg_type_t *type, 516 cfg_obj_t **ret); 517 518 void 519 cfg_print_percentage(cfg_printer_t *pctx, const cfg_obj_t *obj); 520 521 isc_result_t 522 cfg_parse_duration(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 523 524 void 525 cfg_print_duration(cfg_printer_t *pctx, const cfg_obj_t *obj); 526 527 isc_result_t 528 cfg_parse_duration_or_unlimited(cfg_parser_t *pctx, const cfg_type_t *type, 529 cfg_obj_t **ret); 530 531 void 532 cfg_print_duration_or_unlimited(cfg_printer_t *pctx, const cfg_obj_t *obj); 533 534 isc_result_t 535 cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); 536 537 void 538 cfg_print_obj(cfg_printer_t *pctx, const cfg_obj_t *obj); 539 540 void 541 cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type); 542 /*%< 543 * Print a description of the grammar of an arbitrary configuration 544 * type 'type' 545 */ 546 547 void 548 cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type); 549 /*%< 550 * Document the type 'type' as a terminal by printing its 551 * name in angle brackets, e.g., <uint32>. 552 */ 553 554 void 555 cfg_parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) 556 ISC_FORMAT_PRINTF(3, 4); 557 /*! 558 * Pass one of these flags to cfg_parser_error() to include the 559 * token text in log message. 560 */ 561 #define CFG_LOG_NEAR 0x00000001 /*%< Say "near <token>" */ 562 #define CFG_LOG_BEFORE 0x00000002 /*%< Say "before <token>" */ 563 #define CFG_LOG_NOPREP 0x00000004 /*%< Say just "<token>" */ 564 565 void 566 cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) 567 ISC_FORMAT_PRINTF(3, 4); 568 569 bool 570 cfg_is_enum(const char *s, const char *const *enums); 571 /*%< Return true iff the string 's' is one of the strings in 'enums' */ 572 573 bool 574 cfg_clause_validforzone(const char *name, unsigned int ztype); 575 /*%< 576 * Check whether an option is legal for the specified zone type. 577 */ 578 579 void 580 cfg_print_zonegrammar(const unsigned int zonetype, unsigned int flags, 581 void (*f)(void *closure, const char *text, int textlen), 582 void *closure); 583 /*%< 584 * Print a summary of the grammar of the zone type represented by 585 * 'zonetype'. 586 */ 587 588 void 589 cfg_print_clauseflags(cfg_printer_t *pctx, unsigned int flags); 590 /*%< 591 * Print clause flags (e.g. "obsolete", "not implemented", etc) in 592 * human readable form 593 */ 594 595 void 596 cfg_print_indent(cfg_printer_t *pctx); 597 /*%< 598 * Print the necessary indent required by the current settings of 'pctx'. 599 */ 600