xref: /netbsd-src/external/mpl/bind/dist/lib/isccfg/include/isccfg/grammar.h (revision bcda20f65a8566e103791ec395f7f499ef322704)
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., &lt;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