summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bind/lib/isccfg/parser.c
diff options
context:
space:
mode:
authorjakob <jakob@openbsd.org>2004-09-28 17:14:01 +0000
committerjakob <jakob@openbsd.org>2004-09-28 17:14:01 +0000
commitb2d2683558b03d82a0e27c5ba2cc4a8587a76bb9 (patch)
tree46d872038a60738a8adb1c055a5cff3127d790b1 /usr.sbin/bind/lib/isccfg/parser.c
parentUse ETHER_MIN_LEN/ETHER_MAX_DIX_LEN (diff)
downloadwireguard-openbsd-b2d2683558b03d82a0e27c5ba2cc4a8587a76bb9.tar.xz
wireguard-openbsd-b2d2683558b03d82a0e27c5ba2cc4a8587a76bb9.zip
resolve conflicts
Diffstat (limited to 'usr.sbin/bind/lib/isccfg/parser.c')
-rw-r--r--usr.sbin/bind/lib/isccfg/parser.c2695
1 files changed, 506 insertions, 2189 deletions
diff --git a/usr.sbin/bind/lib/isccfg/parser.c b/usr.sbin/bind/lib/isccfg/parser.c
index c93af6f7d44..76aa71625b0 100644
--- a/usr.sbin/bind/lib/isccfg/parser.c
+++ b/usr.sbin/bind/lib/isccfg/parser.c
@@ -1,21 +1,21 @@
/*
+ * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
- * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
- * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
*/
-/* $ISC: parser.c,v 1.70.2.22 2003/09/19 13:41:36 marka Exp $ */
+/* $ISC: parser.c,v 1.70.2.20.2.18 2004/05/15 03:46:13 jinmei Exp $ */
#include <config.h>
@@ -30,52 +30,21 @@
#include <isc/print.h>
#include <isc/string.h>
#include <isc/sockaddr.h>
+#include <isc/netscope.h>
#include <isc/util.h>
#include <isc/symtab.h>
#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
#include <isccfg/log.h>
/* Shorthand */
#define CAT CFG_LOGCATEGORY_CONFIG
#define MOD CFG_LOGMODULE_PARSER
-#define QSTRING (ISC_LEXOPT_QSTRING | ISC_LEXOPT_QSTRINGMULTILINE)
-
-/*
- * Pass one of these flags to parser_error() to include the
- * token text in log message.
- */
-#define LOG_NEAR 0x00000001 /* Say "near <token>" */
-#define LOG_BEFORE 0x00000002 /* Say "before <token>" */
-#define LOG_NOPREP 0x00000004 /* Say just "<token>" */
-
#define MAP_SYM 1 /* Unique type for isc_symtab */
-/* Clause may occur multiple times (e.g., "zone") */
-#define CFG_CLAUSEFLAG_MULTI 0x00000001
-/* Clause is obsolete */
-#define CFG_CLAUSEFLAG_OBSOLETE 0x00000002
-/* Clause is not implemented, and may never be */
-#define CFG_CLAUSEFLAG_NOTIMP 0x00000004
-/* Clause is not implemented yet */
-#define CFG_CLAUSEFLAG_NYI 0x00000008
-/* Default value has changed since earlier release */
-#define CFG_CLAUSEFLAG_NEWDEFAULT 0x00000010
-/*
- * Clause needs to be interpreted during parsing
- * by calling a callback function, like the
- * "directory" option.
- */
-#define CFG_CLAUSEFLAG_CALLBACK 0x00000020
-
-/*
- * Flags defining whether to accept certain types of network addresses.
- */
-#define V4OK 0x00000001
-#define V4PREFIXOK 0x00000002
-#define V6OK 0x00000004
-#define WILDOK 0x00000008
+#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
/* Check a return value. */
#define CHECK(op) \
@@ -88,231 +57,12 @@
do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
-typedef struct cfg_clausedef cfg_clausedef_t;
-typedef struct cfg_tuplefielddef cfg_tuplefielddef_t;
-typedef struct cfg_printer cfg_printer_t;
-typedef ISC_LIST(cfg_listelt_t) cfg_list_t;
-typedef struct cfg_map cfg_map_t;
-typedef struct cfg_rep cfg_rep_t;
-
-/*
- * Function types for configuration object methods
- */
-
-typedef isc_result_t (*cfg_parsefunc_t)(cfg_parser_t *, const cfg_type_t *type,
- cfg_obj_t **);
-typedef void (*cfg_printfunc_t)(cfg_printer_t *, cfg_obj_t *);
-typedef void (*cfg_freefunc_t)(cfg_parser_t *, cfg_obj_t *);
-
-
-/*
- * Structure definitions
- */
-
-/* The parser object. */
-struct cfg_parser {
- isc_mem_t * mctx;
- isc_log_t * lctx;
- isc_lex_t * lexer;
- unsigned int errors;
- unsigned int warnings;
- isc_token_t token;
-
- /* We are at the end of all input. */
- isc_boolean_t seen_eof;
-
- /* The current token has been pushed back. */
- isc_boolean_t ungotten;
-
- /*
- * The stack of currently active files, represented
- * as a configuration list of configuration strings.
- * The head is the top-level file, subsequent elements
- * (if any) are the nested include files, and the
- * last element is the file currently being parsed.
- */
- cfg_obj_t * open_files;
-
- /*
- * Names of files that we have parsed and closed
- * and were previously on the open_file list.
- * We keep these objects around after closing
- * the files because the file names may still be
- * referenced from other configuration objects
- * for use in reporting semantic errors after
- * parsing is complete.
- */
- cfg_obj_t * closed_files;
-
- /*
- * Current line number. We maintain our own
- * copy of this so that it is available even
- * when a file has just been closed.
- */
- unsigned int line;
-
- cfg_parsecallback_t callback;
- void *callbackarg;
-};
-
-/*
- * A configuration printer object. This is an abstract
- * interface to a destination to which text can be printed
- * by calling the function 'f'.
- */
-struct cfg_printer {
- void (*f)(void *closure, const char *text, int textlen);
- void *closure;
- int indent;
-};
-
-/* A clause definition. */
-
-struct cfg_clausedef {
- const char *name;
- cfg_type_t *type;
- unsigned int flags;
-};
-
-/* A tuple field definition. */
-
-struct cfg_tuplefielddef {
- const char *name;
- cfg_type_t *type;
- unsigned int flags;
-};
-
-/* A configuration object type definition. */
-struct cfg_type {
- const char *name; /* For debugging purposes only */
- cfg_parsefunc_t parse;
- cfg_printfunc_t print;
- cfg_rep_t * rep; /* Data representation */
- const void * of; /* For meta-types */
-};
-
-/* A keyword-type definition, for things like "port <integer>". */
-
-typedef struct {
- const char *name;
- const cfg_type_t *type;
-} keyword_type_t;
-
-struct cfg_map {
- cfg_obj_t *id; /* Used for 'named maps' like keys, zones, &c */
- const cfg_clausedef_t * const *clausesets; /* The clauses that
- can occur in this map;
- used for printing */
- isc_symtab_t *symtab;
-};
-
-typedef struct cfg_netprefix cfg_netprefix_t;
-
-struct cfg_netprefix {
- isc_netaddr_t address; /* IP4/IP6 */
- unsigned int prefixlen;
-};
-
-/*
- * A configuration data representation.
- */
-struct cfg_rep {
- const char * name; /* For debugging only */
- cfg_freefunc_t free; /* How to free this kind of data. */
-};
-
-/*
- * A configuration object. This is the main building block
- * of the configuration parse tree.
- */
-
-struct cfg_obj {
- const cfg_type_t *type;
- union {
- isc_uint32_t uint32;
- isc_uint64_t uint64;
- isc_textregion_t string; /* null terminated, too */
- isc_boolean_t boolean;
- cfg_map_t map;
- cfg_list_t list;
- cfg_obj_t ** tuple;
- isc_sockaddr_t sockaddr;
- cfg_netprefix_t netprefix;
- } value;
- char * file;
- unsigned int line;
-};
-
-
-/* A list element. */
-
-struct cfg_listelt {
- cfg_obj_t *obj;
- ISC_LINK(cfg_listelt_t) link;
-};
-
/*
* Forward declarations of static functions.
*/
-static isc_result_t
-create_cfgobj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
-
-static isc_result_t
-create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
-
-static isc_result_t
-create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
-
-static void
-free_list(cfg_parser_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
- cfg_obj_t **ret);
-
static void
-free_string(cfg_parser_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
-
-static isc_result_t
-create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
-
-static void
-free_map(cfg_parser_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-get_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na);
-
-static void
-print(cfg_printer_t *pctx, const char *text, int len);
-
-static void
-print_void(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
- const cfg_type_t *othertype, cfg_obj_t **ret);
-
-static isc_result_t
-parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
-static void
-print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
-static void
-print_map(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
-static isc_result_t
-parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj);
static isc_result_t
parse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
@@ -320,41 +70,24 @@ parse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
static void
print_list(cfg_printer_t *pctx, cfg_obj_t *obj);
-static isc_result_t
-parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
-static void
-print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static void
-free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
-static void
-print_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj);
-
static void
-print_sockaddr(cfg_printer_t *pctx, cfg_obj_t *obj);
+free_list(cfg_parser_t *pctx, cfg_obj_t *obj);
static isc_result_t
-parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
static isc_result_t
-parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
+ cfg_obj_t **ret);
static void
-print_bracketed_list(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+free_string(cfg_parser_t *pctx, cfg_obj_t *obj);
static isc_result_t
-parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
static void
-print_keyvalue(cfg_printer_t *pctx, cfg_obj_t *obj);
+free_map(cfg_parser_t *pctx, cfg_obj_t *obj);
static isc_result_t
parse_symtab_elt(cfg_parser_t *pctx, const char *name,
@@ -365,38 +98,12 @@ static void
free_noop(cfg_parser_t *pctx, cfg_obj_t *obj);
static isc_result_t
-cfg_gettoken(cfg_parser_t *pctx, int options);
-
-static void
-cfg_ungettoken(cfg_parser_t *pctx);
-
-static isc_result_t
-cfg_peektoken(cfg_parser_t *pctx, int options);
-
-static isc_result_t
cfg_getstringtoken(cfg_parser_t *pctx);
static void
-parser_error(cfg_parser_t *pctx, unsigned int flags,
- const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);
-
-static void
-parser_warning(cfg_parser_t *pctx, unsigned int flags,
- const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);
-
-static void
parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
unsigned int flags, const char *format, va_list args);
-static void
-print_uint32(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static void
-print_ustring(cfg_printer_t *pctx, cfg_obj_t *obj);
-
-static isc_result_t
-parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
-
/*
* Data representations. These correspond to members of the
* "value" union in struct cfg_obj (except "void", which does
@@ -415,734 +122,30 @@ cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
cfg_rep_t cfg_rep_void = { "void", free_noop };
/*
- * Forward declarations of configuration type definitions.
- * Additional types are declared publicly in cfg.h.
- */
-
-static cfg_type_t cfg_type_boolean;
-static cfg_type_t cfg_type_uint32;
-static cfg_type_t cfg_type_qstring;
-static cfg_type_t cfg_type_astring;
-static cfg_type_t cfg_type_ustring;
-static cfg_type_t cfg_type_optional_port;
-static cfg_type_t cfg_type_bracketed_aml;
-static cfg_type_t cfg_type_acl;
-static cfg_type_t cfg_type_portiplist;
-static cfg_type_t cfg_type_bracketed_sockaddrlist;
-static cfg_type_t cfg_type_sockaddr;
-static cfg_type_t cfg_type_netaddr;
-static cfg_type_t cfg_type_optional_keyref;
-static cfg_type_t cfg_type_options;
-static cfg_type_t cfg_type_view;
-static cfg_type_t cfg_type_viewopts;
-static cfg_type_t cfg_type_key;
-static cfg_type_t cfg_type_server;
-static cfg_type_t cfg_type_controls;
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist;
-static cfg_type_t cfg_type_querysource4;
-static cfg_type_t cfg_type_querysource6;
-static cfg_type_t cfg_type_querysource;
-static cfg_type_t cfg_type_sockaddr4wild;
-static cfg_type_t cfg_type_sockaddr6wild;
-static cfg_type_t cfg_type_sockaddr;
-static cfg_type_t cfg_type_netprefix;
-static cfg_type_t cfg_type_zone;
-static cfg_type_t cfg_type_zoneopts;
-static cfg_type_t cfg_type_logging;
-static cfg_type_t cfg_type_optional_facility;
-static cfg_type_t cfg_type_void;
-static cfg_type_t cfg_type_optional_class;
-static cfg_type_t cfg_type_destinationlist;
-static cfg_type_t cfg_type_size;
-static cfg_type_t cfg_type_sizenodefault;
-static cfg_type_t cfg_type_negated;
-static cfg_type_t cfg_type_addrmatchelt;
-static cfg_type_t cfg_type_unsupported;
-static cfg_type_t cfg_type_token;
-static cfg_type_t cfg_type_server_key_kludge;
-static cfg_type_t cfg_type_optional_facility;
-static cfg_type_t cfg_type_logseverity;
-static cfg_type_t cfg_type_logfile;
-static cfg_type_t cfg_type_lwres;
-static cfg_type_t cfg_type_controls_sockaddr;
-static cfg_type_t cfg_type_notifytype;
-static cfg_type_t cfg_type_dialuptype;
-
-/*
* Configuration type definitions.
*/
-/* tkey-dhkey */
-
-static cfg_tuplefielddef_t tkey_dhkey_fields[] = {
- { "name", &cfg_type_qstring, 0 },
- { "keyid", &cfg_type_uint32, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_type_t cfg_type_tkey_dhkey = {
- "tkey-dhkey", parse_tuple, print_tuple, &cfg_rep_tuple,
- tkey_dhkey_fields
-};
-
-/* listen-on */
-
-static cfg_tuplefielddef_t listenon_fields[] = {
- { "port", &cfg_type_optional_port, 0 },
- { "acl", &cfg_type_bracketed_aml, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_listenon = {
- "listenon", parse_tuple, print_tuple, &cfg_rep_tuple, listenon_fields };
-
-/* acl */
-
-static cfg_tuplefielddef_t acl_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "value", &cfg_type_bracketed_aml, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_type_t cfg_type_acl = {
- "acl", parse_tuple, print_tuple, &cfg_rep_tuple, acl_fields };
-
-
-/*
- * "sockaddrkeylist", a list of socket addresses with optional keys
- * and an optional default port, as used in the masters option.
- * E.g.,
- * "port 1234 { 10.0.0.1 key foo; 1::2 port 69; }"
- */
-
-static cfg_tuplefielddef_t sockaddrkey_fields[] = {
- { "sockaddr", &cfg_type_sockaddr, 0 },
- { "key", &cfg_type_optional_keyref, 0 },
- { NULL, NULL, 0 },
-};
-
-static cfg_type_t cfg_type_sockaddrkey = {
- "sockaddrkey", parse_tuple, print_tuple, &cfg_rep_tuple,
- sockaddrkey_fields
-};
-
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist = {
- "bracketed_sockaddrkeylist", parse_bracketed_list,
- print_bracketed_list, &cfg_rep_list, &cfg_type_sockaddrkey
-};
-
-static cfg_tuplefielddef_t sockaddrkeylist_fields[] = {
- { "port", &cfg_type_optional_port, 0 },
- { "addresses", &cfg_type_bracketed_sockaddrkeylist, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_sockaddrkeylist = {
- "sockaddrkeylist", parse_tuple, print_tuple, &cfg_rep_tuple,
- sockaddrkeylist_fields
-};
-
-/*
- * A list of socket addresses with an optional default port,
- * as used in the also-notify option. E.g.,
- * "port 1234 { 10.0.0.1; 1::2 port 69; }"
- */
-static cfg_tuplefielddef_t portiplist_fields[] = {
- { "port", &cfg_type_optional_port, 0 },
- { "addresses", &cfg_type_bracketed_sockaddrlist, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_portiplist = {
- "portiplist", parse_tuple, print_tuple, &cfg_rep_tuple,
- portiplist_fields
-};
-
-/*
- * A public key, as in the "pubkey" statement.
- */
-static cfg_tuplefielddef_t pubkey_fields[] = {
- { "flags", &cfg_type_uint32, 0 },
- { "protocol", &cfg_type_uint32, 0 },
- { "algorithm", &cfg_type_uint32, 0 },
- { "key", &cfg_type_qstring, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_pubkey = {
- "pubkey", parse_tuple, print_tuple, &cfg_rep_tuple, pubkey_fields };
-
-
-/*
- * A list of RR types, used in grant statements.
- * Note that the old parser allows quotes around the RR type names.
- */
-static cfg_type_t cfg_type_rrtypelist = {
- "rrtypelist", parse_spacelist, print_spacelist, &cfg_rep_list,
- &cfg_type_astring
-};
-
-static const char *mode_enums[] = { "grant", "deny", NULL };
-static cfg_type_t cfg_type_mode = {
- "mode", parse_enum, print_ustring, &cfg_rep_string,
- &mode_enums
-};
-
-static const char *matchtype_enums[] = {
- "name", "subdomain", "wildcard", "self", NULL };
-static cfg_type_t cfg_type_matchtype = {
- "matchtype", parse_enum, print_ustring, &cfg_rep_string,
- &matchtype_enums
-};
-
-/*
- * A grant statement, used in the update policy.
- */
-static cfg_tuplefielddef_t grant_fields[] = {
- { "mode", &cfg_type_mode, 0 },
- { "identity", &cfg_type_astring, 0 }, /* domain name */
- { "matchtype", &cfg_type_matchtype, 0 },
- { "name", &cfg_type_astring, 0 }, /* domain name */
- { "types", &cfg_type_rrtypelist, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_grant = {
- "grant", parse_tuple, print_tuple, &cfg_rep_tuple, grant_fields };
-
-static cfg_type_t cfg_type_updatepolicy = {
- "update_policy", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_grant
-};
-
-/*
- * A view statement.
- */
-static cfg_tuplefielddef_t view_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "class", &cfg_type_optional_class, 0 },
- { "options", &cfg_type_viewopts, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_view = {
- "view", parse_tuple, print_tuple, &cfg_rep_tuple, view_fields };
-
-/*
- * A zone statement.
- */
-static cfg_tuplefielddef_t zone_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "class", &cfg_type_optional_class, 0 },
- { "options", &cfg_type_zoneopts, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_zone = {
- "zone", parse_tuple, print_tuple, &cfg_rep_tuple, zone_fields };
-
-/*
- * A "category" clause in the "logging" statement.
- */
-static cfg_tuplefielddef_t category_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "destinations", &cfg_type_destinationlist,0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_category = {
- "category", parse_tuple, print_tuple, &cfg_rep_tuple, category_fields };
-
-
-/*
- * A trusted key, as used in the "trusted-keys" statement.
- */
-static cfg_tuplefielddef_t trustedkey_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "flags", &cfg_type_uint32, 0 },
- { "protocol", &cfg_type_uint32, 0 },
- { "algorithm", &cfg_type_uint32, 0 },
- { "key", &cfg_type_qstring, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_trustedkey = {
- "trustedkey", parse_tuple, print_tuple, &cfg_rep_tuple,
- trustedkey_fields
-};
-
-
-static keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
-
-static cfg_type_t cfg_type_optional_wild_class = {
- "optional_wild_class", parse_optional_keyvalue,
- print_keyvalue, &cfg_rep_string, &wild_class_kw
-};
-
-static keyword_type_t wild_type_kw = { "type", &cfg_type_ustring };
-
-static cfg_type_t cfg_type_optional_wild_type = {
- "optional_wild_type", parse_optional_keyvalue,
- print_keyvalue, &cfg_rep_string, &wild_type_kw
-};
-
-static keyword_type_t wild_name_kw = { "name", &cfg_type_qstring };
-
-static cfg_type_t cfg_type_optional_wild_name = {
- "optional_wild_name", parse_optional_keyvalue,
- print_keyvalue, &cfg_rep_string, &wild_name_kw
-};
-
-/*
- * An rrset ordering element.
- */
-static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
- { "class", &cfg_type_optional_wild_class, 0 },
- { "type", &cfg_type_optional_wild_type, 0 },
- { "name", &cfg_type_optional_wild_name, 0 },
- { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
- { "ordering", &cfg_type_ustring, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_rrsetorderingelement = {
- "rrsetorderingelement", parse_tuple, print_tuple, &cfg_rep_tuple,
- rrsetorderingelement_fields
-};
-
-/*
- * A global or view "check-names" option. Note that the zone
- * "check-names" option has a different syntax.
- */
-static cfg_tuplefielddef_t checknames_fields[] = {
- { "type", &cfg_type_ustring, 0 },
- { "mode", &cfg_type_ustring, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_checknames = {
- "checknames", parse_tuple, print_tuple, &cfg_rep_tuple,
- checknames_fields
-};
-
-static cfg_type_t cfg_type_bracketed_sockaddrlist = {
- "bracketed_sockaddrlist", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_sockaddr
-};
-
-static cfg_type_t cfg_type_rrsetorder = {
- "rrsetorder", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_rrsetorderingelement
-};
-
-static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
-
-static cfg_type_t cfg_type_optional_port = {
- "optional_port", parse_optional_keyvalue, print_keyvalue,
- &cfg_rep_uint32, &port_kw
-};
-
-/* A list of keys, as in the "key" clause of the controls statement. */
-static cfg_type_t cfg_type_keylist = {
- "keylist", parse_bracketed_list, print_bracketed_list, &cfg_rep_list,
- &cfg_type_astring
-};
-
-static cfg_type_t cfg_type_trustedkeys = {
- "trusted-keys", parse_bracketed_list, print_bracketed_list, &cfg_rep_list,
- &cfg_type_trustedkey
-};
-
/*
* An implicit list. These are formed by clauses that occur multiple times.
*/
static cfg_type_t cfg_type_implicitlist = {
- "implicitlist", NULL, print_list, &cfg_rep_list, NULL };
-
-static const char *forwardtype_enums[] = { "first", "only", NULL };
-static cfg_type_t cfg_type_forwardtype = {
- "forwardtype", parse_enum, print_ustring, &cfg_rep_string,
- &forwardtype_enums
-};
-
-static const char *zonetype_enums[] = {
- "master", "slave", "stub", "hint", "forward", "delegation-only", NULL };
-static cfg_type_t cfg_type_zonetype = {
- "zonetype", parse_enum, print_ustring, &cfg_rep_string,
- &zonetype_enums
-};
-
-static const char *loglevel_enums[] = {
- "critical", "error", "warning", "notice", "info", "dynamic", NULL };
-static cfg_type_t cfg_type_loglevel = {
- "loglevel", parse_enum, print_ustring, &cfg_rep_string,
- &loglevel_enums
-};
-
-static const char *transferformat_enums[] = {
- "many-answers", "one-answer", NULL };
-static cfg_type_t cfg_type_transferformat = {
- "transferformat", parse_enum, print_ustring, &cfg_rep_string,
- &transferformat_enums
-};
-
-/*
- * Clauses that can be found within the top level of the named.conf
- * file only.
- */
-static cfg_clausedef_t
-namedconf_clauses[] = {
- { "options", &cfg_type_options, 0 },
- { "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
- { "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
- { "logging", &cfg_type_logging, 0 },
- { "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
- { "lwres", &cfg_type_lwres, CFG_CLAUSEFLAG_MULTI },
- { NULL, NULL, 0 }
-};
-
-/*
- * Clauses that can occur at the top level or in the view
- * statement, but not in the options block.
- */
-static cfg_clausedef_t
-namedconf_or_view_clauses[] = {
- { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
- { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
- { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
-#ifdef ISC_RFC2535
- { "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
-#else
- { "trusted-keys", &cfg_type_trustedkeys,
- CFG_CLAUSEFLAG_MULTI|CFG_CLAUSEFLAG_OBSOLETE },
-#endif
- { NULL, NULL, 0 }
-};
-
-/*
- * Clauses that can be found within the 'options' statement.
- */
-static cfg_clausedef_t
-options_clauses[] = {
- { "blackhole", &cfg_type_bracketed_aml, 0 },
- { "coresize", &cfg_type_size, 0 },
- { "datasize", &cfg_type_size, 0 },
- { "deallocate-on-exit", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK },
- { "dump-file", &cfg_type_qstring, 0 },
- { "fake-iquery", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "files", &cfg_type_size, 0 },
- { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "heartbeat-interval", &cfg_type_uint32, 0 },
- { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP },
- { "interface-interval", &cfg_type_uint32, 0 },
- { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
- { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
- { "match-mapped-addresses", &cfg_type_boolean, 0 },
- { "memstatistics-file", &cfg_type_qstring, CFG_CLAUSEFLAG_NOTIMP },
- { "multiple-cnames", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "named-xfer", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
- { "pid-file", &cfg_type_qstring, 0 },
- { "port", &cfg_type_uint32, 0 },
- { "random-device", &cfg_type_qstring, 0 },
- { "recursive-clients", &cfg_type_uint32, 0 },
- { "rrset-order", &cfg_type_rrsetorder, CFG_CLAUSEFLAG_NOTIMP },
- { "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
- { "serial-query-rate", &cfg_type_uint32, 0 },
- { "stacksize", &cfg_type_size, 0 },
- { "statistics-file", &cfg_type_qstring, 0 },
- { "statistics-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_NYI },
- { "tcp-clients", &cfg_type_uint32, 0 },
- { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
- { "tkey-gssapi-credential", &cfg_type_qstring, 0 },
- { "tkey-domain", &cfg_type_qstring, 0 },
- { "transfers-per-ns", &cfg_type_uint32, 0 },
- { "transfers-in", &cfg_type_uint32, 0 },
- { "transfers-out", &cfg_type_uint32, 0 },
- { "treat-cr-as-space", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "use-id-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "use-ixfr", &cfg_type_boolean, 0 },
- { "version", &cfg_type_qstring, 0 },
- { NULL, NULL, 0 }
-};
-
-
-static cfg_type_t cfg_type_namelist = {
- "namelist", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_qstring };
-
-static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist };
-
-static cfg_type_t cfg_type_optional_exclude = {
- "optional_exclude", parse_optional_keyvalue, print_keyvalue,
- &cfg_rep_list, &exclude_kw };
-
-/*
- * Clauses that can be found within the 'view' statement,
- * with defaults in the 'options' statement.
- */
-
-static cfg_clausedef_t
-view_clauses[] = {
- { "allow-recursion", &cfg_type_bracketed_aml, 0 },
- { "allow-v6-synthesis", &cfg_type_bracketed_aml, 0 },
- { "sortlist", &cfg_type_bracketed_aml, 0 },
- { "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
- { "auth-nxdomain", &cfg_type_boolean, CFG_CLAUSEFLAG_NEWDEFAULT },
- { "minimal-responses", &cfg_type_boolean, 0 },
- { "recursion", &cfg_type_boolean, 0 },
- { "provide-ixfr", &cfg_type_boolean, 0 },
- { "request-ixfr", &cfg_type_boolean, 0 },
- { "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
- { "additional-from-auth", &cfg_type_boolean, 0 },
- { "additional-from-cache", &cfg_type_boolean, 0 },
- /*
- * Note that the query-source option syntax is different
- * from the other -source options.
- */
- { "query-source", &cfg_type_querysource4, 0 },
- { "query-source-v6", &cfg_type_querysource6, 0 },
- { "cleaning-interval", &cfg_type_uint32, 0 },
- { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
- { "lame-ttl", &cfg_type_uint32, 0 },
- { "max-ncache-ttl", &cfg_type_uint32, 0 },
- { "max-cache-ttl", &cfg_type_uint32, 0 },
- { "transfer-format", &cfg_type_transferformat, 0 },
- { "max-cache-size", &cfg_type_sizenodefault, 0 },
- { "check-names", &cfg_type_checknames,
- CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NOTIMP },
- { "cache-file", &cfg_type_qstring, 0 },
- { "root-delegation-only", &cfg_type_optional_exclude, 0 },
- { NULL, NULL, 0 }
-};
-
-/*
- * Clauses that can be found within the 'view' statement only.
- */
-static cfg_clausedef_t
-view_only_clauses[] = {
- { "match-clients", &cfg_type_bracketed_aml, 0 },
- { "match-destinations", &cfg_type_bracketed_aml, 0 },
- { "match-recursive-only", &cfg_type_boolean, 0 },
- { NULL, NULL, 0 }
-};
-
-/*
- * Clauses that can be found in a 'zone' statement,
- * with defaults in the 'view' or 'options' statement.
- */
-static cfg_clausedef_t
-zone_clauses[] = {
- { "allow-query", &cfg_type_bracketed_aml, 0 },
- { "allow-transfer", &cfg_type_bracketed_aml, 0 },
- { "allow-update-forwarding", &cfg_type_bracketed_aml, 0 },
- { "allow-notify", &cfg_type_bracketed_aml, 0 },
- { "notify", &cfg_type_notifytype, 0 },
- { "notify-source", &cfg_type_sockaddr4wild, 0 },
- { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
- { "also-notify", &cfg_type_portiplist, 0 },
- { "dialup", &cfg_type_dialuptype, 0 },
- { "forward", &cfg_type_forwardtype, 0 },
- { "forwarders", &cfg_type_portiplist, 0 },
- { "maintain-ixfr-base", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE },
- { "transfer-source", &cfg_type_sockaddr4wild, 0 },
- { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
- { "max-transfer-time-in", &cfg_type_uint32, 0 },
- { "max-transfer-time-out", &cfg_type_uint32, 0 },
- { "max-transfer-idle-in", &cfg_type_uint32, 0 },
- { "max-transfer-idle-out", &cfg_type_uint32, 0 },
- { "max-retry-time", &cfg_type_uint32, 0 },
- { "min-retry-time", &cfg_type_uint32, 0 },
- { "max-refresh-time", &cfg_type_uint32, 0 },
- { "min-refresh-time", &cfg_type_uint32, 0 },
- { "sig-validity-interval", &cfg_type_uint32, 0 },
- { "zone-statistics", &cfg_type_boolean, 0 },
- { NULL, NULL, 0 }
-};
-
-/*
- * Clauses that can be found in a 'zone' statement
- * only.
- */
-static cfg_clausedef_t
-zone_only_clauses[] = {
- { "type", &cfg_type_zonetype, 0 },
- { "allow-update", &cfg_type_bracketed_aml, 0 },
- { "file", &cfg_type_qstring, 0 },
- { "ixfr-base", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
- { "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
- { "masters", &cfg_type_sockaddrkeylist, 0 },
- { "pubkey", &cfg_type_pubkey,
- CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
- { "update-policy", &cfg_type_updatepolicy, 0 },
- { "database", &cfg_type_astring, 0 },
- { "delegation-only", &cfg_type_boolean, 0 },
- /*
- * Note that the format of the check-names option is different between
- * the zone options and the global/view options. Ugh.
- */
- { "check-names", &cfg_type_ustring, CFG_CLAUSEFLAG_NOTIMP },
- { NULL, NULL, 0 }
-};
-
-
-/* The top-level named.conf syntax. */
-
-static cfg_clausedef_t *
-namedconf_clausesets[] = {
- namedconf_clauses,
- namedconf_or_view_clauses,
- NULL
-};
-
-LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_namedconf = {
- "namedconf", parse_mapbody, print_mapbody, &cfg_rep_map,
- namedconf_clausesets
-};
-
-/* The "options" statement syntax. */
-
-static cfg_clausedef_t *
-options_clausesets[] = {
- options_clauses,
- view_clauses,
- zone_clauses,
- NULL
-};
-static cfg_type_t cfg_type_options = {
- "options", parse_map, print_map, &cfg_rep_map, options_clausesets };
-
-/* The "view" statement syntax. */
-
-static cfg_clausedef_t *
-view_clausesets[] = {
- view_only_clauses,
- namedconf_or_view_clauses,
- view_clauses,
- zone_clauses,
- NULL
-};
-static cfg_type_t cfg_type_viewopts = {
- "view", parse_map, print_map, &cfg_rep_map, view_clausesets };
-
-/* The "zone" statement syntax. */
-
-static cfg_clausedef_t *
-zone_clausesets[] = {
- zone_only_clauses,
- zone_clauses,
- NULL
-};
-static cfg_type_t cfg_type_zoneopts = {
- "zoneopts", parse_map, print_map, &cfg_rep_map, zone_clausesets };
-
-/*
- * Clauses that can be found within the 'key' statement.
- */
-static cfg_clausedef_t
-key_clauses[] = {
- { "algorithm", &cfg_type_astring, 0 },
- { "secret", &cfg_type_astring, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-key_clausesets[] = {
- key_clauses,
- NULL
-};
-static cfg_type_t cfg_type_key = {
- "key", parse_named_map, print_map, &cfg_rep_map, key_clausesets };
-
-
-/*
- * Clauses that can be found in a 'server' statement.
- */
-static cfg_clausedef_t
-server_clauses[] = {
- { "bogus", &cfg_type_boolean, 0 },
- { "provide-ixfr", &cfg_type_boolean, 0 },
- { "request-ixfr", &cfg_type_boolean, 0 },
- { "support-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
- { "transfers", &cfg_type_uint32, 0 },
- { "transfer-format", &cfg_type_transferformat, 0 },
- { "keys", &cfg_type_server_key_kludge, 0 },
- { "edns", &cfg_type_boolean, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_clausedef_t *
-server_clausesets[] = {
- server_clauses,
- NULL
-};
-static cfg_type_t cfg_type_server = {
- "server", parse_addressed_map, print_map, &cfg_rep_map,
- server_clausesets
-};
-
-
-/*
- * Clauses that can be found in a 'channel' clause in the
- * 'logging' statement.
- *
- * These have some additional constraints that need to be
- * checked after parsing:
- * - There must exactly one of file/syslog/null/stderr
- *
- */
-static cfg_clausedef_t
-channel_clauses[] = {
- /* Destinations. We no longer require these to be first. */
- { "file", &cfg_type_logfile, 0 },
- { "syslog", &cfg_type_optional_facility, 0 },
- { "null", &cfg_type_void, 0 },
- { "stderr", &cfg_type_void, 0 },
- /* Options. We now accept these for the null channel, too. */
- { "severity", &cfg_type_logseverity, 0 },
- { "print-time", &cfg_type_boolean, 0 },
- { "print-severity", &cfg_type_boolean, 0 },
- { "print-category", &cfg_type_boolean, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_clausedef_t *
-channel_clausesets[] = {
- channel_clauses,
- NULL
-};
-static cfg_type_t cfg_type_channel = {
- "channel", parse_named_map, print_map,
- &cfg_rep_map, channel_clausesets
-};
-
-/* A list of log destination, used in the "category" clause. */
-static cfg_type_t cfg_type_destinationlist = {
- "destinationlist", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_astring };
-
-/*
- * Clauses that can be found in a 'logging' statement.
- */
-static cfg_clausedef_t
-logging_clauses[] = {
- { "channel", &cfg_type_channel, CFG_CLAUSEFLAG_MULTI },
- { "category", &cfg_type_category, CFG_CLAUSEFLAG_MULTI },
- { NULL, NULL, 0 }
-};
-static cfg_clausedef_t *
-logging_clausesets[] = {
- logging_clauses,
- NULL
-};
-static cfg_type_t cfg_type_logging = {
- "logging", parse_map, print_map, &cfg_rep_map, logging_clausesets };
-
+ "implicitlist", NULL, print_list, NULL, &cfg_rep_list, NULL };
/* Functions. */
-static void
-print_obj(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_obj(cfg_printer_t *pctx, cfg_obj_t *obj) {
obj->type->print(pctx, obj);
}
-static void
-print(cfg_printer_t *pctx, const char *text, int len) {
+void
+cfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
pctx->f(pctx->closure, text, len);
}
static void
print_open(cfg_printer_t *pctx) {
- print(pctx, "{\n", 2);
+ cfg_print_chars(pctx, "{\n", 2);
pctx->indent++;
}
@@ -1150,7 +153,7 @@ static void
print_indent(cfg_printer_t *pctx) {
int indent = pctx->indent;
while (indent > 0) {
- print(pctx, "\t", 1);
+ cfg_print_chars(pctx, "\t", 1);
indent--;
}
}
@@ -1159,11 +162,11 @@ static void
print_close(cfg_printer_t *pctx) {
pctx->indent--;
print_indent(pctx);
- print(pctx, "}", 1);
+ cfg_print_chars(pctx, "}", 1);
}
-static isc_result_t
-parse(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
INSIST(ret != NULL && *ret == NULL);
result = type->parse(pctx, type, ret);
@@ -1188,8 +191,8 @@ cfg_print(cfg_obj_t *obj,
/* Tuples. */
-static isc_result_t
-create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
const cfg_tuplefielddef_t *fields = type->of;
const cfg_tuplefielddef_t *f;
@@ -1200,7 +203,7 @@ create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
for (f = fields; f->name != NULL; f++)
nfields++;
- CHECK(create_cfgobj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx, type, &obj));
obj->value.tuple = isc_mem_get(pctx->mctx,
nfields * sizeof(cfg_obj_t *));
if (obj->value.tuple == NULL) {
@@ -1218,8 +221,8 @@ create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static isc_result_t
-parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+isc_result_t
+cfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
{
isc_result_t result;
const cfg_tuplefielddef_t *fields = type->of;
@@ -1227,9 +230,9 @@ parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
cfg_obj_t *obj = NULL;
unsigned int i;
- CHECK(create_tuple(pctx, type, &obj));
+ CHECK(cfg_create_tuple(pctx, type, &obj));
for (f = fields, i = 0; f->name != NULL; f++, i++)
- CHECK(parse(pctx, f->type, &obj->value.tuple[i]));
+ CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[i]));
*ret = obj;
return (ISC_R_SUCCESS);
@@ -1239,8 +242,8 @@ parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
return (result);
}
-static void
-print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj) {
unsigned int i;
const cfg_tuplefielddef_t *fields = obj->type->of;
const cfg_tuplefielddef_t *f;
@@ -1249,9 +252,23 @@ print_tuple(cfg_printer_t *pctx, cfg_obj_t *obj) {
for (f = fields, i = 0; f->name != NULL; f++, i++) {
cfg_obj_t *fieldobj = obj->value.tuple[i];
if (need_space)
- print(pctx, " ", 1);
- print_obj(pctx, fieldobj);
- need_space = ISC_TF(fieldobj->type->print != print_void);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, fieldobj);
+ need_space = ISC_TF(fieldobj->type->print != cfg_print_void);
+ }
+}
+
+void
+cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_tuplefielddef_t *fields = type->of;
+ const cfg_tuplefielddef_t *f;
+ isc_boolean_t need_space = ISC_FALSE;
+
+ for (f = fields; f->name != NULL; f++) {
+ if (need_space)
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, f->type);
+ need_space = ISC_TF(f->type->print != cfg_print_void);
}
}
@@ -1296,18 +313,15 @@ cfg_tuple_get(cfg_obj_t *tupleobj, const char* name) {
return (NULL);
}
-/*
- * Parse a required special character.
- */
-static isc_result_t
-parse_special(cfg_parser_t *pctx, int special) {
+isc_result_t
+cfg_parse_special(cfg_parser_t *pctx, int special) {
isc_result_t result;
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type == isc_tokentype_special &&
pctx->token.value.as_char == special)
return (ISC_R_SUCCESS);
- parser_error(pctx, LOG_NEAR, "'%c' expected", special);
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "'%c' expected", special);
return (ISC_R_UNEXPECTEDTOKEN);
cleanup:
return (result);
@@ -1328,7 +342,7 @@ parse_semicolon(cfg_parser_t *pctx) {
pctx->token.value.as_char == ';')
return (ISC_R_SUCCESS);
- parser_error(pctx, LOG_BEFORE, "missing ';'");
+ cfg_parser_error(pctx, CFG_LOG_BEFORE, "missing ';'");
cfg_ungettoken(pctx);
cleanup:
return (result);
@@ -1345,22 +359,21 @@ parse_eof(cfg_parser_t *pctx) {
if (pctx->token.type == isc_tokentype_eof)
return (ISC_R_SUCCESS);
- parser_error(pctx, LOG_NEAR, "syntax error");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "syntax error");
return (ISC_R_UNEXPECTEDTOKEN);
cleanup:
- return(result);
+ return (result);
}
/* A list of files, used internally for pctx->files. */
static cfg_type_t cfg_type_filelist = {
- "filelist", NULL, print_list, &cfg_rep_list,
+ "filelist", NULL, print_list, NULL, &cfg_rep_list,
&cfg_type_qstring
};
isc_result_t
-cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret)
-{
+cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
isc_result_t result;
cfg_parser_t *pctx;
isc_lexspecials_t specials;
@@ -1401,8 +414,8 @@ cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret)
ISC_LEXCOMMENT_CPLUSPLUS |
ISC_LEXCOMMENT_SHELL));
- CHECK(create_list(pctx, &cfg_type_filelist, &pctx->open_files));
- CHECK(create_list(pctx, &cfg_type_filelist, &pctx->closed_files));
+ CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files));
+ CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files));
*ret = pctx;
return (ISC_R_SUCCESS);
@@ -1424,7 +437,7 @@ parser_openfile(cfg_parser_t *pctx, const char *filename) {
result = isc_lex_openfile(pctx->lexer, filename);
if (result != ISC_R_SUCCESS) {
- parser_error(pctx, 0, "open: %s: %s",
+ cfg_parser_error(pctx, 0, "open: %s: %s",
filename, isc_result_totext(result));
goto cleanup;
}
@@ -1458,7 +471,7 @@ parse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
- result = parse(pctx, type, &obj);
+ result = cfg_parse_obj(pctx, type, &obj);
if (pctx->errors != 0) {
/* Errors have been logged. */
@@ -1469,7 +482,7 @@ parse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
if (result != ISC_R_SUCCESS) {
/* Parsing failed but no errors have been logged. */
- parser_error(pctx, 0, "parsing failed");
+ cfg_parser_error(pctx, 0, "parsing failed");
goto cleanup;
}
@@ -1528,44 +541,51 @@ cfg_parser_destroy(cfg_parser_t **pctxp) {
/*
* void
*/
-static isc_result_t
-parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
UNUSED(type);
- return (create_cfgobj(pctx, &cfg_type_void, ret));
+ return (cfg_create_obj(pctx, &cfg_type_void, ret));
}
-static void
-print_void(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_void(cfg_printer_t *pctx, cfg_obj_t *obj) {
UNUSED(pctx);
UNUSED(obj);
}
+void
+cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(pctx);
+ UNUSED(type);
+}
+
isc_boolean_t
cfg_obj_isvoid(cfg_obj_t *obj) {
REQUIRE(obj != NULL);
return (ISC_TF(obj->type->rep == &cfg_rep_void));
}
-static cfg_type_t cfg_type_void = {
- "void", parse_void, print_void, &cfg_rep_void, NULL };
+cfg_type_t cfg_type_void = {
+ "void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
+ NULL };
/*
* uint32
*/
-static isc_result_t
-parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
UNUSED(type);
CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
if (pctx->token.type != isc_tokentype_number) {
- parser_error(pctx, LOG_NEAR, "expected number");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected number");
return (ISC_R_UNEXPECTEDTOKEN);
}
- CHECK(create_cfgobj(pctx, &cfg_type_uint32, &obj));
+ CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj));
obj->value.uint32 = pctx->token.value.as_ulong;
*ret = obj;
@@ -1573,21 +593,21 @@ parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static void
-print_cstr(cfg_printer_t *pctx, const char *s) {
- print(pctx, s, strlen(s));
+void
+cfg_print_cstr(cfg_printer_t *pctx, const char *s) {
+ cfg_print_chars(pctx, s, strlen(s));
}
-static void
-print_uint(cfg_printer_t *pctx, unsigned int u) {
+void
+cfg_print_rawuint(cfg_printer_t *pctx, unsigned int u) {
char buf[32];
snprintf(buf, sizeof(buf), "%u", u);
- print_cstr(pctx, buf);
+ cfg_print_cstr(pctx, buf);
}
-static void
-print_uint32(cfg_printer_t *pctx, cfg_obj_t *obj) {
- print_uint(pctx, obj->value.uint32);
+void
+cfg_print_uint32(cfg_printer_t *pctx, cfg_obj_t *obj) {
+ cfg_print_rawuint(pctx, obj->value.uint32);
}
isc_boolean_t
@@ -1602,8 +622,10 @@ cfg_obj_asuint32(cfg_obj_t *obj) {
return (obj->value.uint32);
}
-static cfg_type_t cfg_type_uint32 = {
- "integer", parse_uint32, print_uint32, &cfg_rep_uint32, NULL };
+cfg_type_t cfg_type_uint32 = {
+ "integer", cfg_parse_uint32, cfg_print_uint32, cfg_doc_terminal,
+ &cfg_rep_uint32, NULL
+};
/*
@@ -1621,162 +643,22 @@ cfg_obj_asuint64(cfg_obj_t *obj) {
return (obj->value.uint64);
}
-static isc_result_t
-parse_unitstring(char *str, isc_resourcevalue_t *valuep) {
- char *endp;
- unsigned int len;
- isc_uint64_t value;
- isc_uint64_t unit;
-
- value = isc_string_touint64(str, &endp, 10);
- if (*endp == 0) {
- *valuep = value;
- return (ISC_R_SUCCESS);
- }
-
- len = strlen(str);
- if (len < 2 || endp[1] != '\0')
- return (ISC_R_FAILURE);
-
- switch (str[len - 1]) {
- case 'k':
- case 'K':
- unit = 1024;
- break;
- case 'm':
- case 'M':
- unit = 1024 * 1024;
- break;
- case 'g':
- case 'G':
- unit = 1024 * 1024 * 1024;
- break;
- default:
- return (ISC_R_FAILURE);
- }
- if (value > ISC_UINT64_MAX / unit)
- return (ISC_R_FAILURE);
- *valuep = value * unit;
- return (ISC_R_SUCCESS);
-}
-
-static void
-print_uint64(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_uint64(cfg_printer_t *pctx, cfg_obj_t *obj) {
char buf[32];
snprintf(buf, sizeof(buf), "%" ISC_PRINT_QUADFORMAT "u",
obj->value.uint64);
- print_cstr(pctx, buf);
-}
-
-static cfg_type_t cfg_type_uint64 = {
- "64_bit_integer", NULL, print_uint64, &cfg_rep_uint64, NULL };
-
-static isc_result_t
-parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
- cfg_obj_t *obj = NULL;
- isc_uint64_t val;
-
- UNUSED(type);
-
- CHECK(cfg_gettoken(pctx, 0));
- if (pctx->token.type != isc_tokentype_string) {
- result = ISC_R_UNEXPECTEDTOKEN;
- goto cleanup;
- }
- CHECK(parse_unitstring(pctx->token.value.as_pointer, &val));
-
- CHECK(create_cfgobj(pctx, &cfg_type_uint64, &obj));
- obj->value.uint64 = val;
- *ret = obj;
- return (ISC_R_SUCCESS);
-
- cleanup:
- parser_error(pctx, LOG_NEAR, "expected integer and optional unit");
- return (result);
+ cfg_print_cstr(pctx, buf);
}
-/*
- * A size value (number + optional unit).
- */
-static cfg_type_t cfg_type_sizeval = {
- "sizeval", parse_sizeval, print_uint64, &cfg_rep_uint64, NULL };
-
-/*
- * A size, "unlimited", or "default".
- */
-
-static isc_result_t
-parse_size(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_enum_or_other(pctx, type, &cfg_type_sizeval, ret));
-}
-
-static const char *size_enums[] = { "unlimited", "default", NULL };
-static cfg_type_t cfg_type_size = {
- "size", parse_size, print_ustring, &cfg_rep_string, size_enums
+cfg_type_t cfg_type_uint64 = {
+ "64_bit_integer", NULL, cfg_print_uint64, cfg_doc_terminal,
+ &cfg_rep_uint64, NULL
};
/*
- * A size or "unlimited", but not "default".
- */
-static const char *sizenodefault_enums[] = { "unlimited", NULL };
-static cfg_type_t cfg_type_sizenodefault = {
- "size_no_default", parse_size, print_ustring, &cfg_rep_string,
- sizenodefault_enums
-};
-
-/*
- * optional_keyvalue
- */
-static isc_result_t
-parse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
- isc_boolean_t optional, cfg_obj_t **ret)
-{
- isc_result_t result;
- cfg_obj_t *obj = NULL;
- const keyword_type_t *kw = type->of;
-
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string &&
- strcasecmp(pctx->token.value.as_pointer, kw->name) == 0) {
- CHECK(cfg_gettoken(pctx, 0));
- CHECK(kw->type->parse(pctx, kw->type, &obj));
- obj->type = type; /* XXX kludge */
- } else {
- if (optional) {
- CHECK(parse_void(pctx, NULL, &obj));
- } else {
- parser_error(pctx, LOG_NEAR, "expected '%s'",
- kw->name);
- result = ISC_R_UNEXPECTEDTOKEN;
- goto cleanup;
- }
- }
- *ret = obj;
- cleanup:
- return (result);
-}
-
-static isc_result_t
-parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_maybe_optional_keyvalue(pctx, type, ISC_FALSE, ret));
-}
-
-static isc_result_t
-parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_maybe_optional_keyvalue(pctx, type, ISC_TRUE, ret));
-}
-
-static void
-print_keyvalue(cfg_printer_t *pctx, cfg_obj_t *obj) {
- const keyword_type_t *kw = obj->type->of;
- print_cstr(pctx, kw->name);
- print(pctx, " ", 1);
- kw->type->print(pctx, obj);
-}
-
-/*
- * qstring, ustring, astring
+ * qstring (quoted string), ustring (unquoted string), astring
+ * (any string)
*/
/* Create a string object from a null-terminated C string. */
@@ -1788,7 +670,7 @@ create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
cfg_obj_t *obj = NULL;
int len;
- CHECK(create_cfgobj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx, type, &obj));
len = strlen(contents);
obj->value.string.length = len;
obj->value.string.base = isc_mem_get(pctx->mctx, len + 1);
@@ -1804,18 +686,18 @@ create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
return (result);
}
-static isc_result_t
-parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
UNUSED(type);
- CHECK(cfg_gettoken(pctx, QSTRING));
+ CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
if (pctx->token.type != isc_tokentype_qstring) {
- parser_error(pctx, LOG_NEAR, "expected quoted string");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected quoted string");
return (ISC_R_UNEXPECTEDTOKEN);
}
return (create_string(pctx,
- pctx->token.value.as_pointer,
+ TOKEN_STRING(pctx),
&cfg_type_qstring,
ret));
cleanup:
@@ -1829,33 +711,33 @@ parse_ustring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
CHECK(cfg_gettoken(pctx, 0));
if (pctx->token.type != isc_tokentype_string) {
- parser_error(pctx, LOG_NEAR, "expected unquoted string");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected unquoted string");
return (ISC_R_UNEXPECTEDTOKEN);
}
return (create_string(pctx,
- pctx->token.value.as_pointer,
+ TOKEN_STRING(pctx),
&cfg_type_ustring,
ret));
cleanup:
return (result);
}
-static isc_result_t
-parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
UNUSED(type);
CHECK(cfg_getstringtoken(pctx));
return (create_string(pctx,
- pctx->token.value.as_pointer,
+ TOKEN_STRING(pctx),
&cfg_type_qstring,
ret));
cleanup:
return (result);
}
-static isc_boolean_t
-is_enum(const char *s, const char *const *enums) {
+isc_boolean_t
+cfg_is_enum(const char *s, const char *const *enums) {
const char * const *p;
for (p = enums; *p != NULL; p++) {
if (strcasecmp(*p, s) == 0)
@@ -1867,14 +749,14 @@ is_enum(const char *s, const char *const *enums) {
static isc_result_t
check_enum(cfg_parser_t *pctx, cfg_obj_t *obj, const char *const *enums) {
const char *s = obj->value.string.base;
- if (is_enum(s, enums))
+ if (cfg_is_enum(s, enums))
return (ISC_R_SUCCESS);
- parser_error(pctx, 0, "'%s' unexpected", s);
+ cfg_parser_error(pctx, 0, "'%s' unexpected", s);
return (ISC_R_UNEXPECTEDTOKEN);
}
-static isc_result_t
-parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
CHECK(parse_ustring(pctx, NULL, &obj));
@@ -1886,36 +768,28 @@ parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static isc_result_t
-parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
- const cfg_type_t *othertype, cfg_obj_t **ret)
-{
- isc_result_t result;
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string &&
- is_enum(pctx->token.value.as_pointer, enumtype->of)) {
- CHECK(parse_enum(pctx, enumtype, ret));
- } else {
- CHECK(parse(pctx, othertype, ret));
+void
+cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const char * const *p;
+ cfg_print_chars(pctx, "( ", 2);
+ for (p = type->of; *p != NULL; p++) {
+ cfg_print_cstr(pctx, *p);
+ if (p[1] != NULL)
+ cfg_print_chars(pctx, " | ", 3);
}
- cleanup:
- return (result);
+ cfg_print_chars(pctx, " )", 2);
}
-
-/*
- * Print a string object.
- */
-static void
-print_ustring(cfg_printer_t *pctx, cfg_obj_t *obj) {
- print(pctx, obj->value.string.base, obj->value.string.length);
+void
+cfg_print_ustring(cfg_printer_t *pctx, cfg_obj_t *obj) {
+ cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
}
static void
print_qstring(cfg_printer_t *pctx, cfg_obj_t *obj) {
- print(pctx, "\"", 1);
- print_ustring(pctx, obj);
- print(pctx, "\"", 1);
+ cfg_print_chars(pctx, "\"", 1);
+ cfg_print_ustring(pctx, obj);
+ cfg_print_chars(pctx, "\"", 1);
}
static void
@@ -1936,6 +810,28 @@ cfg_obj_asstring(cfg_obj_t *obj) {
return (obj->value.string.base);
}
+/* Quoted string only */
+cfg_type_t cfg_type_qstring = {
+ "quoted_string", cfg_parse_qstring, print_qstring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/* Unquoted string only */
+cfg_type_t cfg_type_ustring = {
+ "string", parse_ustring, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/* Any string (quoted or unquoted); printed with quotes */
+cfg_type_t cfg_type_astring = {
+ "string", cfg_parse_astring, print_qstring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/*
+ * Booleans
+ */
+
isc_boolean_t
cfg_obj_isboolean(cfg_obj_t *obj) {
REQUIRE(obj != NULL);
@@ -1948,22 +844,6 @@ cfg_obj_asboolean(cfg_obj_t *obj) {
return (obj->value.boolean);
}
-/* Quoted string only */
-static cfg_type_t cfg_type_qstring = {
- "quoted_string", parse_qstring, print_qstring, &cfg_rep_string, NULL };
-
-/* Unquoted string only */
-static cfg_type_t cfg_type_ustring = {
- "string", parse_ustring, print_ustring, &cfg_rep_string, NULL };
-
-/* Any string (quoted or unquoted); printed with quotes */
-static cfg_type_t cfg_type_astring = {
- "string", parse_astring, print_qstring, &cfg_rep_string, NULL };
-
-
-/*
- * boolean
- */
static isc_result_t
parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
{
@@ -1979,25 +859,25 @@ parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
if (pctx->token.type != isc_tokentype_string)
goto bad_boolean;
- if ((strcasecmp(pctx->token.value.as_pointer, "true") == 0) ||
- (strcasecmp(pctx->token.value.as_pointer, "yes") == 0) ||
- (strcmp(pctx->token.value.as_pointer, "1") == 0)) {
+ if ((strcasecmp(TOKEN_STRING(pctx), "true") == 0) ||
+ (strcasecmp(TOKEN_STRING(pctx), "yes") == 0) ||
+ (strcmp(TOKEN_STRING(pctx), "1") == 0)) {
value = ISC_TRUE;
- } else if ((strcasecmp(pctx->token.value.as_pointer, "false") == 0) ||
- (strcasecmp(pctx->token.value.as_pointer, "no") == 0) ||
- (strcmp(pctx->token.value.as_pointer, "0") == 0)) {
+ } else if ((strcasecmp(TOKEN_STRING(pctx), "false") == 0) ||
+ (strcasecmp(TOKEN_STRING(pctx), "no") == 0) ||
+ (strcmp(TOKEN_STRING(pctx), "0") == 0)) {
value = ISC_FALSE;
} else {
goto bad_boolean;
}
- CHECK(create_cfgobj(pctx, &cfg_type_boolean, &obj));
+ CHECK(cfg_create_obj(pctx, &cfg_type_boolean, &obj));
obj->value.boolean = value;
*ret = obj;
return (result);
bad_boolean:
- parser_error(pctx, LOG_NEAR, "boolean expected");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "boolean expected");
return (ISC_R_UNEXPECTEDTOKEN);
cleanup:
@@ -2007,56 +887,24 @@ parse_boolean(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
static void
print_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) {
if (obj->value.boolean)
- print(pctx, "yes", 3);
+ cfg_print_chars(pctx, "yes", 3);
else
- print(pctx, "no", 2);
+ cfg_print_chars(pctx, "no", 2);
}
-static cfg_type_t cfg_type_boolean = {
- "boolean", parse_boolean, print_boolean, &cfg_rep_boolean, NULL };
-
-static const char *dialup_enums[] = {
- "notify", "notify-passive", "refresh", "passive", NULL };
-static isc_result_t
-parse_dialup_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
-}
-static cfg_type_t cfg_type_dialuptype = {
- "dialuptype", parse_dialup_type, print_ustring,
- &cfg_rep_string, dialup_enums
+cfg_type_t cfg_type_boolean = {
+ "boolean", parse_boolean, print_boolean, cfg_doc_terminal,
+ &cfg_rep_boolean, NULL
};
-static const char *notify_enums[] = { "explicit", NULL };
-static isc_result_t
-parse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
-}
-static cfg_type_t cfg_type_notifytype = {
- "notifytype", parse_notify_type, print_ustring,
- &cfg_rep_string, notify_enums,
-};
-
-static keyword_type_t key_kw = { "key", &cfg_type_astring };
-
-LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {
- "keyref", parse_keyvalue, print_keyvalue,
- &cfg_rep_string, &key_kw
-};
-
-static cfg_type_t cfg_type_optional_keyref = {
- "optional_keyref", parse_optional_keyvalue, print_keyvalue,
- &cfg_rep_string, &key_kw
-};
-
-
/*
* Lists.
*/
-static isc_result_t
-create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {
+isc_result_t
+cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {
isc_result_t result;
- CHECK(create_cfgobj(pctx, type, obj));
+ CHECK(cfg_create_obj(pctx, type, obj));
ISC_LIST_INIT((*obj)->value.list);
cleanup:
return (result);
@@ -2092,9 +940,9 @@ free_list(cfg_parser_t *pctx, cfg_obj_t *obj) {
}
}
-static isc_result_t
-parse_list_elt(cfg_parser_t *pctx, const cfg_type_t *elttype,
- cfg_listelt_t **ret)
+isc_result_t
+cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
+ cfg_listelt_t **ret)
{
isc_result_t result;
cfg_listelt_t *elt = NULL;
@@ -2102,7 +950,7 @@ parse_list_elt(cfg_parser_t *pctx, const cfg_type_t *elttype,
CHECK(create_listelt(pctx, &elt));
- result = parse(pctx, elttype, &value);
+ result = cfg_parse_obj(pctx, elttype, &value);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -2128,14 +976,14 @@ parse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
isc_result_t result;
cfg_listelt_t *elt = NULL;
- CHECK(create_list(pctx, listtype, &listobj));
+ CHECK(cfg_create_list(pctx, listtype, &listobj));
for (;;) {
CHECK(cfg_peektoken(pctx, 0));
if (pctx->token.type == isc_tokentype_special &&
pctx->token.value.as_char == /*{*/ '}')
break;
- CHECK(parse_list_elt(pctx, listof, &elt));
+ CHECK(cfg_parse_listelt(pctx, listof, &elt));
CHECK(parse_semicolon(pctx));
ISC_LIST_APPEND(listobj->value.list, elt, link);
elt = NULL;
@@ -2159,42 +1007,51 @@ print_list(cfg_printer_t *pctx, cfg_obj_t *obj) {
elt != NULL;
elt = ISC_LIST_NEXT(elt, link)) {
print_indent(pctx);
- print_obj(pctx, elt->obj);
- print(pctx, ";\n", 2);
+ cfg_print_obj(pctx, elt->obj);
+ cfg_print_chars(pctx, ";\n", 2);
}
}
-static isc_result_t
-parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+isc_result_t
+cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
{
isc_result_t result;
- CHECK(parse_special(pctx, '{'));
+ CHECK(cfg_parse_special(pctx, '{'));
CHECK(parse_list(pctx, type, ret));
- CHECK(parse_special(pctx, '}'));
+ CHECK(cfg_parse_special(pctx, '}'));
cleanup:
return (result);
}
-static void
-print_bracketed_list(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_bracketed_list(cfg_printer_t *pctx, cfg_obj_t *obj) {
print_open(pctx);
print_list(pctx, obj);
print_close(pctx);
}
+void
+cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_chars(pctx, "{ ", 2);
+ cfg_doc_obj(pctx, type->of);
+ cfg_print_chars(pctx, "; ... }", 7);
+}
+
/*
* Parse a homogeneous list whose elements are of type 'elttype'
* and where elements are separated by space. The list ends
* before the first semicolon.
*/
-static isc_result_t
-parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
+isc_result_t
+cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype,
+ cfg_obj_t **ret)
{
cfg_obj_t *listobj = NULL;
const cfg_type_t *listof = listtype->of;
isc_result_t result;
- CHECK(create_list(pctx, listtype, &listobj));
+ CHECK(cfg_create_list(pctx, listtype, &listobj));
for (;;) {
cfg_listelt_t *elt = NULL;
@@ -2203,7 +1060,7 @@ parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
if (pctx->token.type == isc_tokentype_special &&
pctx->token.value.as_char == ';')
break;
- CHECK(parse_list_elt(pctx, listof, &elt));
+ CHECK(cfg_parse_listelt(pctx, listof, &elt));
ISC_LIST_APPEND(listobj->value.list, elt, link);
}
*ret = listobj;
@@ -2214,20 +1071,21 @@ parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
return (result);
}
-static void
-print_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj) {
cfg_list_t *list = &obj->value.list;
cfg_listelt_t *elt;
for (elt = ISC_LIST_HEAD(*list);
elt != NULL;
elt = ISC_LIST_NEXT(elt, link)) {
- print_obj(pctx, elt->obj);
+ cfg_print_obj(pctx, elt->obj);
if (ISC_LIST_NEXT(elt, link) != NULL)
- print(pctx, " ", 1);
+ cfg_print_chars(pctx, " ", 1);
}
}
+
isc_boolean_t
cfg_obj_islist(cfg_obj_t *obj) {
REQUIRE(obj != NULL);
@@ -2268,8 +1126,8 @@ cfg_listelt_value(cfg_listelt_t *elt) {
* the named.conf syntax, as well as for the body of the
* options, view, zone, and other statements.
*/
-static isc_result_t
-parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+isc_result_t
+cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
{
const cfg_clausedef_t * const *clausesets = type->of;
isc_result_t result;
@@ -2304,13 +1162,13 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
* We accept "include" statements wherever a map body
* clause can occur.
*/
- if (strcasecmp(pctx->token.value.as_pointer, "include") == 0) {
+ if (strcasecmp(TOKEN_STRING(pctx), "include") == 0) {
/*
* Turn the file name into a temporary configuration
* object just so that it is not overwritten by the
* semicolon token.
*/
- CHECK(parse(pctx, &cfg_type_qstring, &includename));
+ CHECK(cfg_parse_obj(pctx, &cfg_type_qstring, &includename));
CHECK(parse_semicolon(pctx));
CHECK(parser_openfile(pctx, includename->
value.string.base));
@@ -2323,35 +1181,35 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
for (clause = *clauseset;
clause->name != NULL;
clause++) {
- if (strcasecmp(pctx->token.value.as_pointer,
+ if (strcasecmp(TOKEN_STRING(pctx),
clause->name) == 0)
goto done;
}
}
done:
if (clause == NULL || clause->name == NULL) {
- parser_error(pctx, LOG_NOPREP, "unknown option");
+ cfg_parser_error(pctx, CFG_LOG_NOPREP, "unknown option");
/*
* Try to recover by parsing this option as an unknown
* option and discarding it.
*/
- CHECK(parse(pctx, &cfg_type_unsupported, &eltobj));
- cfg_obj_destroy(pctx, &eltobj);
- CHECK(parse_semicolon(pctx));
- continue;
+ CHECK(cfg_parse_obj(pctx, &cfg_type_unsupported, &eltobj));
+ cfg_obj_destroy(pctx, &eltobj);
+ CHECK(parse_semicolon(pctx));
+ continue;
}
/* Clause is known. */
/* Issue warnings if appropriate */
if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)
- parser_warning(pctx, 0, "option '%s' is obsolete",
+ cfg_parser_warning(pctx, 0, "option '%s' is obsolete",
clause->name);
if ((clause->flags & CFG_CLAUSEFLAG_NOTIMP) != 0)
- parser_warning(pctx, 0, "option '%s' is "
+ cfg_parser_warning(pctx, 0, "option '%s' is "
"not implemented", clause->name);
if ((clause->flags & CFG_CLAUSEFLAG_NYI) != 0)
- parser_warning(pctx, 0, "option '%s' is "
+ cfg_parser_warning(pctx, 0, "option '%s' is "
"not implemented", clause->name);
/*
* Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
@@ -2367,7 +1225,7 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
/* Multivalued clause */
cfg_obj_t *listobj = NULL;
if (result == ISC_R_NOTFOUND) {
- CHECK(create_list(pctx,
+ CHECK(cfg_create_list(pctx,
&cfg_type_implicitlist,
&listobj));
symval.as_pointer = listobj;
@@ -2377,7 +1235,7 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
1, symval,
isc_symexists_reject);
if (result != ISC_R_SUCCESS) {
- parser_error(pctx, LOG_NEAR,
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
"isc_symtab_define(%s) "
"failed", clause->name);
isc_mem_put(pctx->mctx, list,
@@ -2390,7 +1248,7 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
}
elt = NULL;
- CHECK(parse_list_elt(pctx, clause->type, &elt));
+ CHECK(cfg_parse_listelt(pctx, clause->type, &elt));
CHECK(parse_semicolon(pctx));
ISC_LIST_APPEND(listobj->value.list, elt, link);
@@ -2406,12 +1264,12 @@ parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
callback));
CHECK(parse_semicolon(pctx));
} else if (result == ISC_R_SUCCESS) {
- parser_error(pctx, LOG_NEAR, "'%s' redefined",
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "'%s' redefined",
clause->name);
result = ISC_R_EXISTS;
goto cleanup;
} else {
- parser_error(pctx, LOG_NEAR,
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
"isc_symtab_define() failed");
goto cleanup;
}
@@ -2439,7 +1297,7 @@ parse_symtab_elt(cfg_parser_t *pctx, const char *name,
cfg_obj_t *obj = NULL;
isc_symvalue_t symval;
- CHECK(parse(pctx, elttype, &obj));
+ CHECK(cfg_parse_obj(pctx, elttype, &obj));
if (callback && pctx->callback != NULL)
CHECK(pctx->callback(name, obj, pctx->callbackarg));
@@ -2458,19 +1316,18 @@ parse_symtab_elt(cfg_parser_t *pctx, const char *name,
/*
* Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }"
*/
-static isc_result_t
-parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
-{
+isc_result_t
+cfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
- CHECK(parse_special(pctx, '{'));
- CHECK(parse_mapbody(pctx, type, ret));
- CHECK(parse_special(pctx, '}'));
+ CHECK(cfg_parse_special(pctx, '{'));
+ CHECK(cfg_parse_mapbody(pctx, type, ret));
+ CHECK(cfg_parse_special(pctx, '}'));
cleanup:
return (result);
}
/*
- * Subroutine for parse_named_map() and parse_addressed_map().
+ * Subroutine for cfg_parse_named_map() and cfg_parse_addressed_map().
*/
static isc_result_t
parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *type,
@@ -2480,8 +1337,8 @@ parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *
cfg_obj_t *idobj = NULL;
cfg_obj_t *mapobj = NULL;
- CHECK(parse(pctx, nametype, &idobj));
- CHECK(parse_map(pctx, type, &mapobj));
+ CHECK(cfg_parse_obj(pctx, nametype, &idobj));
+ CHECK(cfg_parse_map(pctx, type, &mapobj));
mapobj->value.map.id = idobj;
idobj = NULL;
*ret = mapobj;
@@ -2494,8 +1351,8 @@ parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *
* Parse a map identified by a string name. E.g., "name { foo 1; }".
* Used for the "key" and "channel" statements.
*/
-static isc_result_t
-parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (parse_any_named_map(pctx, &cfg_type_astring, type, ret));
}
@@ -2503,13 +1360,13 @@ parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
* Parse a map identified by a network address.
* Used for the "server" statement.
*/
-static isc_result_t
-parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (parse_any_named_map(pctx, &cfg_type_netaddr, type, ret));
}
-static void
-print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
isc_result_t result = ISC_R_SUCCESS;
const cfg_clausedef_t * const *clauseset;
@@ -2536,18 +1393,18 @@ print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
elt != NULL;
elt = ISC_LIST_NEXT(elt, link)) {
print_indent(pctx);
- print_cstr(pctx, clause->name);
- print(pctx, " ", 1);
- print_obj(pctx, elt->obj);
- print(pctx, ";\n", 2);
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, elt->obj);
+ cfg_print_chars(pctx, ";\n", 2);
}
} else {
/* Single-valued. */
print_indent(pctx);
- print_cstr(pctx, clause->name);
- print(pctx, " ", 1);
- print_obj(pctx, obj);
- print(pctx, ";\n", 2);
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, obj);
+ cfg_print_chars(pctx, ";\n", 2);
}
} else if (result == ISC_R_NOTFOUND) {
; /* do nothing */
@@ -2558,14 +1415,92 @@ print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
}
}
-static void
-print_map(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_clausedef_t * const *clauseset;
+ const cfg_clausedef_t *clause;
+
+ for (clauseset = type->of; *clauseset != NULL; clauseset++) {
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, clause->type);
+ cfg_print_chars(pctx, ";", 1);
+ /* XXX print flags here? */
+ cfg_print_chars(pctx, "\n\n", 2);
+ }
+ }
+}
+
+static struct flagtext {
+ unsigned int flag;
+ const char *text;
+} flagtexts[] = {
+ { CFG_CLAUSEFLAG_NOTIMP, "not implemented" },
+ { CFG_CLAUSEFLAG_NYI, "not yet implemented" },
+ { CFG_CLAUSEFLAG_OBSOLETE, "obsolete" },
+ { CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" },
+ { 0, NULL }
+};
+
+void
+cfg_print_map(cfg_printer_t *pctx, cfg_obj_t *obj) {
if (obj->value.map.id != NULL) {
- print_obj(pctx, obj->value.map.id);
- print(pctx, " ", 1);
+ cfg_print_obj(pctx, obj->value.map.id);
+ cfg_print_chars(pctx, " ", 1);
}
print_open(pctx);
- print_mapbody(pctx, obj);
+ cfg_print_mapbody(pctx, obj);
+ print_close(pctx);
+}
+
+static void
+print_clause_flags(cfg_printer_t *pctx, unsigned int flags) {
+ struct flagtext *p;
+ isc_boolean_t first = ISC_TRUE;
+ for (p = flagtexts; p->flag != 0; p++) {
+ if ((flags & p->flag) != 0) {
+ if (first)
+ cfg_print_chars(pctx, " // ", 4);
+ else
+ cfg_print_chars(pctx, ", ", 2);
+ cfg_print_cstr(pctx, p->text);
+ first = ISC_FALSE;
+ }
+ }
+}
+
+void
+cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_clausedef_t * const *clauseset;
+ const cfg_clausedef_t *clause;
+
+ if (type->parse == cfg_parse_named_map) {
+ cfg_doc_obj(pctx, &cfg_type_astring);
+ cfg_print_chars(pctx, " ", 1);
+ } else if (type->parse == cfg_parse_addressed_map) {
+ cfg_doc_obj(pctx, &cfg_type_netaddr);
+ cfg_print_chars(pctx, " ", 1);
+ }
+
+ print_open(pctx);
+
+ for (clauseset = type->of; *clauseset != NULL; clauseset++) {
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ print_indent(pctx);
+ cfg_print_cstr(pctx, clause->name);
+ if (clause->type->print != cfg_print_void)
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, clause->type);
+ cfg_print_chars(pctx, ";", 1);
+ print_clause_flags(pctx, clause->flags);
+ cfg_print_chars(pctx, "\n", 1);
+ }
+ }
print_close(pctx);
}
@@ -2610,8 +1545,8 @@ parse_token(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
UNUSED(type);
- CHECK(create_cfgobj(pctx, &cfg_type_token, &obj));
- CHECK(cfg_gettoken(pctx, QSTRING));
+ CHECK(cfg_create_obj(pctx, &cfg_type_token, &obj));
+ CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
if (pctx->token.type == isc_tokentype_eof) {
cfg_ungettoken(pctx);
result = ISC_R_EOF;
@@ -2630,8 +1565,10 @@ parse_token(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static cfg_type_t cfg_type_token = {
- "token", parse_token, print_ustring, &cfg_rep_string, NULL };
+cfg_type_t cfg_type_token = {
+ "token", parse_token, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
/*
* An unsupported option. This is just a list of tokens with balanced braces
@@ -2644,7 +1581,7 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
int braces = 0;
- CHECK(create_list(pctx, type, &listobj));
+ CHECK(cfg_create_list(pctx, type, &listobj));
for (;;) {
cfg_listelt_t *elt = NULL;
@@ -2660,12 +1597,12 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
break;
}
if (pctx->token.type == isc_tokentype_eof || braces < 0) {
- parser_error(pctx, LOG_NEAR, "unexpected token");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "unexpected token");
result = ISC_R_UNEXPECTEDTOKEN;
goto cleanup;
}
- CHECK(parse_list_elt(pctx, &cfg_type_token, &elt));
+ CHECK(cfg_parse_listelt(pctx, &cfg_type_token, &elt));
ISC_LIST_APPEND(listobj->value.list, elt, link);
}
INSIST(braces == 0);
@@ -2677,85 +1614,18 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static cfg_type_t cfg_type_unsupported = {
- "unsupported", parse_unsupported, print_spacelist,
+cfg_type_t cfg_type_unsupported = {
+ "unsupported", parse_unsupported, cfg_print_spacelist, cfg_doc_terminal,
&cfg_rep_list, NULL
};
/*
- * A "controls" statement is represented as a map with the multivalued
- * "inet" and "unix" clauses. Inet controls are tuples; unix controls
- * are cfg_unsupported_t objects.
- */
-
-static keyword_type_t controls_allow_kw = {
- "allow", &cfg_type_bracketed_aml };
-static cfg_type_t cfg_type_controls_allow = {
- "controls_allow", parse_keyvalue,
- print_keyvalue, &cfg_rep_list, &controls_allow_kw
-};
-
-static keyword_type_t controls_keys_kw = {
- "keys", &cfg_type_keylist };
-static cfg_type_t cfg_type_controls_keys = {
- "controls_keys", parse_optional_keyvalue,
- print_keyvalue, &cfg_rep_list, &controls_keys_kw
-};
-
-static cfg_tuplefielddef_t inetcontrol_fields[] = {
- { "address", &cfg_type_controls_sockaddr, 0 },
- { "allow", &cfg_type_controls_allow, 0 },
- { "keys", &cfg_type_controls_keys, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_inetcontrol = {
- "inetcontrol", parse_tuple, print_tuple, &cfg_rep_tuple,
- inetcontrol_fields
-};
-
-static cfg_clausedef_t
-controls_clauses[] = {
- { "inet", &cfg_type_inetcontrol, CFG_CLAUSEFLAG_MULTI },
- { "unix", &cfg_type_unsupported,
- CFG_CLAUSEFLAG_MULTI|CFG_CLAUSEFLAG_NOTIMP },
- { NULL, NULL, 0 }
-};
-static cfg_clausedef_t *
-controls_clausesets[] = {
- controls_clauses,
- NULL
-};
-static cfg_type_t cfg_type_controls = {
- "controls", parse_map, print_map, &cfg_rep_map, &controls_clausesets
-};
-
-/*
- * An optional class, as used in view and zone statements.
- */
-static isc_result_t
-parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
- UNUSED(type);
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string)
- CHECK(parse(pctx, &cfg_type_ustring, ret));
- else
- CHECK(parse(pctx, &cfg_type_void, ret));
- cleanup:
- return (result);
-}
-
-static cfg_type_t cfg_type_optional_class = {
- "optional_class", parse_optional_class, NULL, NULL, NULL };
-
-
-/*
* Try interpreting the current token as a network address.
*
- * If WILDOK is set in flags, "*" can be used as a wildcard
- * and at least one of V4OK and V6OK must also be set. The
- * "*" is interpreted as the IPv4 wildcard address if V4OK is
- * set (including the case where V4OK and V6OK are both set),
+ * If CFG_ADDR_WILDOK is set in flags, "*" can be used as a wildcard
+ * and at least one of CFG_ADDR_V4OK and CFG_ADDR_V6OK must also be set. The
+ * "*" is interpreted as the IPv4 wildcard address if CFG_ADDR_V4OK is
+ * set (including the case where CFG_ADDR_V4OK and CFG_ADDR_V6OK are both set),
* and the IPv6 wildcard address otherwise.
*/
static isc_result_t
@@ -2767,25 +1637,25 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
if (pctx->token.type != isc_tokentype_string)
return (ISC_R_UNEXPECTEDTOKEN);
- s = pctx->token.value.as_pointer;
- if ((flags & WILDOK) != 0 && strcmp(s, "*") == 0) {
- if ((flags & V4OK) != 0) {
+ s = TOKEN_STRING(pctx);
+ if ((flags & CFG_ADDR_WILDOK) != 0 && strcmp(s, "*") == 0) {
+ if ((flags & CFG_ADDR_V4OK) != 0) {
isc_netaddr_any(na);
return (ISC_R_SUCCESS);
- } else if ((flags & V6OK) != 0) {
+ } else if ((flags & CFG_ADDR_V6OK) != 0) {
isc_netaddr_any6(na);
return (ISC_R_SUCCESS);
} else {
INSIST(0);
}
} else {
- if ((flags & (V4OK | V4PREFIXOK)) != 0) {
+ if ((flags & (CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK)) != 0) {
if (inet_pton(AF_INET, s, &in4a) == 1) {
isc_netaddr_fromin(na, &in4a);
return (ISC_R_SUCCESS);
}
}
- if ((flags & V4PREFIXOK) != 0 &&
+ if ((flags & CFG_ADDR_V4PREFIXOK) != 0 &&
strlen(s) <= 15U) {
char buf[64];
int i;
@@ -2799,9 +1669,35 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
}
}
}
- if (flags & V6OK) {
- if (inet_pton(AF_INET6, s, &in6a) == 1) {
+ if ((flags & CFG_ADDR_V6OK) != 0 &&
+ strlen(s) <= 127U) {
+ char buf[128]; /* see lib/bind9/getaddresses.c */
+ char *d; /* zone delimiter */
+ isc_uint32_t zone = 0; /* scope zone ID */
+
+ strlcpy(buf, s, sizeof(buf));
+ d = strchr(buf, '%');
+ if (d != NULL)
+ *d = '\0';
+
+ if (inet_pton(AF_INET6, buf, &in6a) == 1) {
+ if (d != NULL) {
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ isc_result_t result;
+
+ result = isc_netscope_pton(AF_INET6,
+ d + 1,
+ &in6a,
+ &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#else
+ return (ISC_R_BADADDRESSFORM);
+#endif
+ }
+
isc_netaddr_fromin6(na, &in6a);
+ isc_netaddr_setzone(na, zone);
return (ISC_R_SUCCESS);
}
}
@@ -2809,44 +1705,44 @@ token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
return (ISC_R_UNEXPECTEDTOKEN);
}
-static isc_result_t
-get_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
+isc_result_t
+cfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
isc_result_t result;
CHECK(cfg_gettoken(pctx, 0));
result = token_addr(pctx, flags, na);
if (result == ISC_R_UNEXPECTEDTOKEN)
- parser_error(pctx, LOG_NEAR, "expected IP address");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected IP address");
cleanup:
return (result);
}
-static isc_boolean_t
-looking_at_netaddr(cfg_parser_t *pctx, unsigned int flags) {
+isc_boolean_t
+cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags) {
isc_result_t result;
isc_netaddr_t na_dummy;
result = token_addr(pctx, flags, &na_dummy);
return (ISC_TF(result == ISC_R_SUCCESS));
}
-static isc_result_t
-get_port(cfg_parser_t *pctx, unsigned int flags, in_port_t *port) {
+isc_result_t
+cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port) {
isc_result_t result;
CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
- if ((flags & WILDOK) != 0 &&
+ if ((flags & CFG_ADDR_WILDOK) != 0 &&
pctx->token.type == isc_tokentype_string &&
- strcmp(pctx->token.value.as_pointer, "*") == 0) {
+ strcmp(TOKEN_STRING(pctx), "*") == 0) {
*port = 0;
return (ISC_R_SUCCESS);
}
if (pctx->token.type != isc_tokentype_number) {
- parser_error(pctx, LOG_NEAR,
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected port number or '*'");
return (ISC_R_UNEXPECTEDTOKEN);
}
if (pctx->token.value.as_ulong >= 65536U) {
- parser_error(pctx, LOG_NEAR,
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
"port number out of range");
return (ISC_R_UNEXPECTEDTOKEN);
}
@@ -2856,80 +1752,8 @@ get_port(cfg_parser_t *pctx, unsigned int flags, in_port_t *port) {
return (result);
}
-static isc_result_t
-parse_querysource(cfg_parser_t *pctx, int flags, cfg_obj_t **ret) {
- isc_result_t result;
- cfg_obj_t *obj = NULL;
- isc_netaddr_t netaddr;
- in_port_t port;
- unsigned int have_address = 0;
- unsigned int have_port = 0;
-
- if ((flags & V4OK) != 0)
- isc_netaddr_any(&netaddr);
- else if ((flags & V6OK) != 0)
- isc_netaddr_any6(&netaddr);
- else
- INSIST(0);
-
- port = 0;
-
- CHECK(create_cfgobj(pctx, &cfg_type_querysource, &obj));
- for (;;) {
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string) {
- if (strcasecmp(pctx->token.value.as_pointer,
- "address") == 0)
- {
- /* read "address" */
- CHECK(cfg_gettoken(pctx, 0));
- CHECK(get_addr(pctx, flags|WILDOK, &netaddr));
- have_address++;
- } else if (strcasecmp(pctx->token.value.as_pointer,
- "port") == 0)
- {
- /* read "port" */
- CHECK(cfg_gettoken(pctx, 0));
- CHECK(get_port(pctx, WILDOK, &port));
- have_port++;
- } else {
- parser_error(pctx, LOG_NEAR,
- "expected 'address' or 'port'");
- return (ISC_R_UNEXPECTEDTOKEN);
- }
- } else
- break;
- }
- if (have_address > 1 || have_port > 1 ||
- have_address + have_port == 0) {
- parser_error(pctx, 0, "expected one address and/or port");
- return (ISC_R_UNEXPECTEDTOKEN);
- }
-
- isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
- *ret = obj;
- return (ISC_R_SUCCESS);
-
- cleanup:
- parser_error(pctx, LOG_NEAR, "invalid query source");
- CLEANUP_OBJ(obj);
- return (result);
-}
-
-static isc_result_t
-parse_querysource4(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- UNUSED(type);
- return (parse_querysource(pctx, V4OK, ret));
-}
-
-static isc_result_t
-parse_querysource6(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- UNUSED(type);
- return (parse_querysource(pctx, V6OK, ret));
-}
-
-static void
-print_isc_netaddr(cfg_printer_t *pctx, isc_netaddr_t *na) {
+void
+cfg_print_rawaddr(cfg_printer_t *pctx, isc_netaddr_t *na) {
isc_result_t result;
char text[128];
isc_buffer_t buf;
@@ -2937,26 +1761,9 @@ print_isc_netaddr(cfg_printer_t *pctx, isc_netaddr_t *na) {
isc_buffer_init(&buf, text, sizeof(text));
result = isc_netaddr_totext(na, &buf);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- print(pctx, isc_buffer_base(&buf), isc_buffer_usedlength(&buf));
+ cfg_print_chars(pctx, isc_buffer_base(&buf), isc_buffer_usedlength(&buf));
}
-static void
-print_querysource(cfg_printer_t *pctx, cfg_obj_t *obj) {
- isc_netaddr_t na;
- isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr);
- print(pctx, "address ", 8);
- print_isc_netaddr(pctx, &na);
- print(pctx, " port ", 6);
- print_uint(pctx, isc_sockaddr_getport(&obj->value.sockaddr));
-}
-
-static cfg_type_t cfg_type_querysource4 = {
- "querysource4", parse_querysource4, NULL, NULL, NULL };
-static cfg_type_t cfg_type_querysource6 = {
- "querysource6", parse_querysource6, NULL, NULL, NULL };
-static cfg_type_t cfg_type_querysource = {
- "querysource", NULL, print_querysource, &cfg_rep_sockaddr, NULL };
-
/* netaddr */
static isc_result_t
@@ -2965,8 +1772,8 @@ parse_netaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
cfg_obj_t *obj = NULL;
isc_netaddr_t netaddr;
UNUSED(type);
- CHECK(create_cfgobj(pctx, type, &obj));
- CHECK(get_addr(pctx, V4OK|V6OK, &netaddr));
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK, &netaddr));
isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, 0);
*ret = obj;
return (ISC_R_SUCCESS);
@@ -2975,20 +1782,25 @@ parse_netaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (result);
}
-static cfg_type_t cfg_type_netaddr = {
- "netaddr", parse_netaddr, print_sockaddr, &cfg_rep_sockaddr, NULL };
+cfg_type_t cfg_type_netaddr = {
+ "netaddr", parse_netaddr, cfg_print_sockaddr, cfg_doc_terminal,
+ &cfg_rep_sockaddr, NULL
+};
/* netprefix */
-static isc_result_t
-parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+isc_result_t
+cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
cfg_obj_t *obj = NULL;
isc_result_t result;
isc_netaddr_t netaddr;
unsigned int addrlen, prefixlen;
UNUSED(type);
- CHECK(get_addr(pctx, V4OK|V4PREFIXOK|V6OK, &netaddr));
+ CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
+ CFG_ADDR_V6OK, &netaddr));
switch (netaddr.family) {
case AF_INET:
addrlen = 32;
@@ -3007,35 +1819,35 @@ parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
CHECK(cfg_gettoken(pctx, 0)); /* read "/" */
CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
if (pctx->token.type != isc_tokentype_number) {
- parser_error(pctx, LOG_NEAR,
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
"expected prefix length");
return (ISC_R_UNEXPECTEDTOKEN);
}
prefixlen = pctx->token.value.as_ulong;
if (prefixlen > addrlen) {
- parser_error(pctx, LOG_NOPREP,
+ cfg_parser_error(pctx, CFG_LOG_NOPREP,
"invalid prefix length");
return (ISC_R_RANGE);
}
} else {
prefixlen = addrlen;
}
- CHECK(create_cfgobj(pctx, &cfg_type_netprefix, &obj));
+ CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));
obj->value.netprefix.address = netaddr;
obj->value.netprefix.prefixlen = prefixlen;
*ret = obj;
return (ISC_R_SUCCESS);
cleanup:
- parser_error(pctx, LOG_NEAR, "expected network prefix");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected network prefix");
return (result);
}
static void
print_netprefix(cfg_printer_t *pctx, cfg_obj_t *obj) {
cfg_netprefix_t *p = &obj->value.netprefix;
- print_isc_netaddr(pctx, &p->address);
- print(pctx, "/", 1);
- print_uint(pctx, p->prefixlen);
+ cfg_print_rawaddr(pctx, &p->address);
+ cfg_print_chars(pctx, "/", 1);
+ cfg_print_rawuint(pctx, p->prefixlen);
}
isc_boolean_t
@@ -3052,79 +1864,9 @@ cfg_obj_asnetprefix(cfg_obj_t *obj, isc_netaddr_t *netaddr,
*prefixlen = obj->value.netprefix.prefixlen;
}
-static cfg_type_t cfg_type_netprefix = {
- "netprefix", parse_netprefix, print_netprefix, &cfg_rep_netprefix, NULL };
-
-/* addrmatchelt */
-
-static isc_result_t
-parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
- UNUSED(type);
-
- CHECK(cfg_peektoken(pctx, QSTRING));
-
- if (pctx->token.type == isc_tokentype_string ||
- pctx->token.type == isc_tokentype_qstring) {
- if (pctx->token.type == isc_tokentype_string &&
- (strcasecmp(pctx->token.value.as_pointer, "key") == 0)) {
- CHECK(parse(pctx, &cfg_type_keyref, ret));
- } else {
- if (looking_at_netaddr(pctx, V4OK|V4PREFIXOK|V6OK)) {
- CHECK(parse_netprefix(pctx, NULL, ret));
- } else {
- CHECK(parse_astring(pctx, NULL, ret));
- }
- }
- } else if (pctx->token.type == isc_tokentype_special) {
- if (pctx->token.value.as_char == '{') {
- /* Nested match list. */
- CHECK(parse(pctx, &cfg_type_bracketed_aml, ret));
- } else if (pctx->token.value.as_char == '!') {
- CHECK(cfg_gettoken(pctx, 0)); /* read "!" */
- CHECK(parse(pctx, &cfg_type_negated, ret));
- } else {
- goto bad;
- }
- } else {
- bad:
- parser_error(pctx, LOG_NEAR,
- "expected IP match list element");
- return (ISC_R_UNEXPECTEDTOKEN);
- }
- cleanup:
- return (result);
-}
-
-/*
- * A negated address match list element (like "! 10.0.0.1").
- * Somewhat sneakily, the caller is expected to parse the
- * "!", but not to print it.
- */
-
-static cfg_tuplefielddef_t negated_fields[] = {
- { "value", &cfg_type_addrmatchelt, 0 },
- { NULL, NULL, 0 }
-};
-
-static void
-print_negated(cfg_printer_t *pctx, cfg_obj_t *obj) {
- print(pctx, "!", 1);
- print_tuple(pctx, obj);
-}
-
-static cfg_type_t cfg_type_negated = {
- "negated", parse_tuple, print_negated, &cfg_rep_tuple,
- &negated_fields
-};
-
-/* an address match list element */
-
-static cfg_type_t cfg_type_addrmatchelt = {
- "address_match_element", parse_addrmatchelt, NULL, NULL, NULL };
-static cfg_type_t cfg_type_bracketed_aml = {
- "bracketed_aml", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_addrmatchelt
+cfg_type_t cfg_type_netprefix = {
+ "netprefix", cfg_parse_netprefix, print_netprefix, cfg_doc_terminal,
+ &cfg_rep_netprefix, NULL
};
static isc_result_t
@@ -3136,13 +1878,13 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type,
in_port_t port = 0;
cfg_obj_t *obj = NULL;
- CHECK(create_cfgobj(pctx, type, &obj));
- CHECK(get_addr(pctx, flags, &netaddr));
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
CHECK(cfg_peektoken(pctx, 0));
if (pctx->token.type == isc_tokentype_string &&
- strcasecmp(pctx->token.value.as_pointer, "port") == 0) {
+ strcasecmp(TOKEN_STRING(pctx), "port") == 0) {
CHECK(cfg_gettoken(pctx, 0)); /* read "port" */
- CHECK(get_port(pctx, flags, &port));
+ CHECK(cfg_parse_rawport(pctx, flags, &port));
}
isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
*ret = obj;
@@ -3153,25 +1895,62 @@ parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type,
return (result);
}
-static isc_result_t
-parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+static unsigned int sockaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
+cfg_type_t cfg_type_sockaddr = {
+ "sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr,
+ &cfg_rep_sockaddr, &sockaddr_flags
+};
+
+isc_result_t
+cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
const unsigned int *flagp = type->of;
- return (parse_sockaddrsub(pctx, &cfg_type_sockaddr4wild, *flagp, ret));
+ return (parse_sockaddrsub(pctx, &cfg_type_sockaddr, *flagp, ret));
}
-static void
-print_sockaddr(cfg_printer_t *pctx, cfg_obj_t *obj) {
+void
+cfg_print_sockaddr(cfg_printer_t *pctx, cfg_obj_t *obj) {
isc_netaddr_t netaddr;
in_port_t port;
char buf[ISC_NETADDR_FORMATSIZE];
isc_netaddr_fromsockaddr(&netaddr, &obj->value.sockaddr);
isc_netaddr_format(&netaddr, buf, sizeof(buf));
- print_cstr(pctx, buf);
+ cfg_print_cstr(pctx, buf);
port = isc_sockaddr_getport(&obj->value.sockaddr);
if (port != 0) {
- print(pctx, " port ", 6);
- print_uint(pctx, port);
+ cfg_print_chars(pctx, " port ", 6);
+ cfg_print_rawuint(pctx, port);
+ }
+}
+
+void
+cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const unsigned int *flagp = type->of;
+ int n = 0;
+ cfg_print_chars(pctx, "( ", 2);
+ if (*flagp & CFG_ADDR_V4OK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_V6OK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_WILDOK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_chars(pctx, "*", 1);
+ n++;
+ }
+ cfg_print_chars(pctx, " ) ", 3);
+ if (*flagp & CFG_ADDR_WILDOK) {
+ cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]");
+ } else {
+ cfg_print_cstr(pctx, "[ port <integer> ]");
}
}
@@ -3187,344 +1966,7 @@ cfg_obj_assockaddr(cfg_obj_t *obj) {
return (&obj->value.sockaddr);
}
-/* An IPv4/IPv6 address with optional port, "*" accepted as wildcard. */
-static unsigned int sockaddr4wild_flags = WILDOK|V4OK;
-static cfg_type_t cfg_type_sockaddr4wild = {
- "sockaddr4wild", parse_sockaddr, print_sockaddr,
- &cfg_rep_sockaddr, &sockaddr4wild_flags
-};
-
-static unsigned int sockaddr6wild_flags = WILDOK|V6OK;
-static cfg_type_t cfg_type_sockaddr6wild = {
- "v6addrportwild", parse_sockaddr, print_sockaddr,
- &cfg_rep_sockaddr, &sockaddr6wild_flags
-};
-
-static unsigned int sockaddr_flags = V4OK|V6OK;
-static cfg_type_t cfg_type_sockaddr = {
- "sockaddr", parse_sockaddr, print_sockaddr,
- &cfg_rep_sockaddr, &sockaddr_flags
-};
-
-/*
- * The socket address syntax in the "controls" statement is silly.
- * It allows both socket address families, but also allows "*",
- * whis is gratuitously interpreted as the IPv4 wildcard address.
- */
-static unsigned int controls_sockaddr_flags = V4OK|V6OK|WILDOK;
-static cfg_type_t cfg_type_controls_sockaddr = {
- "controls_sockaddr", parse_sockaddr, print_sockaddr,
- &cfg_rep_sockaddr, &controls_sockaddr_flags };
-
-
-/*
- * Handle the special kludge syntax of the "keys" clause in the "server"
- * statement, which takes a single key with our without braces and semicolon.
- */
-static isc_result_t
-parse_server_key_kludge(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
-{
- isc_result_t result;
- isc_boolean_t braces = ISC_FALSE;
- UNUSED(type);
-
- /* Allow opening brace. */
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_special &&
- pctx->token.value.as_char == '{') {
- result = cfg_gettoken(pctx, 0);
- braces = ISC_TRUE;
- }
-
- CHECK(parse(pctx, &cfg_type_astring, ret));
-
- if (braces) {
- /* Skip semicolon if present. */
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_special &&
- pctx->token.value.as_char == ';')
- CHECK(cfg_gettoken(pctx, 0));
-
- CHECK(parse_special(pctx, '}'));
- }
- cleanup:
- return (result);
-}
-static cfg_type_t cfg_type_server_key_kludge = {
- "server_key", parse_server_key_kludge, NULL, NULL, NULL };
-
-
-/*
- * An optional logging facility.
- */
-
-static isc_result_t
-parse_optional_facility(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
-{
- isc_result_t result;
- UNUSED(type);
-
- CHECK(cfg_peektoken(pctx, QSTRING));
- if (pctx->token.type == isc_tokentype_string ||
- pctx->token.type == isc_tokentype_qstring) {
- CHECK(parse(pctx, &cfg_type_astring, ret));
- } else {
- CHECK(parse(pctx, &cfg_type_void, ret));
- }
- cleanup:
- return (result);
-}
-
-static cfg_type_t cfg_type_optional_facility = {
- "optional_facility", parse_optional_facility, NULL, NULL, NULL };
-
-
-/*
- * A log severity. Return as a string, except "debug N",
- * which is returned as a keyword object.
- */
-
-static keyword_type_t debug_kw = { "debug", &cfg_type_uint32 };
-static cfg_type_t cfg_type_debuglevel = {
- "debuglevel", parse_keyvalue,
- print_keyvalue, &cfg_rep_uint32, &debug_kw
-};
-
-static isc_result_t
-parse_logseverity(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
- UNUSED(type);
-
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string &&
- strcasecmp(pctx->token.value.as_pointer, "debug") == 0) {
- CHECK(cfg_gettoken(pctx, 0)); /* read "debug" */
- CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER));
- if (pctx->token.type == isc_tokentype_number) {
- CHECK(parse_uint32(pctx, NULL, ret));
- } else {
- /*
- * The debug level is optional and defaults to 1.
- * This makes little sense, but we support it for
- * compatibility with BIND 8.
- */
- CHECK(create_cfgobj(pctx, &cfg_type_uint32, ret));
- (*ret)->value.uint32 = 1;
- }
- (*ret)->type = &cfg_type_debuglevel; /* XXX kludge */
- } else {
- CHECK(parse(pctx, &cfg_type_loglevel, ret));
- }
- cleanup:
- return (result);
-}
-
-static cfg_type_t cfg_type_logseverity = {
- "logseverity", parse_logseverity, NULL, NULL, NULL };
-
-/*
- * The "file" clause of the "channel" statement.
- * This is yet another special case.
- */
-
-static const char *logversions_enums[] = { "unlimited", NULL };
-static isc_result_t
-parse_logversions(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_enum_or_other(pctx, type, &cfg_type_uint32, ret));
-}
-static cfg_type_t cfg_type_logversions = {
- "logversions", parse_logversions, print_ustring,
- &cfg_rep_string, logversions_enums
-};
-
-static cfg_tuplefielddef_t logfile_fields[] = {
- { "file", &cfg_type_qstring, 0 },
- { "versions", &cfg_type_logversions, 0 },
- { "size", &cfg_type_size, 0 },
- { NULL, NULL, 0 }
-};
-
-static isc_result_t
-parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
- cfg_obj_t *obj = NULL;
- const cfg_tuplefielddef_t *fields = type->of;
-
- CHECK(create_tuple(pctx, type, &obj));
-
- /* Parse the mandatory "file" field */
- CHECK(parse(pctx, fields[0].type, &obj->value.tuple[0]));
-
- /* Parse "versions" and "size" fields in any order. */
- for (;;) {
- CHECK(cfg_peektoken(pctx, 0));
- if (pctx->token.type == isc_tokentype_string) {
- CHECK(cfg_gettoken(pctx, 0));
- if (strcasecmp(pctx->token.value.as_pointer,
- "versions") == 0 &&
- obj->value.tuple[1] == NULL) {
- CHECK(parse(pctx, fields[1].type,
- &obj->value.tuple[1]));
- } else if (strcasecmp(pctx->token.value.as_pointer,
- "size") == 0 &&
- obj->value.tuple[2] == NULL) {
- CHECK(parse(pctx, fields[2].type,
- &obj->value.tuple[2]));
- } else {
- break;
- }
- } else {
- break;
- }
- }
-
- /* Create void objects for missing optional values. */
- if (obj->value.tuple[1] == NULL)
- CHECK(parse_void(pctx, NULL, &obj->value.tuple[1]));
- if (obj->value.tuple[2] == NULL)
- CHECK(parse_void(pctx, NULL, &obj->value.tuple[2]));
-
- *ret = obj;
- return (ISC_R_SUCCESS);
-
- cleanup:
- CLEANUP_OBJ(obj);
- return (result);
-}
-
-static void
-print_logfile(cfg_printer_t *pctx, cfg_obj_t *obj) {
- print_obj(pctx, obj->value.tuple[0]); /* file */
- if (obj->value.tuple[1]->type->print != print_void) {
- print(pctx, " versions ", 10);
- print_obj(pctx, obj->value.tuple[1]);
- }
- if (obj->value.tuple[2]->type->print != print_void) {
- print(pctx, " size ", 6);
- print_obj(pctx, obj->value.tuple[2]);
- }
-}
-
-static cfg_type_t cfg_type_logfile = {
- "logfile", parse_logfile, print_logfile, &cfg_rep_tuple,
- logfile_fields
-};
-
-
-/*
- * lwres
- */
-
-static cfg_tuplefielddef_t lwres_view_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "class", &cfg_type_optional_class, 0 },
- { NULL, NULL, 0 }
-};
-static cfg_type_t cfg_type_lwres_view = {
- "lwres_view", parse_tuple, print_tuple, &cfg_rep_tuple,
- lwres_view_fields
-};
-
-static cfg_type_t cfg_type_lwres_searchlist = {
- "lwres_searchlist", parse_bracketed_list, print_bracketed_list,
- &cfg_rep_list, &cfg_type_astring };
-
-static cfg_clausedef_t
-lwres_clauses[] = {
- { "listen-on", &cfg_type_portiplist, 0 },
- { "view", &cfg_type_lwres_view, 0 },
- { "search", &cfg_type_lwres_searchlist, 0 },
- { "ndots", &cfg_type_uint32, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-lwres_clausesets[] = {
- lwres_clauses,
- NULL
-};
-static cfg_type_t cfg_type_lwres = {
- "lwres", parse_map, print_map, &cfg_rep_map, lwres_clausesets };
-
-/*
- * rndc
- */
-
-static cfg_clausedef_t
-rndcconf_options_clauses[] = {
- { "default-server", &cfg_type_astring, 0 },
- { "default-key", &cfg_type_astring, 0 },
- { "default-port", &cfg_type_uint32, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-rndcconf_options_clausesets[] = {
- rndcconf_options_clauses,
- NULL
-};
-
-static cfg_type_t cfg_type_rndcconf_options = {
- "rndcconf_options", parse_map, print_map, &cfg_rep_map,
- rndcconf_options_clausesets
-};
-
-static cfg_clausedef_t
-rndcconf_server_clauses[] = {
- { "key", &cfg_type_astring, 0 },
- { "port", &cfg_type_uint32, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-rndcconf_server_clausesets[] = {
- rndcconf_server_clauses,
- NULL
-};
-
-static cfg_type_t cfg_type_rndcconf_server = {
- "rndcconf_server", parse_named_map, print_map, &cfg_rep_map,
- rndcconf_server_clausesets
-};
-
-static cfg_clausedef_t
-rndcconf_clauses[] = {
- { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
- { "server", &cfg_type_rndcconf_server, CFG_CLAUSEFLAG_MULTI },
- { "options", &cfg_type_rndcconf_options, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-rndcconf_clausesets[] = {
- rndcconf_clauses,
- NULL
-};
-
-LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndcconf = {
- "rndcconf", parse_mapbody, print_mapbody, &cfg_rep_map,
- rndcconf_clausesets
-};
-
-static cfg_clausedef_t
-rndckey_clauses[] = {
- { "key", &cfg_type_key, 0 },
- { NULL, NULL, 0 }
-};
-
-static cfg_clausedef_t *
-rndckey_clausesets[] = {
- rndckey_clauses,
- NULL
-};
-
-LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = {
- "rndckey", parse_mapbody, print_mapbody, &cfg_rep_map,
- rndckey_clausesets
-};
-
-
-static isc_result_t
+isc_result_t
cfg_gettoken(cfg_parser_t *pctx, int options) {
isc_result_t result;
@@ -3566,23 +2008,23 @@ cfg_gettoken(cfg_parser_t *pctx, int options) {
case ISC_R_NOSPACE:
/* More understandable than "ran out of space". */
- parser_error(pctx, LOG_NEAR, "token too big");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "token too big");
break;
case ISC_R_IOERROR:
- parser_error(pctx, 0, "%s",
+ cfg_parser_error(pctx, 0, "%s",
isc_result_totext(result));
break;
default:
- parser_error(pctx, LOG_NEAR, "%s",
- isc_result_totext(result));
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "%s",
+ isc_result_totext(result));
break;
}
return (result);
}
-static void
+void
cfg_ungettoken(cfg_parser_t *pctx) {
if (pctx->seen_eof)
return;
@@ -3590,7 +2032,7 @@ cfg_ungettoken(cfg_parser_t *pctx) {
pctx->ungotten = ISC_TRUE;
}
-static isc_result_t
+isc_result_t
cfg_peektoken(cfg_parser_t *pctx, int options) {
isc_result_t result;
CHECK(cfg_gettoken(pctx, options));
@@ -3607,20 +2049,20 @@ static isc_result_t
cfg_getstringtoken(cfg_parser_t *pctx) {
isc_result_t result;
- result = cfg_gettoken(pctx, QSTRING);
+ result = cfg_gettoken(pctx, CFG_LEXOPT_QSTRING);
if (result != ISC_R_SUCCESS)
return (result);
if (pctx->token.type != isc_tokentype_string &&
pctx->token.type != isc_tokentype_qstring) {
- parser_error(pctx, LOG_NEAR, "expected string");
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected string");
return (ISC_R_UNEXPECTEDTOKEN);
}
return (ISC_R_SUCCESS);
}
-static void
-parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
+void
+cfg_parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
parser_complain(pctx, ISC_FALSE, flags, fmt, args);
@@ -3628,8 +2070,8 @@ parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
pctx->errors++;
}
-static void
-parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
+void
+cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
parser_complain(pctx, ISC_TRUE, flags, fmt, args);
@@ -3679,7 +2121,7 @@ parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
FATAL_ERROR(__FILE__, __LINE__,
"error message would overflow");
- if ((flags & (LOG_NEAR|LOG_BEFORE|LOG_NOPREP)) != 0) {
+ if ((flags & (CFG_LOG_NEAR|CFG_LOG_BEFORE|CFG_LOG_NOPREP)) != 0) {
isc_region_t r;
if (pctx->ungotten)
@@ -3702,9 +2144,9 @@ parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
}
/* Choose a preposition. */
- if (flags & LOG_NEAR)
+ if (flags & CFG_LOG_NEAR)
prep = " near ";
- else if (flags & LOG_BEFORE)
+ else if (flags & CFG_LOG_BEFORE)
prep = " before ";
else
prep = " ";
@@ -3733,8 +2175,18 @@ cfg_obj_log(cfg_obj_t *obj, isc_log_t *lctx, int level, const char *fmt, ...) {
va_end(ap);
}
-static isc_result_t
-create_cfgobj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+const char *
+cfg_obj_file(cfg_obj_t *obj) {
+ return (obj->file);
+}
+
+unsigned int
+cfg_obj_line(cfg_obj_t *obj) {
+ return (obj->line);
+}
+
+isc_result_t
+cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
cfg_obj_t *obj;
obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t));
@@ -3767,7 +2219,7 @@ create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_symtab_t *symtab = NULL;
cfg_obj_t *obj = NULL;
- CHECK(create_cfgobj(pctx, type, &obj));
+ CHECK(cfg_create_obj(pctx, type, &obj));
CHECK(isc_symtab_create(pctx->mctx, 5, /* XXX */
map_symtabitem_destroy,
pctx, ISC_FALSE, &symtab));
@@ -3812,151 +2264,16 @@ free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) {
UNUSED(obj);
}
-/*
- * Data and functions for printing grammar summaries.
- */
-static struct flagtext {
- unsigned int flag;
- const char *text;
-} flagtexts[] = {
- { CFG_CLAUSEFLAG_NOTIMP, "not implemented" },
- { CFG_CLAUSEFLAG_NYI, "not yet implemented" },
- { CFG_CLAUSEFLAG_OBSOLETE, "obsolete" },
- { CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" },
- { 0, NULL }
-};
-
-static void
-print_clause_flags(cfg_printer_t *pctx, unsigned int flags) {
- struct flagtext *p;
- isc_boolean_t first = ISC_TRUE;
- for (p = flagtexts; p->flag != 0; p++) {
- if ((flags & p->flag) != 0) {
- if (first)
- print(pctx, " // ", 4);
- else
- print(pctx, ", ", 2);
- print_cstr(pctx, p->text);
- first = ISC_FALSE;
- }
- }
+void
+cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type) {
+ type->doc(pctx, type);
}
-static void
-print_grammar(cfg_printer_t *pctx, const cfg_type_t *type) {
- if (type->print == print_mapbody) {
- const cfg_clausedef_t * const *clauseset;
- const cfg_clausedef_t *clause;
-
- for (clauseset = type->of; *clauseset != NULL; clauseset++) {
- for (clause = *clauseset;
- clause->name != NULL;
- clause++) {
- print_cstr(pctx, clause->name);
- print(pctx, " ", 1);
- print_grammar(pctx, clause->type);
- print(pctx, ";", 1);
- /* XXX print flags here? */
- print(pctx, "\n\n", 2);
- }
- }
- } else if (type->print == print_map) {
- const cfg_clausedef_t * const *clauseset;
- const cfg_clausedef_t *clause;
-
- if (type->parse == parse_named_map) {
- print_grammar(pctx, &cfg_type_astring);
- print(pctx, " ", 1);
- }
-
- print_open(pctx);
-
- for (clauseset = type->of; *clauseset != NULL; clauseset++) {
- for (clause = *clauseset;
- clause->name != NULL;
- clause++) {
- print_indent(pctx);
- print_cstr(pctx, clause->name);
- if (clause->type->print != print_void)
- print(pctx, " ", 1);
- print_grammar(pctx, clause->type);
- print(pctx, ";", 1);
- print_clause_flags(pctx, clause->flags);
- print(pctx, "\n", 1);
- }
- }
- print_close(pctx);
- } else if (type->print == print_tuple) {
- const cfg_tuplefielddef_t *fields = type->of;
- const cfg_tuplefielddef_t *f;
- isc_boolean_t need_space = ISC_FALSE;
-
- for (f = fields; f->name != NULL; f++) {
- if (need_space)
- print(pctx, " ", 1);
- print_grammar(pctx, f->type);
- need_space = ISC_TF(f->type->print != print_void);
- }
- } else if (type->parse == parse_enum) {
- const char * const *p;
- print(pctx, "( ", 2);
- for (p = type->of; *p != NULL; p++) {
- print_cstr(pctx, *p);
- if (p[1] != NULL)
- print(pctx, " | ", 3);
- }
- print(pctx, " )", 2);
- } else if (type->print == print_bracketed_list) {
- print(pctx, "{ ", 2);
- print_grammar(pctx, type->of);
- print(pctx, "; ... }", 7);
- } else if (type->parse == parse_keyvalue) {
- const keyword_type_t *kw = type->of;
- print_cstr(pctx, kw->name);
- print(pctx, " ", 1);
- print_grammar(pctx, kw->type);
- } else if (type->parse == parse_optional_keyvalue) {
- const keyword_type_t *kw = type->of;
- print(pctx, "[ ", 2);
- print_cstr(pctx, kw->name);
- print(pctx, " ", 1);
- print_grammar(pctx, kw->type);
- print(pctx, " ]", 2);
- } else if (type->parse == parse_sockaddr) {
- const unsigned int *flagp = type->of;
- int n = 0;
- print(pctx, "( ", 2);
- if (*flagp & V4OK) {
- if (n != 0)
- print(pctx, " | ", 3);
- print_cstr(pctx, "<ipv4_address>");
- n++;
- }
- if (*flagp & V6OK) {
- if (n != 0)
- print(pctx, " | ", 3);
- print_cstr(pctx, "<ipv6_address>");
- n++;
- }
- if (*flagp & WILDOK) {
- if (n != 0)
- print(pctx, " | ", 3);
- print(pctx, "*", 1);
- n++;
- }
- print(pctx, " ) ", 3);
- if (*flagp & WILDOK) {
- print_cstr(pctx, "[ port ( <integer> | * ) ]");
- } else {
- print_cstr(pctx, "[ port <integer> ]");
- }
- } else if (type->print == print_void) {
- /* Print nothing. */
- } else {
- print(pctx, "<", 1);
- print_cstr(pctx, type->name);
- print(pctx, ">", 1);
- }
+void
+cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_chars(pctx, "<", 1);
+ cfg_print_cstr(pctx, type->name);
+ cfg_print_chars(pctx, ">", 1);
}
void
@@ -3968,5 +2285,5 @@ cfg_print_grammar(const cfg_type_t *type,
pctx.f = f;
pctx.closure = closure;
pctx.indent = 0;
- print_grammar(&pctx, type);
+ cfg_doc_obj(&pctx, type);
}