#include <isccfg/cfg.h>
#include <isccfg/grammar.h>
+/*
+ * cfg_obj_t is used _a lot_ when building the configuration tree, which
+ * can take a significant amount of memory. This assert ensures that we
+ * won't increase its size by mistake without getting a warning.
+ */
+static_assert(sizeof(struct cfg_obj) <= 48,
+ "sizeof(cfg_obj_t) must be 48 bytes");
+
/* Shorthand */
#define CAT CFG_LOGCATEGORY_CONFIG
#define MOD CFG_LOGMODULE_PARSER
#define SYMTAB_DUMMY_TYPE 1
#define TOKEN_STRING(pctx) (pctx->token.value.as_textregion.base)
-#define TOKEN_REGION(pctx) (pctx->token.value.as_textregion)
/* cfg_obj_t magic number */
#define CFGOBJ_MAGIC ISC_MAGIC('c', 'f', 'g', 'o')
static void
copy_sockaddrtls(cfg_obj_t *to, const cfg_obj_t *from) {
- to->value.sockaddrtls.sockaddr = isc_mem_get(isc_g_mctx,
- sizeof(isc_sockaddr_t));
- memmove(to->value.sockaddrtls.sockaddr,
- from->value.sockaddrtls.sockaddr, sizeof(isc_sockaddr_t));
-
- if (from->value.sockaddrtls.tls.base != NULL) {
- size_t len = from->value.sockaddrtls.tls.length;
-
- to->value.sockaddrtls.tls.base = isc_mem_get(isc_g_mctx,
- len + 1);
- to->value.sockaddrtls.tls.length = len;
- memmove(to->value.sockaddrtls.tls.base,
- from->value.sockaddrtls.tls.base, len + 1);
+ to->value.sockaddrtls = isc_mem_cget(isc_g_mctx, 1,
+ sizeof(*to->value.sockaddrtls));
+ to->value.sockaddrtls->sockaddr = from->value.sockaddrtls->sockaddr;
+ if (from->value.sockaddrtls->tls != NULL) {
+ to->value.sockaddrtls->tls = isc_mem_strdup(
+ isc_g_mctx, from->value.sockaddrtls->tls);
}
}
static void
copy_string(cfg_obj_t *to, const cfg_obj_t *from) {
- to->value.string.length = from->value.string.length;
- to->value.string.base = isc_mem_get(isc_g_mctx,
- to->value.string.length + 1);
- memmove(to->value.string.base, from->value.string.base,
- to->value.string.length + 1);
+ to->value.string = isc_mem_strdup(isc_g_mctx, from->value.string);
}
static void
cfg_obj_clone(value.as_pointer, &toelt);
value.as_pointer = toelt;
- INSIST(isc_symtab_define(to->value.map.symtab, key, type, value,
+ INSIST(isc_symtab_define(to->value.map->symtab, key, type, value,
isc_symexists_reject) == ISC_R_SUCCESS);
/*
static void
copy_map(cfg_obj_t *to, const cfg_obj_t *from) {
- if (from->value.map.id != NULL) {
- cfg_obj_clone(from->value.map.id, &to->value.map.id);
+ to->value.map = isc_mem_cget(isc_g_mctx, 1, sizeof(*to->value.map));
+
+ if (from->value.map->id != NULL) {
+ cfg_obj_clone(from->value.map->id, &to->value.map->id);
}
+
isc_symtab_create(isc_g_mctx, copy_map_destroy, NULL, false,
- &to->value.map.symtab);
- isc_symtab_foreach(from->value.map.symtab, copy_map_add, to);
+ &to->value.map->symtab);
+ isc_symtab_foreach(from->value.map->symtab, copy_map_add, to);
/*
* clausesets are statically defined
*/
- to->value.map.clausesets = from->value.map.clausesets;
+ to->value.map->clausesets = from->value.map->clausesets;
}
static void
copy_list(cfg_obj_t *to, const cfg_obj_t *from) {
const cfg_listelt_t *fromelt = cfg_list_first(from);
- ISC_LIST_INIT(to->value.list);
+ to->value.list = isc_mem_get(isc_g_mctx, sizeof(*to->value.list));
+ ISC_LIST_INIT(*to->value.list);
while (fromelt != NULL) {
cfg_listelt_t *toelt = isc_mem_get(isc_g_mctx, sizeof(*toelt));
*toelt = (cfg_listelt_t){ .link = ISC_LINK_INITIALIZER };
cfg_obj_clone(fromelt->obj, &toelt->obj);
- ISC_LIST_APPEND(to->value.list, toelt, link);
+ ISC_LIST_APPEND(*to->value.list, toelt, link);
fromelt = cfg_list_next(fromelt);
}
return NULL;
}
- elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+ elt = ISC_LIST_TAIL(*pctx->open_files->value.list);
if (elt == NULL) {
return NULL;
}
cfg_string_create(pctx, filename, &cfg_type_qstring, &stringobj);
cfg_listelt_create(&elt);
elt->obj = stringobj;
- ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);
+ ISC_LIST_APPEND(*pctx->open_files->value.list, elt, link);
return ISC_R_SUCCESS;
cleanup:
result = parse2(pctx, type, ret);
/* Clean up the opened file */
- elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+ elt = ISC_LIST_TAIL(*pctx->open_files->value.list);
INSIST(elt != NULL);
- ISC_LIST_UNLINK(pctx->open_files->value.list, elt, link);
- ISC_LIST_APPEND(pctx->closed_files->value.list, elt, link);
+ ISC_LIST_UNLINK(*pctx->open_files->value.list, elt, link);
+ ISC_LIST_APPEND(*pctx->closed_files->value.list, elt, link);
cleanup:
parser_destroy(&pctx);
cfg_string_create(cfg_parser_t *pctx, const char *contents,
const cfg_type_t *type, cfg_obj_t **ret) {
cfg_obj_t *obj = NULL;
- int len;
cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
- len = strlen(contents);
- obj->value.string.length = len;
- obj->value.string.base = isc_mem_get(isc_g_mctx, len + 1);
- memmove(obj->value.string.base, contents, len);
- obj->value.string.base[len] = '\0';
-
+ obj->value.string = isc_mem_strdup(isc_g_mctx, contents);
*ret = obj;
}
*/
pctx->indent++;
cfg_print_cstr(pctx, "{");
- cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+ cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
print_close(pctx);
}
REQUIRE(VALID_CFGOBJ(obj));
- s = obj->value.string.base;
+ s = obj->value.string;
if (cfg_is_enum(s, enums)) {
return ISC_R_SUCCESS;
}
REQUIRE(pctx != NULL);
REQUIRE(VALID_CFGOBJ(obj));
- cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+ cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
}
static void
-print_rawqstring(cfg_printer_t *pctx, const isc_textregion_t string) {
+print_rawqstring(cfg_printer_t *pctx, const char *string) {
cfg_print_cstr(pctx, "\"");
- for (size_t i = 0; i < string.length; i++) {
- if (string.base[i] == '"') {
+ for (size_t i = 0; i < strlen(string); i++) {
+ if (string[i] == '"') {
cfg_print_cstr(pctx, "\\");
}
- cfg_print_chars(pctx, (const char *)&string.base[i], 1);
+ cfg_print_chars(pctx, (const char *)&string[i], 1);
}
cfg_print_cstr(pctx, "\"");
}
REQUIRE(VALID_CFGOBJ(obj));
cfg_print_cstr(pctx, "\"");
if ((pctx->flags & CFG_PRINTER_XKEY) != 0) {
- unsigned int len = obj->value.string.length;
+ size_t len = strlen(obj->value.string);
while (len-- > 0) {
cfg_print_cstr(pctx, "?");
}
static void
free_string(cfg_obj_t *obj) {
- isc_mem_put(isc_g_mctx, obj->value.string.base,
- obj->value.string.length + 1);
+ isc_mem_free(isc_g_mctx, obj->value.string);
}
static void
static void
free_sockaddrtls(cfg_obj_t *obj) {
- isc_mem_put(isc_g_mctx, obj->value.sockaddrtls.sockaddr,
- sizeof(isc_sockaddr_t));
- if (obj->value.sockaddrtls.tls.base != NULL) {
- INSIST(obj->value.sockaddrtls.tls.length != 0);
- isc_mem_put(isc_g_mctx, obj->value.sockaddrtls.tls.base,
- obj->value.sockaddrtls.tls.length + 1);
+ if (obj->value.sockaddrtls->tls != NULL) {
+ isc_mem_free(isc_g_mctx, obj->value.sockaddrtls->tls);
}
+ isc_mem_put(isc_g_mctx, obj->value.sockaddrtls,
+ sizeof(*obj->value.sockaddrtls));
}
bool
cfg_obj_asstring(const cfg_obj_t *obj) {
REQUIRE(VALID_CFGOBJ(obj));
REQUIRE(obj->type->rep == &cfg_rep_string);
- return obj->value.string.base;
+ return obj->value.string;
}
/* Quoted string only */
pctx->indent++;
cfg_print_cstr(pctx, "{");
- cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+ cfg_print_chars(pctx, obj->value.string, strlen(obj->value.string));
print_close(pctx);
}
REQUIRE(obj != NULL && *obj == NULL);
cfg_obj_create(file, line, type, obj);
- ISC_LIST_INIT((*obj)->value.list);
+ (*obj)->value.list = isc_mem_get(isc_g_mctx,
+ sizeof(*(*obj)->value.list));
+ ISC_LIST_INIT(*(*obj)->value.list);
}
void
static void
free_list(cfg_obj_t *obj) {
- ISC_LIST_FOREACH(obj->value.list, elt, link) {
+ ISC_LIST_FOREACH(*obj->value.list, elt, link) {
free_listelt(&elt);
}
+ isc_mem_put(isc_g_mctx, obj->value.list, sizeof(*obj->value.list));
}
isc_result_t
}
CHECK(cfg_parse_listelt(pctx, listobj, listof, &elt));
CHECK(parse_semicolon(pctx));
- ISC_LIST_APPEND(listobj->value.list, elt, link);
+ ISC_LIST_APPEND(*listobj->value.list, elt, link);
elt = NULL;
}
*ret = listobj;
REQUIRE(VALID_CFGOBJ(obj));
- list = UNCONST(&obj->value.list);
+ list = UNCONST(obj->value.list);
ISC_LIST_FOREACH(*list, elt, link) {
if ((pctx->flags & CFG_PRINTER_ONELINE) != 0) {
cfg_print_obj(pctx, elt->obj);
break;
}
CHECK(cfg_parse_listelt(pctx, listobj, listof, &elt));
- ISC_LIST_APPEND(listobj->value.list, elt, link);
+ ISC_LIST_APPEND(*listobj->value.list, elt, link);
}
*ret = listobj;
return ISC_R_SUCCESS;
REQUIRE(pctx != NULL);
REQUIRE(VALID_CFGOBJ(obj));
- list = UNCONST(&obj->value.list);
+ list = UNCONST(obj->value.list);
ISC_LIST_FOREACH(*list, elt, link) {
cfg_print_obj(pctx, elt->obj);
if (obj == NULL) {
return NULL;
}
- return ISC_LIST_HEAD(obj->value.list);
+ return ISC_LIST_HEAD(*obj->value.list);
}
const cfg_listelt_t *
void
cfg_list_unlink(cfg_obj_t *list, cfg_listelt_t *elt) {
REQUIRE(VALID_CFGOBJ(list));
- ISC_LIST_UNLINK(list->value.list, elt, link);
+ ISC_LIST_UNLINK(*list->value.list, elt, link);
free_listelt(&elt);
}
create_map(pctx, type, &obj);
- obj->value.map.clausesets = clausesets;
+ obj->value.map->clausesets = clausesets;
for (;;) {
/*
&includename));
CHECK(parse_semicolon(pctx));
- if (includename->value.string.length == 0) {
+ if (includename->value.string[0] == 0) {
CLEANUP(ISC_R_FILENOTFOUND);
}
&cfg_type_implicitlist, &listobj);
symval.as_pointer = listobj;
result = isc_symtab_define_and_return(
- obj->value.map.symtab, clause->name,
+ obj->value.map->symtab, clause->name,
SYMTAB_DUMMY_TYPE, symval, isc_symexists_reject,
&symval);
if (result == ISC_R_EXISTS) {
CHECK(cfg_parse_listelt(pctx, listobj, clause->type,
&elt));
- ISC_LIST_APPEND(listobj->value.list, elt, link);
+ ISC_LIST_APPEND(*listobj->value.list, elt, link);
CHECK(parse_semicolon(pctx));
} else {
/* Single-valued clause */
result = parse_symtab_elt(pctx, clause,
- obj->value.map.symtab);
+ obj->value.map->symtab);
if (result == ISC_R_EXISTS) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"'%s' redefined",
CHECK(cfg_parse_obj(pctx, nametype, &idobj));
CHECK(cfg_parse_map(pctx, type, &mapobj));
- mapobj->value.map.id = idobj;
+ mapobj->value.map->id = idobj;
*ret = mapobj;
return result;
cleanup:
REQUIRE(pctx != NULL);
REQUIRE(VALID_CFGOBJ(obj));
- for (clauseset = obj->value.map.clausesets; *clauseset != NULL;
+ for (clauseset = obj->value.map->clausesets; *clauseset != NULL;
clauseset++)
{
isc_symvalue_t symval;
continue;
}
- result = isc_symtab_lookup(obj->value.map.symtab,
+ result = isc_symtab_lookup(obj->value.map->symtab,
clause->name,
SYMTAB_DUMMY_TYPE, &symval);
if (result == ISC_R_SUCCESS) {
cfg_obj_t *symobj = symval.as_pointer;
if (symobj->type == &cfg_type_implicitlist) {
/* Multivalued. */
- cfg_list_t *list = &symobj->value.list;
+ cfg_list_t *list = symobj->value.list;
ISC_LIST_FOREACH(*list, elt, link) {
print_symval(pctx, clause->name,
elt->obj);
REQUIRE(pctx != NULL);
REQUIRE(VALID_CFGOBJ(obj));
- if (obj->value.map.id != NULL) {
- cfg_print_obj(pctx, obj->value.map.id);
+ if (obj->value.map->id != NULL) {
+ cfg_print_obj(pctx, obj->value.map->id);
cfg_print_cstr(pctx, " ");
}
print_open(pctx);
REQUIRE(name != NULL);
REQUIRE(obj != NULL && *obj == NULL);
- map = &mapobj->value.map;
+ map = mapobj->value.map;
RETERR(isc_symtab_lookup(map->symtab, name, SYMTAB_DUMMY_TYPE, &val));
*obj = val.as_pointer;
cfg_map_getname(const cfg_obj_t *mapobj) {
REQUIRE(VALID_CFGOBJ(mapobj));
REQUIRE(mapobj->type->rep == &cfg_rep_map);
- return mapobj->value.map.id;
+ return mapobj->value.map->id;
}
unsigned int
REQUIRE(VALID_CFGOBJ(mapobj));
REQUIRE(mapobj->type->rep == &cfg_rep_map);
- map = &mapobj->value.map;
+ map = mapobj->value.map;
return isc_symtab_count(map->symtab);
}
return ((cfg_clausedef_t *)clauses) + idx;
}
+static char *
+region_to_string(isc_region_t region) {
+ size_t len = region.length + 1;
+ char *str = isc_mem_allocate(isc_g_mctx, len);
+
+ memmove(str, region.base, region.length);
+ str[region.length] = 0;
+
+ return str;
+}
+
/* Parse an arbitrary token, storing its raw text representation. */
static isc_result_t
parse_token(cfg_parser_t *pctx, const cfg_type_t *type ISC_ATTR_UNUSED,
}
isc_lex_getlasttokentext(pctx->lexer, &pctx->token, &r);
+ obj->value.string = region_to_string(r);
- obj->value.string.base = isc_mem_get(isc_g_mctx, r.length + 1);
- obj->value.string.length = r.length;
- memmove(obj->value.string.base, r.base, r.length);
- obj->value.string.base[r.length] = '\0';
*ret = obj;
return result;
}
CHECK(cfg_parse_listelt(pctx, listobj, &cfg_type_token, &elt));
- ISC_LIST_APPEND(listobj->value.list, elt, link);
+ ISC_LIST_APPEND(*listobj->value.list, elt, link);
}
INSIST(braces == 0);
*ret = listobj;
print_netprefix, cfg_doc_terminal,
&cfg_rep_netprefix, NULL };
-static void
-copy_textregion(isc_mem_t *mctx, isc_textregion_t *dest, isc_textregion_t src) {
- size_t dest_mem_length = (dest->base != NULL) ? dest->length + 1 : 0;
- dest->base = isc_mem_creget(mctx, dest->base, dest_mem_length,
- src.length + 1, sizeof(char));
- dest->length = src.length;
- memmove(dest->base, src.base, src.length);
- dest->base[dest->length] = '\0';
-}
-
static isc_result_t
parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type, int flags,
cfg_obj_t **ret) {
cfg_obj_t *obj = NULL;
int have_address = 0;
int have_port = 0;
- int have_tls = 0;
int is_port_ok = (flags & CFG_ADDR_PORTOK) != 0;
int is_tls_ok = (flags & CFG_ADDR_TLSOK) != 0;
int is_address_ok = (flags & CFG_ADDR_TRAILINGOK) != 0;
-
- isc_textregion_t tls = { .base = NULL, .length = 0 };
+ char *tls = NULL;
CHECK(cfg_peektoken(pctx, 0));
if (cfg_lookingat_netaddr(pctx, flags)) {
CHECK(cfg_gettoken(pctx, 0)); /* read "tls" */
CHECK(cfg_getstringtoken(pctx));
- isc_textregion_t tok = TOKEN_REGION(pctx);
- copy_textregion(isc_g_mctx, &tls, tok);
+ if (tls != NULL) {
+ cfg_parser_error(
+ pctx, 0,
+ "expected at most one tls");
+ CLEANUP(ISC_R_UNEXPECTEDTOKEN);
+ }
- ++have_tls;
+ tls = region_to_string(
+ pctx->token.value.as_region);
} else {
break;
}
CLEANUP(ISC_R_UNEXPECTEDTOKEN);
}
- if (have_tls > 1) {
- cfg_parser_error(pctx, 0, "expected at most one tls");
- CLEANUP(ISC_R_UNEXPECTEDTOKEN);
- }
-
cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
- if (have_tls == 1) {
- obj->value.sockaddrtls.tls = tls;
+
+ if (is_tls_ok != 0) {
+ obj->value.sockaddrtls = isc_mem_cget(
+ isc_g_mctx, 1, sizeof(*obj->value.sockaddrtls));
+ isc_sockaddr_fromnetaddr(&obj->value.sockaddrtls->sockaddr,
+ &netaddr, port);
+ obj->value.sockaddrtls->tls = tls;
+ tls = NULL;
+ } else {
+ obj->value.sockaddr = isc_mem_get(isc_g_mctx,
+ sizeof(*obj->value.sockaddr));
+ isc_sockaddr_fromnetaddr(obj->value.sockaddr, &netaddr, port);
}
- obj->value.sockaddrtls.sockaddr = isc_mem_get(isc_g_mctx,
- sizeof(isc_sockaddr_t));
- isc_sockaddr_fromnetaddr(obj->value.sockaddrtls.sockaddr, &netaddr,
- port);
+
*ret = obj;
return ISC_R_SUCCESS;
cleanup:
- if (tls.base != NULL) {
- isc_mem_put(isc_g_mctx, tls.base, tls.length + 1);
+ if (tls != NULL) {
+ isc_mem_free(isc_g_mctx, tls);
}
CLEANUP_OBJ(obj);
return result;
isc_netaddr_t netaddr;
in_port_t port;
char buf[ISC_NETADDR_FORMATSIZE];
+ isc_sockaddr_t *sockaddr;
+ bool tls = false;
REQUIRE(pctx != NULL);
REQUIRE(VALID_CFGOBJ(obj));
- isc_netaddr_fromsockaddr(&netaddr, obj->value.sockaddr);
+ if (obj->type == &cfg_type_sockaddrtls) {
+ sockaddr = &obj->value.sockaddrtls->sockaddr;
+ tls = true;
+ } else {
+ sockaddr = obj->value.sockaddr;
+ }
+
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
isc_netaddr_format(&netaddr, buf, sizeof(buf));
cfg_print_cstr(pctx, buf);
- port = isc_sockaddr_getport(obj->value.sockaddr);
+ port = isc_sockaddr_getport(sockaddr);
if (port != 0) {
cfg_print_cstr(pctx, " port ");
cfg_print_rawuint(pctx, port);
}
- if (obj->value.sockaddrtls.tls.base != NULL) {
+ if (tls && obj->value.sockaddrtls->tls != NULL) {
cfg_print_cstr(pctx, " tls ");
- print_rawqstring(pctx, obj->value.sockaddrtls.tls);
+ print_rawqstring(pctx, obj->value.sockaddrtls->tls);
}
}
cfg_obj_getsockaddrtls(const cfg_obj_t *obj) {
REQUIRE(VALID_CFGOBJ(obj));
REQUIRE(obj->type->rep == &cfg_rep_sockaddrtls);
- return obj->value.sockaddrtls.tls.base;
+ return obj->value.sockaddrtls->tls;
}
isc_result_t
*/
cfg_listelt_t *elt;
elt = ISC_LIST_TAIL(
- pctx->open_files->value.list);
+ *pctx->open_files->value.list);
INSIST(elt != NULL);
- ISC_LIST_UNLINK(pctx->open_files->value.list,
+ ISC_LIST_UNLINK(*pctx->open_files->value.list,
elt, link);
- ISC_LIST_APPEND(pctx->closed_files->value.list,
+ ISC_LIST_APPEND(*pctx->closed_files->value.list,
elt, link);
goto redo;
}
cfg_obj_create(cfg_parser_currentfile(pctx), pctx->line, type, &obj);
isc_symtab_create(isc_g_mctx, map_symtabitem_destroy, pctx, false,
&symtab);
- obj->value.map.symtab = symtab;
- obj->value.map.id = NULL;
+
+ obj->value.map = isc_mem_cget(isc_g_mctx, 1, sizeof(*obj->value.map));
+ obj->value.map->symtab = symtab;
*ret = obj;
}
static void
free_map(cfg_obj_t *obj) {
- CLEANUP_OBJ(obj->value.map.id);
- isc_symtab_destroy(&obj->value.map.symtab);
+ CLEANUP_OBJ(obj->value.map->id);
+ isc_symtab_destroy(&obj->value.map->symtab);
+ isc_mem_put(isc_g_mctx, obj->value.map, sizeof(*obj->value.map));
}
bool
const cfg_map_t *map;
isc_symvalue_t symval;
- map = &mapobj->value.map;
+ map = mapobj->value.map;
result = isc_symtab_lookup(map->symtab, clause->name, SYMTAB_DUMMY_TYPE,
&symval);
if (result == ISC_R_NOTFOUND) {
&cfg_type_implicitlist, &destobj);
cfg_listelt_create(&elt);
cfg_obj_attach(obj, &elt->obj);
- ISC_LIST_APPEND(destobj->value.list, elt, link);
+ ISC_LIST_APPEND(*destobj->value.list, elt, link);
symval.as_pointer = destobj;
} else {
symval.as_pointer = obj;
if (destobj->type == &cfg_type_implicitlist) {
cfg_listelt_create(&elt);
cfg_obj_attach(obj, &elt->obj);
- ISC_LIST_APPEND(destobj->value.list, elt, link);
+ ISC_LIST_APPEND(*destobj->value.list, elt, link);
} else {
result = ISC_R_EXISTS;
}
if (prepend) {
ISC_LIST_APPEND(list, dstelt, link);
} else {
- ISC_LIST_APPEND(dst->value.list, dstelt, link);
+ ISC_LIST_APPEND(*dst->value.list, dstelt, link);
}
srcelt = cfg_list_next(srcelt);
}
if (prepend) {
- ISC_LIST_PREPENDLIST(dst->value.list, list, link);
+ ISC_LIST_PREPENDLIST(*dst->value.list, list, link);
}
}