mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
the values of the notify and dialup options may now be of either boolean or
string types; added cfg_obj_is*() functions for determining the type of a configuration object; reordered some functions in parser.c
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: cfg.h,v 1.11 2001/02/22 23:59:28 bwelling Exp $ */
|
/* $Id: cfg.h,v 1.12 2001/02/23 00:15:55 gson Exp $ */
|
||||||
|
|
||||||
#ifndef DNS_CFG_H
|
#ifndef DNS_CFG_H
|
||||||
#define DNS_CFG_H 1
|
#define DNS_CFG_H 1
|
||||||
@@ -138,6 +138,19 @@ cfg_parser_destroy(cfg_parser_t **pctxp);
|
|||||||
* Destroy a configuration parser.
|
* Destroy a configuration parser.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isvoid(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of void type (e.g., an optional
|
||||||
|
* value not specified).
|
||||||
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_ismap(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of a map type.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
cfg_map_get(cfg_obj_t *mapobj, const char* name, cfg_obj_t **obj);
|
cfg_map_get(cfg_obj_t *mapobj, const char* name, cfg_obj_t **obj);
|
||||||
/*
|
/*
|
||||||
@@ -167,6 +180,12 @@ cfg_map_getname(cfg_obj_t *mapobj);
|
|||||||
* or NULL if the map object does not have a name.
|
* or NULL if the map object does not have a name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_istuple(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of a map type.
|
||||||
|
*/
|
||||||
|
|
||||||
cfg_obj_t *
|
cfg_obj_t *
|
||||||
cfg_tuple_get(cfg_obj_t *tupleobj, const char* name);
|
cfg_tuple_get(cfg_obj_t *tupleobj, const char* name);
|
||||||
/*
|
/*
|
||||||
@@ -179,6 +198,12 @@ cfg_tuple_get(cfg_obj_t *tupleobj, const char* name);
|
|||||||
* fields of said tuple type.
|
* fields of said tuple type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isuint32(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of integer type.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_uint32_t
|
isc_uint32_t
|
||||||
cfg_obj_asuint32(cfg_obj_t *obj);
|
cfg_obj_asuint32(cfg_obj_t *obj);
|
||||||
/*
|
/*
|
||||||
@@ -191,6 +216,12 @@ cfg_obj_asuint32(cfg_obj_t *obj);
|
|||||||
* A 32-bit unsigned integer.
|
* A 32-bit unsigned integer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isstring(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of string type.
|
||||||
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
cfg_obj_asstring(cfg_obj_t *obj);
|
cfg_obj_asstring(cfg_obj_t *obj);
|
||||||
/*
|
/*
|
||||||
@@ -204,6 +235,12 @@ cfg_obj_asstring(cfg_obj_t *obj);
|
|||||||
* A pointer to a null terminated string.
|
* A pointer to a null terminated string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isboolean(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of a boolean type.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
cfg_obj_asboolean(cfg_obj_t *obj);
|
cfg_obj_asboolean(cfg_obj_t *obj);
|
||||||
/*
|
/*
|
||||||
@@ -216,6 +253,12 @@ cfg_obj_asboolean(cfg_obj_t *obj);
|
|||||||
* A boolean value.
|
* A boolean value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_issockaddr(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of sockaddr type.
|
||||||
|
*/
|
||||||
|
|
||||||
isc_sockaddr_t *
|
isc_sockaddr_t *
|
||||||
cfg_obj_assockaddr(cfg_obj_t *obj);
|
cfg_obj_assockaddr(cfg_obj_t *obj);
|
||||||
/*
|
/*
|
||||||
@@ -229,6 +272,12 @@ cfg_obj_assockaddr(cfg_obj_t *obj);
|
|||||||
* if necessary.
|
* if necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_islist(cfg_obj_t *obj);
|
||||||
|
/*
|
||||||
|
* Return true iff 'obj' is of list type.
|
||||||
|
*/
|
||||||
|
|
||||||
cfg_listelt_t *
|
cfg_listelt_t *
|
||||||
cfg_list_first(cfg_obj_t *obj);
|
cfg_list_first(cfg_obj_t *obj);
|
||||||
/*
|
/*
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: parser.c,v 1.19 2001/02/22 23:59:27 bwelling Exp $ */
|
/* $Id: parser.c,v 1.20 2001/02/23 00:15:53 gson Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -387,6 +387,7 @@ cfg_rep_t cfg_rep_void = { "void", free_noop };
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static cfg_type_t cfg_type_boolean;
|
static cfg_type_t cfg_type_boolean;
|
||||||
|
static cfg_type_t cfg_type_boolean_or_ustring;
|
||||||
static cfg_type_t cfg_type_uint32;
|
static cfg_type_t cfg_type_uint32;
|
||||||
static cfg_type_t cfg_type_qstring;
|
static cfg_type_t cfg_type_qstring;
|
||||||
static cfg_type_t cfg_type_astring;
|
static cfg_type_t cfg_type_astring;
|
||||||
@@ -429,7 +430,7 @@ static cfg_type_t cfg_type_server_key_kludge;
|
|||||||
static cfg_type_t cfg_type_optional_facility;
|
static cfg_type_t cfg_type_optional_facility;
|
||||||
static cfg_type_t cfg_type_logseverity;
|
static cfg_type_t cfg_type_logseverity;
|
||||||
static cfg_type_t cfg_type_lwres;
|
static cfg_type_t cfg_type_lwres;
|
||||||
|
static cfg_type_t cfg_type_boolean_or_ustring;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configuration type definitions.
|
* Configuration type definitions.
|
||||||
@@ -837,9 +838,9 @@ static cfg_clausedef_t
|
|||||||
zone_clauses[] = {
|
zone_clauses[] = {
|
||||||
{ "allow-query", &cfg_type_bracketed_aml, 0 },
|
{ "allow-query", &cfg_type_bracketed_aml, 0 },
|
||||||
{ "allow-transfer", &cfg_type_bracketed_aml, 0 },
|
{ "allow-transfer", &cfg_type_bracketed_aml, 0 },
|
||||||
{ "notify", &cfg_type_ustring, 0 },
|
{ "notify", &cfg_type_boolean_or_ustring, 0 },
|
||||||
{ "also-notify", &cfg_type_portiplist, 0 },
|
{ "also-notify", &cfg_type_portiplist, 0 },
|
||||||
{ "dialup", &cfg_type_ustring, 0 },
|
{ "dialup", &cfg_type_boolean_or_ustring, 0 },
|
||||||
{ "forward", &cfg_type_ustring, 0 },
|
{ "forward", &cfg_type_ustring, 0 },
|
||||||
{ "forwarders", &cfg_type_portiplist, 0 },
|
{ "forwarders", &cfg_type_portiplist, 0 },
|
||||||
{ "maintain-ixfr-base", &cfg_type_boolean, 0 },
|
{ "maintain-ixfr-base", &cfg_type_boolean, 0 },
|
||||||
@@ -1134,6 +1135,12 @@ free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj) {
|
|||||||
nfields * sizeof(cfg_obj_t *));
|
nfields * sizeof(cfg_obj_t *));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_istuple(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_tuple));
|
||||||
|
}
|
||||||
|
|
||||||
cfg_obj_t *
|
cfg_obj_t *
|
||||||
cfg_tuple_get(cfg_obj_t *tupleobj, const char* name) {
|
cfg_tuple_get(cfg_obj_t *tupleobj, const char* name) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -1368,31 +1375,6 @@ cfg_parser_destroy(cfg_parser_t **pctxp) {
|
|||||||
*pctxp = NULL;
|
*pctxp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
cfg_map_get(cfg_obj_t *mapobj, const char* name, cfg_obj_t **obj) {
|
|
||||||
isc_result_t result;
|
|
||||||
isc_symvalue_t val;
|
|
||||||
cfg_map_t *map;
|
|
||||||
|
|
||||||
REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
|
|
||||||
REQUIRE(name != NULL);
|
|
||||||
REQUIRE(obj != NULL && *obj == NULL);
|
|
||||||
|
|
||||||
map = &mapobj->value.map;
|
|
||||||
|
|
||||||
result = isc_symtab_lookup(map->symtab, name, MAP_SYM, &val);
|
|
||||||
if (result != ISC_R_SUCCESS)
|
|
||||||
return (result);
|
|
||||||
*obj = val.as_pointer;
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_obj_t *
|
|
||||||
cfg_map_getname(cfg_obj_t *mapobj) {
|
|
||||||
REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
|
|
||||||
return (mapobj->value.map.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void
|
* void
|
||||||
*/
|
*/
|
||||||
@@ -1407,6 +1389,13 @@ print_void(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
UNUSED(pctx);
|
UNUSED(pctx);
|
||||||
UNUSED(obj);
|
UNUSED(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = {
|
static cfg_type_t cfg_type_void = {
|
||||||
"void", parse_void, print_void, &cfg_rep_void, NULL };
|
"void", parse_void, print_void, &cfg_rep_void, NULL };
|
||||||
|
|
||||||
@@ -1451,6 +1440,12 @@ print_uint32(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
print_uint(pctx, obj->value.uint32);
|
print_uint(pctx, obj->value.uint32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isuint32(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_uint32));
|
||||||
|
}
|
||||||
|
|
||||||
isc_uint32_t
|
isc_uint32_t
|
||||||
cfg_obj_asuint32(cfg_obj_t *obj) {
|
cfg_obj_asuint32(cfg_obj_t *obj) {
|
||||||
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint32);
|
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint32);
|
||||||
@@ -1592,24 +1587,30 @@ free_string(cfg_parser_t *pctx, cfg_obj_t *obj) {
|
|||||||
obj->value.string.length + 1);
|
obj->value.string.length + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isstring(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_string));
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
cfg_obj_asstring(cfg_obj_t *obj) {
|
cfg_obj_asstring(cfg_obj_t *obj) {
|
||||||
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_string);
|
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_string);
|
||||||
return (obj->value.string.base);
|
return (obj->value.string.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_isboolean(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_boolean));
|
||||||
|
}
|
||||||
|
|
||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
cfg_obj_asboolean(cfg_obj_t *obj) {
|
cfg_obj_asboolean(cfg_obj_t *obj) {
|
||||||
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_boolean);
|
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_boolean);
|
||||||
return (obj->value.boolean);
|
return (obj->value.boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_sockaddr_t *
|
|
||||||
cfg_obj_assockaddr(cfg_obj_t *obj) {
|
|
||||||
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
|
|
||||||
return (&obj->value.sockaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Quoted string only */
|
/* Quoted string only */
|
||||||
static cfg_type_t cfg_type_qstring = {
|
static cfg_type_t cfg_type_qstring = {
|
||||||
"qstring", parse_qstring, print_qstring, &cfg_rep_string, NULL };
|
"qstring", parse_qstring, print_qstring, &cfg_rep_string, NULL };
|
||||||
@@ -1634,7 +1635,9 @@ static cfg_type_t cfg_type_size = {
|
|||||||
* boolean
|
* boolean
|
||||||
*/
|
*/
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
parse_boolean(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
parse_boolean_like(cfg_parser_t *pctx, cfg_type_t *type,
|
||||||
|
cfg_obj_t **ret, isc_boolean_t accept_string)
|
||||||
|
{
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
isc_boolean_t value;
|
isc_boolean_t value;
|
||||||
cfg_obj_t *obj = NULL;
|
cfg_obj_t *obj = NULL;
|
||||||
@@ -1645,7 +1648,7 @@ parse_boolean(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
|||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
if (pctx->token.type != isc_tokentype_string)
|
if (pctx->token.type != isc_tokentype_string)
|
||||||
goto bad_boolean;
|
goto no_string;
|
||||||
|
|
||||||
if ((strcasecmp(pctx->token.value.as_pointer, "true") == 0) ||
|
if ((strcasecmp(pctx->token.value.as_pointer, "true") == 0) ||
|
||||||
(strcasecmp(pctx->token.value.as_pointer, "yes") == 0) ||
|
(strcasecmp(pctx->token.value.as_pointer, "yes") == 0) ||
|
||||||
@@ -1665,6 +1668,12 @@ parse_boolean(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
|||||||
return (result);
|
return (result);
|
||||||
|
|
||||||
bad_boolean:
|
bad_boolean:
|
||||||
|
if (accept_string)
|
||||||
|
return (create_string(pctx,
|
||||||
|
pctx->token.value.as_pointer,
|
||||||
|
&cfg_type_ustring,
|
||||||
|
ret));
|
||||||
|
no_string:
|
||||||
parser_error(pctx, LOG_NEAR, "boolean expected");
|
parser_error(pctx, LOG_NEAR, "boolean expected");
|
||||||
return (ISC_R_UNEXPECTEDTOKEN);
|
return (ISC_R_UNEXPECTEDTOKEN);
|
||||||
|
|
||||||
@@ -1672,6 +1681,18 @@ parse_boolean(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
parse_boolean(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
||||||
|
return (parse_boolean_like(pctx, type, ret, ISC_FALSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
parse_boolean_or_ustring(cfg_parser_t *pctx, cfg_type_t *type,
|
||||||
|
cfg_obj_t **ret)
|
||||||
|
{
|
||||||
|
return (parse_boolean_like(pctx, type, ret, ISC_TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
print_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
||||||
if (obj->value.boolean)
|
if (obj->value.boolean)
|
||||||
@@ -1683,9 +1704,14 @@ print_boolean(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
static cfg_type_t cfg_type_boolean = {
|
static cfg_type_t cfg_type_boolean = {
|
||||||
"boolean", parse_boolean, print_boolean, &cfg_rep_boolean, NULL };
|
"boolean", parse_boolean, print_boolean, &cfg_rep_boolean, NULL };
|
||||||
|
|
||||||
|
static cfg_type_t cfg_type_boolean_or_ustring = {
|
||||||
|
"boolean_or_string", parse_boolean_or_ustring, NULL, NULL, NULL };
|
||||||
|
|
||||||
static keyword_type_t key_kw = { "key", &cfg_type_astring };
|
static keyword_type_t key_kw = { "key", &cfg_type_astring };
|
||||||
static cfg_type_t cfg_type_optional_keyref = {
|
static cfg_type_t cfg_type_optional_keyref = {
|
||||||
"optional_keyref", parse_optional_keyvalue, print_optional_keyvalue, &cfg_rep_string, &key_kw };
|
"optional_keyref", parse_optional_keyvalue, print_optional_keyvalue,
|
||||||
|
&cfg_rep_string, &key_kw
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1859,6 +1885,12 @@ print_spacelist(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_islist(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_list));
|
||||||
|
}
|
||||||
|
|
||||||
cfg_listelt_t *
|
cfg_listelt_t *
|
||||||
cfg_list_first(cfg_obj_t *obj) {
|
cfg_list_first(cfg_obj_t *obj) {
|
||||||
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_list);
|
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_list);
|
||||||
@@ -1881,6 +1913,240 @@ cfg_listelt_value(cfg_listelt_t *elt) {
|
|||||||
* Maps.
|
* Maps.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a map body. That's something like
|
||||||
|
*
|
||||||
|
* "foo 1; bar { glub; }; zap true; zap false;"
|
||||||
|
*
|
||||||
|
* i.e., a sequence of option names followed by values and
|
||||||
|
* terminated by semicolons. Used for the top level of
|
||||||
|
* 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, cfg_type_t *type, cfg_obj_t **ret)
|
||||||
|
{
|
||||||
|
cfg_clausedef_t **clausesets = type->of;
|
||||||
|
isc_result_t result;
|
||||||
|
cfg_clausedef_t **clauseset;
|
||||||
|
cfg_clausedef_t *clause;
|
||||||
|
cfg_obj_t *value = NULL;
|
||||||
|
cfg_obj_t *obj = NULL;
|
||||||
|
cfg_obj_t *eltobj = NULL;
|
||||||
|
cfg_obj_t *includename = NULL;
|
||||||
|
isc_symvalue_t symval;
|
||||||
|
cfg_list_t *list = NULL;
|
||||||
|
|
||||||
|
CHECK(create_map(pctx, type, &obj));
|
||||||
|
|
||||||
|
obj->value.map.clausesets = clausesets;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
cfg_listelt_t *elt;
|
||||||
|
|
||||||
|
redo:
|
||||||
|
/*
|
||||||
|
* Parse the option name and see if it is known.
|
||||||
|
*/
|
||||||
|
CHECK(cfg_gettoken(pctx, 0));
|
||||||
|
|
||||||
|
if (pctx->token.type != isc_tokentype_string) {
|
||||||
|
cfg_ungettoken(pctx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We accept "include" statements wherever a map body
|
||||||
|
* clause can occur.
|
||||||
|
*/
|
||||||
|
if (strcasecmp(pctx->token.value.as_pointer, "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(parse_semicolon(pctx));
|
||||||
|
CHECK(parser_openfile(pctx, includename->
|
||||||
|
value.string.base));
|
||||||
|
cfg_obj_destroy(pctx, &includename);
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
|
|
||||||
|
clause = NULL;
|
||||||
|
for (clauseset = clausesets; *clauseset != NULL; clauseset++) {
|
||||||
|
for (clause = *clauseset;
|
||||||
|
clause->name != NULL;
|
||||||
|
clause++) {
|
||||||
|
if (strcasecmp(pctx->token.value.as_pointer,
|
||||||
|
clause->name) == 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done:
|
||||||
|
if (clause == NULL || clause->name == NULL) {
|
||||||
|
parser_error(pctx, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clause is known. */
|
||||||
|
|
||||||
|
/* Issue warnings if appropriate */
|
||||||
|
if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)
|
||||||
|
parser_warning(pctx, 0, "option '%s' is obsolete",
|
||||||
|
clause->name);
|
||||||
|
if ((clause->flags & CFG_CLAUSEFLAG_NOTIMP) != 0)
|
||||||
|
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 "
|
||||||
|
"not yet implemented", clause->name);
|
||||||
|
/*
|
||||||
|
* Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
|
||||||
|
* set here - we need to log the *lack* of such an option,
|
||||||
|
* not its presence.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* See if the clause already has a value; if not create one. */
|
||||||
|
result = isc_symtab_lookup(obj->value.map.symtab,
|
||||||
|
clause->name, 0, &symval);
|
||||||
|
|
||||||
|
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
|
||||||
|
/* Multivalued clause */
|
||||||
|
cfg_obj_t *listobj = NULL;
|
||||||
|
if (result == ISC_R_NOTFOUND) {
|
||||||
|
CHECK(create_list(pctx,
|
||||||
|
&cfg_type_implicitlist,
|
||||||
|
&listobj));
|
||||||
|
symval.as_pointer = listobj;
|
||||||
|
result = isc_symtab_define(obj->value.
|
||||||
|
map.symtab,
|
||||||
|
clause->name,
|
||||||
|
1, symval,
|
||||||
|
isc_symexists_reject);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
isc_mem_put(pctx->mctx, list,
|
||||||
|
sizeof(cfg_list_t));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (result == ISC_R_SUCCESS) {
|
||||||
|
listobj = symval.as_pointer;
|
||||||
|
} else {
|
||||||
|
parser_error(pctx, LOG_NEAR,
|
||||||
|
"isc_symtab_define() failed",
|
||||||
|
clause->name);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
elt = NULL;
|
||||||
|
CHECK(parse_list_elt(pctx, clause->type, &elt));
|
||||||
|
CHECK(parse_semicolon(pctx));
|
||||||
|
|
||||||
|
ISC_LIST_APPEND(listobj->value.list, elt, link);
|
||||||
|
} else {
|
||||||
|
/* Single-valued clause */
|
||||||
|
if (result == ISC_R_NOTFOUND) {
|
||||||
|
isc_boolean_t callback =
|
||||||
|
ISC_TF((clause->flags &
|
||||||
|
CFG_CLAUSEFLAG_CALLBACK) != 0);
|
||||||
|
CHECK(parse_symtab_elt(pctx, clause->name,
|
||||||
|
clause->type,
|
||||||
|
obj->value.map.symtab,
|
||||||
|
callback));
|
||||||
|
CHECK(parse_semicolon(pctx));
|
||||||
|
} else if (result == ISC_R_SUCCESS) {
|
||||||
|
parser_error(pctx, LOG_NEAR, "'%s' redefined",
|
||||||
|
clause->name);
|
||||||
|
goto cleanup;
|
||||||
|
} else {
|
||||||
|
parser_error(pctx, LOG_NEAR,
|
||||||
|
"isc_symtab_define() failed");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
*ret = obj;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
CLEANUP_OBJ(value);
|
||||||
|
CLEANUP_OBJ(obj);
|
||||||
|
CLEANUP_OBJ(eltobj);
|
||||||
|
CLEANUP_OBJ(includename);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isc_result_t
|
||||||
|
parse_symtab_elt(cfg_parser_t *pctx, const char *name,
|
||||||
|
cfg_type_t *elttype, isc_symtab_t *symtab,
|
||||||
|
isc_boolean_t callback)
|
||||||
|
{
|
||||||
|
isc_result_t result;
|
||||||
|
cfg_obj_t *obj = NULL;
|
||||||
|
isc_symvalue_t symval;
|
||||||
|
|
||||||
|
CHECK(parse(pctx, elttype, &obj));
|
||||||
|
|
||||||
|
if (callback && pctx->callback != NULL)
|
||||||
|
CHECK(pctx->callback(name, obj, pctx->callbackarg));
|
||||||
|
|
||||||
|
symval.as_pointer = obj;
|
||||||
|
CHECK(isc_symtab_define(symtab, name,
|
||||||
|
1, symval,
|
||||||
|
isc_symexists_reject));
|
||||||
|
obj = NULL;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
CLEANUP_OBJ(obj);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }"
|
||||||
|
*/
|
||||||
|
static isc_result_t
|
||||||
|
parse_map(cfg_parser_t *pctx, 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, '}'));
|
||||||
|
cleanup:
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a named map; e.g., "name { foo 1; }". Used for the "key", "server",
|
||||||
|
* and "channel" statements.
|
||||||
|
*/
|
||||||
|
static isc_result_t
|
||||||
|
parse_named_map(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret)
|
||||||
|
{
|
||||||
|
isc_result_t result;
|
||||||
|
cfg_obj_t *idobj = NULL;
|
||||||
|
cfg_obj_t *mapobj = NULL;
|
||||||
|
|
||||||
|
CHECK(parse_astring(pctx, NULL, &idobj));
|
||||||
|
CHECK(parse_map(pctx, type, &mapobj));
|
||||||
|
mapobj->value.map.id = idobj;
|
||||||
|
idobj = NULL;
|
||||||
|
*ret = mapobj;
|
||||||
|
cleanup:
|
||||||
|
CLEANUP_OBJ(idobj);
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
||||||
isc_result_t result = ISC_R_SUCCESS;
|
isc_result_t result = ISC_R_SUCCESS;
|
||||||
@@ -1944,6 +2210,38 @@ print_map(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
print_close(pctx);
|
print_close(pctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_ismap(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_map));
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_result_t
|
||||||
|
cfg_map_get(cfg_obj_t *mapobj, const char* name, cfg_obj_t **obj) {
|
||||||
|
isc_result_t result;
|
||||||
|
isc_symvalue_t val;
|
||||||
|
cfg_map_t *map;
|
||||||
|
|
||||||
|
REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
|
||||||
|
REQUIRE(name != NULL);
|
||||||
|
REQUIRE(obj != NULL && *obj == NULL);
|
||||||
|
|
||||||
|
map = &mapobj->value.map;
|
||||||
|
|
||||||
|
result = isc_symtab_lookup(map->symtab, name, MAP_SYM, &val);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
return (result);
|
||||||
|
*obj = val.as_pointer;
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_obj_t *
|
||||||
|
cfg_map_getname(cfg_obj_t *mapobj) {
|
||||||
|
REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
|
||||||
|
return (mapobj->value.map.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse an arbitrary token, storing its raw text representation. */
|
/* Parse an arbitrary token, storing its raw text representation. */
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
parse_token(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
parse_token(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret) {
|
||||||
@@ -2529,6 +2827,18 @@ print_sockaddr(cfg_printer_t *pctx, cfg_obj_t *obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isc_boolean_t
|
||||||
|
cfg_obj_issockaddr(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL);
|
||||||
|
return (ISC_TF(obj->type->rep == &cfg_rep_sockaddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_sockaddr_t *
|
||||||
|
cfg_obj_assockaddr(cfg_obj_t *obj) {
|
||||||
|
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
|
||||||
|
return (&obj->value.sockaddr);
|
||||||
|
}
|
||||||
|
|
||||||
/* An IPv4/IPv6 address with optional port, "*" accepted as wildcard. */
|
/* An IPv4/IPv6 address with optional port, "*" accepted as wildcard. */
|
||||||
static cfg_type_t cfg_type_sockaddr4wild = {
|
static cfg_type_t cfg_type_sockaddr4wild = {
|
||||||
"sockaddr4wild", parse_sockaddr4wild, print_sockaddr,
|
"sockaddr4wild", parse_sockaddr4wild, print_sockaddr,
|
||||||
@@ -2726,241 +3036,6 @@ cfg_type_t cfg_type_rndcconf = {
|
|||||||
rndcconf_clausesets
|
rndcconf_clausesets
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a map body. That's something like
|
|
||||||
*
|
|
||||||
* "foo 1; bar { glub; }; zap true; zap false;"
|
|
||||||
*
|
|
||||||
* i.e., a sequence of option names followed by values and
|
|
||||||
* terminated by semicolons. Used for the top level of
|
|
||||||
* 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, cfg_type_t *type, cfg_obj_t **ret)
|
|
||||||
{
|
|
||||||
cfg_clausedef_t **clausesets = type->of;
|
|
||||||
isc_result_t result;
|
|
||||||
cfg_clausedef_t **clauseset;
|
|
||||||
cfg_clausedef_t *clause;
|
|
||||||
cfg_obj_t *value = NULL;
|
|
||||||
cfg_obj_t *obj = NULL;
|
|
||||||
cfg_obj_t *eltobj = NULL;
|
|
||||||
cfg_obj_t *includename = NULL;
|
|
||||||
isc_symvalue_t symval;
|
|
||||||
cfg_list_t *list = NULL;
|
|
||||||
|
|
||||||
CHECK(create_map(pctx, type, &obj));
|
|
||||||
|
|
||||||
obj->value.map.clausesets = clausesets;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
cfg_listelt_t *elt;
|
|
||||||
|
|
||||||
redo:
|
|
||||||
/*
|
|
||||||
* Parse the option name and see if it is known.
|
|
||||||
*/
|
|
||||||
CHECK(cfg_gettoken(pctx, 0));
|
|
||||||
|
|
||||||
if (pctx->token.type != isc_tokentype_string) {
|
|
||||||
cfg_ungettoken(pctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We accept "include" statements wherever a map body
|
|
||||||
* clause can occur.
|
|
||||||
*/
|
|
||||||
if (strcasecmp(pctx->token.value.as_pointer, "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(parse_semicolon(pctx));
|
|
||||||
CHECK(parser_openfile(pctx, includename->
|
|
||||||
value.string.base));
|
|
||||||
cfg_obj_destroy(pctx, &includename);
|
|
||||||
goto redo;
|
|
||||||
}
|
|
||||||
|
|
||||||
clause = NULL;
|
|
||||||
for (clauseset = clausesets; *clauseset != NULL; clauseset++) {
|
|
||||||
for (clause = *clauseset;
|
|
||||||
clause->name != NULL;
|
|
||||||
clause++) {
|
|
||||||
if (strcasecmp(pctx->token.value.as_pointer,
|
|
||||||
clause->name) == 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
if (clause == NULL || clause->name == NULL) {
|
|
||||||
parser_error(pctx, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clause is known. */
|
|
||||||
|
|
||||||
/* Issue warnings if appropriate */
|
|
||||||
if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)
|
|
||||||
parser_warning(pctx, 0, "option '%s' is obsolete",
|
|
||||||
clause->name);
|
|
||||||
if ((clause->flags & CFG_CLAUSEFLAG_NOTIMP) != 0)
|
|
||||||
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 "
|
|
||||||
"not yet implemented", clause->name);
|
|
||||||
/*
|
|
||||||
* Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
|
|
||||||
* set here - we need to log the *lack* of such an option,
|
|
||||||
* not its presence.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* See if the clause already has a value; if not create one. */
|
|
||||||
result = isc_symtab_lookup(obj->value.map.symtab,
|
|
||||||
clause->name, 0, &symval);
|
|
||||||
|
|
||||||
if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
|
|
||||||
/* Multivalued clause */
|
|
||||||
cfg_obj_t *listobj = NULL;
|
|
||||||
if (result == ISC_R_NOTFOUND) {
|
|
||||||
CHECK(create_list(pctx,
|
|
||||||
&cfg_type_implicitlist,
|
|
||||||
&listobj));
|
|
||||||
symval.as_pointer = listobj;
|
|
||||||
result = isc_symtab_define(obj->value.
|
|
||||||
map.symtab,
|
|
||||||
clause->name,
|
|
||||||
1, symval,
|
|
||||||
isc_symexists_reject);
|
|
||||||
if (result != ISC_R_SUCCESS) {
|
|
||||||
isc_mem_put(pctx->mctx, list,
|
|
||||||
sizeof(cfg_list_t));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else if (result == ISC_R_SUCCESS) {
|
|
||||||
listobj = symval.as_pointer;
|
|
||||||
} else {
|
|
||||||
parser_error(pctx, LOG_NEAR,
|
|
||||||
"isc_symtab_define() failed",
|
|
||||||
clause->name);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
elt = NULL;
|
|
||||||
CHECK(parse_list_elt(pctx, clause->type, &elt));
|
|
||||||
CHECK(parse_semicolon(pctx));
|
|
||||||
|
|
||||||
ISC_LIST_APPEND(listobj->value.list, elt, link);
|
|
||||||
} else {
|
|
||||||
/* Single-valued clause */
|
|
||||||
if (result == ISC_R_NOTFOUND) {
|
|
||||||
isc_boolean_t callback =
|
|
||||||
ISC_TF((clause->flags &
|
|
||||||
CFG_CLAUSEFLAG_CALLBACK) != 0);
|
|
||||||
CHECK(parse_symtab_elt(pctx, clause->name,
|
|
||||||
clause->type,
|
|
||||||
obj->value.map.symtab,
|
|
||||||
callback));
|
|
||||||
CHECK(parse_semicolon(pctx));
|
|
||||||
} else if (result == ISC_R_SUCCESS) {
|
|
||||||
parser_error(pctx, LOG_NEAR, "'%s' redefined",
|
|
||||||
clause->name);
|
|
||||||
goto cleanup;
|
|
||||||
} else {
|
|
||||||
parser_error(pctx, LOG_NEAR,
|
|
||||||
"isc_symtab_define() failed");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*ret = obj;
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
CLEANUP_OBJ(value);
|
|
||||||
CLEANUP_OBJ(obj);
|
|
||||||
CLEANUP_OBJ(eltobj);
|
|
||||||
CLEANUP_OBJ(includename);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isc_result_t
|
|
||||||
parse_symtab_elt(cfg_parser_t *pctx, const char *name,
|
|
||||||
cfg_type_t *elttype, isc_symtab_t *symtab,
|
|
||||||
isc_boolean_t callback)
|
|
||||||
{
|
|
||||||
isc_result_t result;
|
|
||||||
cfg_obj_t *obj = NULL;
|
|
||||||
isc_symvalue_t symval;
|
|
||||||
|
|
||||||
CHECK(parse(pctx, elttype, &obj));
|
|
||||||
|
|
||||||
if (callback && pctx->callback != NULL)
|
|
||||||
CHECK(pctx->callback(name, obj, pctx->callbackarg));
|
|
||||||
|
|
||||||
symval.as_pointer = obj;
|
|
||||||
CHECK(isc_symtab_define(symtab, name,
|
|
||||||
1, symval,
|
|
||||||
isc_symexists_reject));
|
|
||||||
obj = NULL;
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
CLEANUP_OBJ(obj);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }"
|
|
||||||
*/
|
|
||||||
static isc_result_t
|
|
||||||
parse_map(cfg_parser_t *pctx, 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, '}'));
|
|
||||||
cleanup:
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a named map; e.g., "name { foo 1; }". Used for the "key", "server",
|
|
||||||
* and "channel" statements.
|
|
||||||
*/
|
|
||||||
static isc_result_t
|
|
||||||
parse_named_map(cfg_parser_t *pctx, cfg_type_t *type, cfg_obj_t **ret)
|
|
||||||
{
|
|
||||||
isc_result_t result;
|
|
||||||
cfg_obj_t *idobj = NULL;
|
|
||||||
cfg_obj_t *mapobj = NULL;
|
|
||||||
|
|
||||||
CHECK(parse_astring(pctx, NULL, &idobj));
|
|
||||||
CHECK(parse_map(pctx, type, &mapobj));
|
|
||||||
mapobj->value.map.id = idobj;
|
|
||||||
idobj = NULL;
|
|
||||||
*ret = mapobj;
|
|
||||||
cleanup:
|
|
||||||
CLEANUP_OBJ(idobj);
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
cfg_gettoken(cfg_parser_t *pctx, int options) {
|
cfg_gettoken(cfg_parser_t *pctx, int options) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
Reference in New Issue
Block a user