From: Colin Vidal Date: Wed, 22 Oct 2025 09:49:09 +0000 (+0200) Subject: cfg_parse_ functions internally handle the parser X-Git-Tag: v9.21.15~43^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d03f6e6fd47ff083f9b3bfa17306d7de00b517d2;p=thirdparty%2Fbind9.git cfg_parse_ functions internally handle the parser Instead of (1) allocating a parser, (2) parsing a file/buffer then (3) freeing the parser, the parser is now internally created/destroyed from within the `cfg_parse_*` functions. This simplifies a lot the use cases, especially around the error cases where the parser needs to be freed in a cleanup goto. The only trick was the parser callback mechanism, which would previously have been set up between steps 1 and 2. Since it's never been used for any purpose other than the "directory" option, the chdir call has now been moved inside the parser and the generic callback mechanism has been removed, replacing CFG_CLAUSEFLAG_CALLBACK with CFG_CLAUSEFLAG_CHDIR. --- diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c index 0c217efd924..169fd66ef75 100644 --- a/bin/check/named-checkconf.c +++ b/bin/check/named-checkconf.c @@ -63,32 +63,6 @@ usage(void) { exit(EXIT_SUCCESS); } -/*% directory callback */ -static isc_result_t -directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { - isc_result_t result; - const char *directory; - - REQUIRE(strcasecmp("directory", clausename) == 0); - - UNUSED(arg); - UNUSED(clausename); - - /* - * Change directory. - */ - directory = cfg_obj_asstring(obj); - result = isc_dir_chdir(directory); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "change directory to '%s' failed: %s\n", directory, - isc_result_totext(result)); - return result; - } - - return ISC_R_SUCCESS; -} - static bool get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) { int i; @@ -574,16 +548,14 @@ output(void *closure, const char *text, int textlen) { int main(int argc, char **argv) { int c; - cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL; const char *conffile = NULL; isc_result_t result = ISC_R_SUCCESS; bool load_zones = false; bool list_zones = false; bool print = false; - bool nodeprecate = false; - bool allconfigs = false; unsigned int flags = 0; + unsigned int parserflags = 0; unsigned int checkflags = BIND_CHECK_PLUGINS | BIND_CHECK_ALGORITHMS; isc_commandline_init(argc, argv); @@ -631,7 +603,7 @@ main(int argc, char **argv) { break; case 'i': - nodeprecate = true; + parserflags |= CFG_PCTX_NODEPRECATED; break; case 'j': @@ -650,7 +622,7 @@ main(int argc, char **argv) { break; case 'n': - allconfigs = true; + parserflags |= CFG_PCTX_ALLCONFIGS; break; case 't': @@ -722,18 +694,8 @@ main(int argc, char **argv) { } CHECK(setup_logging(stdout)); - - CHECK(cfg_parser_create(isc_g_mctx, &parser)); - - if (nodeprecate) { - cfg_parser_setflags(parser, CFG_PCTX_NODEPRECATED, true); - } - if (allconfigs) { - cfg_parser_setflags(parser, CFG_PCTX_ALLCONFIGS, true); - } - cfg_parser_setcallback(parser, directory_callback, NULL); - - CHECK(cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config)); + CHECK(cfg_parse_file(isc_g_mctx, conffile, &cfg_type_namedconf, + parserflags, &config)); CHECK(isccfg_check_namedconf(config, checkflags, isc_g_mctx)); if (load_zones || list_zones) { CHECK(load_zones_fromconfig(config, list_zones)); @@ -748,9 +710,5 @@ cleanup: cfg_obj_detach(&config); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } - return result == ISC_R_SUCCESS ? 0 : 1; } diff --git a/bin/delv/delv.c b/bin/delv/delv.c index dd53c825fa3..b05e05f2d22 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -808,7 +808,6 @@ cleanup: static isc_result_t setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) { isc_result_t result; - cfg_parser_t *parser = NULL; const cfg_obj_t *trust_anchors = NULL; cfg_obj_t *bindkeys = NULL; @@ -824,15 +823,13 @@ setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) { CHECK(convert_name(&afn, &anchor_name, trust_anchor)); } - CHECK(cfg_parser_create(isc_g_mctx, &parser)); - if (anchorfile != NULL) { if (access(anchorfile, R_OK) != 0) { fatal("Unable to read key file '%s'", anchorfile); } - result = cfg_parse_file(parser, anchorfile, &cfg_type_bindkeys, - &bindkeys); + result = cfg_parse_file(isc_g_mctx, anchorfile, + &cfg_type_bindkeys, 0, &bindkeys); if (result != ISC_R_SUCCESS) { fatal("Unable to load keys from '%s'", anchorfile); } @@ -841,8 +838,7 @@ setup_dnsseckeys(dns_client_t *client, dns_view_t *toview) { isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); isc_buffer_add(&b, sizeof(anchortext) - 1); - cfg_parser_reset(parser); - result = cfg_parse_buffer(parser, &b, NULL, 0, + result = cfg_parse_buffer(isc_g_mctx, &b, NULL, 0, &cfg_type_bindkeys, 0, &bindkeys); if (result != ISC_R_SUCCESS) { fatal("Unable to parse built-in keys"); @@ -864,9 +860,6 @@ cleanup: if (bindkeys != NULL) { cfg_obj_detach(&bindkeys); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } if (result != ISC_R_SUCCESS) { delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", isc_result_totext(result)); diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 51949c2cc9f..5928c265bd8 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -1072,7 +1072,6 @@ parse_hmac(const char *algname) { */ static isc_result_t read_confkey(void) { - cfg_parser_t *pctx = NULL; cfg_obj_t *file = NULL; const cfg_obj_t *keyobj = NULL; const cfg_obj_t *secretobj = NULL; @@ -1086,12 +1085,8 @@ read_confkey(void) { return ISC_R_FILENOTFOUND; } - result = cfg_parser_create(isc_g_mctx, &pctx); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file); + result = cfg_parse_file(isc_g_mctx, keyfile, &cfg_type_sessionkey, 0, + &file); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -1117,11 +1112,8 @@ read_confkey(void) { setup_text_key(); cleanup: - if (pctx != NULL) { - if (file != NULL) { - cfg_obj_detach(&file); - } - cfg_parser_destroy(&pctx); + if (file != NULL) { + cfg_obj_detach(&file); } return result; diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index ab53148b449..6c6e82f097d 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -1147,14 +1147,11 @@ main(int argc, char **argv) { keygen(&ctx, argc, argv); } else { - cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL; dns_kasp_t *kasp = NULL; - RUNTIME_CHECK(cfg_parser_create(isc_g_mctx, &parser) == - ISC_R_SUCCESS); - if (cfg_parse_file(parser, ctx.configfile, - &cfg_type_namedconf, + if (cfg_parse_file(isc_g_mctx, ctx.configfile, + &cfg_type_namedconf, 0, &config) != ISC_R_SUCCESS) { fatal("unable to load dnssec-policy '%s' from " @@ -1200,7 +1197,6 @@ main(int argc, char **argv) { dns_kasp_detach(&kasp); cfg_obj_detach(&config); - cfg_parser_destroy(&parser); } } else { keygen(&ctx, argc, argv); diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c index 0a43fd889ac..a4ef81b82ec 100644 --- a/bin/dnssec/dnssec-ksr.c +++ b/bin/dnssec/dnssec-ksr.c @@ -170,11 +170,9 @@ checkparams(ksr_ctx_t *ksr, const char *command) { static void getkasp(ksr_ctx_t *ksr, dns_kasp_t **kasp) { - cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL; - RUNTIME_CHECK(cfg_parser_create(isc_g_mctx, &parser) == ISC_R_SUCCESS); - if (cfg_parse_file(parser, ksr->configfile, &cfg_type_namedconf, + if (cfg_parse_file(isc_g_mctx, ksr->configfile, &cfg_type_namedconf, 0, &config) != ISC_R_SUCCESS) { fatal("unable to load dnssec-policy '%s' from '%s'", @@ -188,7 +186,6 @@ getkasp(ksr_ctx_t *ksr, dns_kasp_t **kasp) { fatal("dnssec-policy '%s' has no keys configured", ksr->policy); } cfg_obj_detach(&config); - cfg_parser_destroy(&parser); } static int diff --git a/bin/named/config.c b/bin/named/config.c index d7022be01ba..00006a8522f 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -363,89 +363,28 @@ remote-servers " DEFAULT_IANA_ROOT_ZONE_PRIMARIES " {\n\ isc_result_t named_config_parsedefaults(cfg_obj_t **conf) { isc_buffer_t b; - cfg_parser_t *parser = NULL; - isc_result_t result; - - result = cfg_parser_create(isc_g_mctx, &parser); - if (result != ISC_R_SUCCESS) { - return result; - } isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1); isc_buffer_add(&b, sizeof(defaultconf) - 1); - result = cfg_parse_buffer(parser, &b, __FILE__, 0, &cfg_type_namedconf, - CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | - CFG_PCTX_NOEXPERIMENTAL, - conf); - - cfg_parser_destroy(&parser); - return result; -} - -/* - * This function is called as soon as the 'directory' statement has been - * parsed. This can be extended to support other options if necessary. - */ -static isc_result_t -directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) { - isc_result_t result; - const char *directory; - - REQUIRE(strcasecmp("directory", clausename) == 0); - - UNUSED(arg); - UNUSED(clausename); - - /* - * Change directory. - */ - directory = cfg_obj_asstring(obj); - - if (!isc_file_ischdiridempotent(directory)) { - cfg_obj_log(obj, ISC_LOG_WARNING, - "option 'directory' contains relative path '%s'", - directory); - } - - if (!isc_file_isdirwritable(directory)) { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, - ISC_LOG_ERROR, "directory '%s' is not writable", - directory); - return ISC_R_NOPERM; - } - - result = isc_dir_chdir(directory); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(obj, ISC_LOG_ERROR, - "change directory to '%s' failed: %s", directory, - isc_result_totext(result)); - return result; - } - - char cwd[PATH_MAX]; - if (getcwd(cwd, sizeof(cwd)) == cwd) { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, - ISC_LOG_INFO, "the working directory is now '%s'", - cwd); - } - - return ISC_R_SUCCESS; + return cfg_parse_buffer(isc_g_mctx, &b, __FILE__, 0, + &cfg_type_namedconf, + CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | + CFG_PCTX_NOEXPERIMENTAL, + conf); } isc_result_t -named_config_parsefile(cfg_parser_t *parser, cfg_obj_t **conf) { +named_config_parsefile(cfg_obj_t **conf) { isc_result_t result; - REQUIRE(parser); REQUIRE(conf && *conf == NULL); isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "parsing user configuration from '%s'", named_g_conffile); - cfg_parser_setcallback(parser, directory_callback, NULL); - result = cfg_parse_file(parser, named_g_conffile, &cfg_type_namedconf, - conf); + result = cfg_parse_file(isc_g_mctx, named_g_conffile, + &cfg_type_namedconf, 0, conf); if (result != ISC_R_SUCCESS) { goto cleanup; } diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c index 0ae02c8891e..0376d2b7709 100644 --- a/bin/named/controlconf.c +++ b/bin/named/controlconf.c @@ -787,7 +787,6 @@ register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist, static isc_result_t get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; - cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *algobj = NULL; @@ -806,8 +805,7 @@ get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { return ISC_R_FILENOTFOUND; } - CHECK(cfg_parser_create(mctx, &pctx)); - CHECK(cfg_parse_file(pctx, named_g_keyfile, &cfg_type_rndckey, + CHECK(cfg_parse_file(mctx, named_g_keyfile, &cfg_type_rndckey, 0, &config)); CHECK(cfg_map_get(config, "key", &key)); @@ -863,9 +861,6 @@ cleanup: if (config != NULL) { cfg_obj_detach(&config); } - if (pctx != NULL) { - cfg_parser_destroy(&pctx); - } return result; } diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h index 6b275727d4b..3de19d73f84 100644 --- a/bin/named/include/named/config.h +++ b/bin/named/include/named/config.h @@ -28,7 +28,7 @@ isc_result_t named_config_parsedefaults(cfg_obj_t **conf); isc_result_t -named_config_parsefile(cfg_parser_t *parser, cfg_obj_t **conf); +named_config_parsefile(cfg_obj_t **conf); const char * named_config_getdefault(void); diff --git a/bin/named/server.c b/bin/named/server.c index 5fdfedd0829..989bcee49c1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -2349,7 +2349,6 @@ catz_addmodzone_cb(void *arg) { cfg_obj_t *zoneobj = NULL; ns_cfgctx_t *cfg = NULL; dns_zone_t *zone = NULL; - cfg_parser_t *parser = NULL; if (isc_loop_shuttingdown(isc_loop_get(isc_tid()))) { goto cleanup; @@ -2464,10 +2463,8 @@ catz_addmodzone_cb(void *arg) { confbuf = NULL; result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); if (result == ISC_R_SUCCESS) { - CHECK(cfg_parser_create(cfg->mctx, &parser)); - result = cfg_parse_buffer(parser, confbuf, "catz", 0, + result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0, &cfg_type_addzoneconf, 0, &zoneconf); - cfg_parser_destroy(&parser); isc_buffer_free(&confbuf); } /* @@ -2721,7 +2718,6 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { ns_cfgctx_t *cfg = NULL; dns_zone_t *zone = NULL; isc_result_t result; - cfg_parser_t *parser = NULL; isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); dns_name_totext(dns_catz_entry_getname(entry), DNS_NAME_OMITFINALDOT, @@ -2745,10 +2741,8 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); if (result == ISC_R_SUCCESS) { - CHECK(cfg_parser_create(cfg->mctx, &parser)); - result = cfg_parse_buffer(parser, confbuf, "catz", 0, + result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0, &cfg_type_addzoneconf, 0, &zoneconf); - cfg_parser_destroy(&parser); isc_buffer_free(&confbuf); } /* @@ -7558,7 +7552,6 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, size_t zone_config_len; cfg_obj_t *zoneconf = NULL; char bufname[DNS_NAME_FORMATSIZE]; - cfg_parser_t *parser = NULL; REQUIRE(view != NULL); REQUIRE(key != NULL); @@ -7596,10 +7589,8 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, zone_name); - CHECK(cfg_parser_create(view->mctx, &parser)); - result = cfg_parse_buffer(parser, *text, bufname, 0, + result = cfg_parse_buffer(view->mctx, *text, bufname, 0, &cfg_type_addzoneconf, 0, &zoneconf); - cfg_parser_destroy(&parser); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, @@ -9232,14 +9223,12 @@ cleanup_aclctx: static isc_result_t load_configuration(named_server_t *server, bool first_time) { isc_result_t result; - cfg_parser_t *parser = NULL; cfg_obj_t *config = NULL, *bindkeys = NULL; isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), "load_configuration"); - CHECK(cfg_parser_create(isc_g_mctx, &parser)); - CHECK(named_config_parsefile(parser, &config)); + CHECK(named_config_parsefile(&config)); if (named_g_bindkeysfile != NULL) { /* @@ -9255,9 +9244,9 @@ load_configuration(named_server_t *server, bool first_time) { "keys instead", named_g_bindkeysfile); } else { - cfg_parser_reset(parser); - result = cfg_parse_file(parser, named_g_bindkeysfile, - &cfg_type_bindkeys, &bindkeys); + result = cfg_parse_file( + isc_g_mctx, named_g_bindkeysfile, + &cfg_type_bindkeys, 0, &bindkeys); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, @@ -9274,9 +9263,6 @@ load_configuration(named_server_t *server, bool first_time) { result = apply_configuration(config, bindkeys, server, first_time); cleanup: - if (parser != NULL) { - cfg_parser_destroy(&parser); - } if (bindkeys != NULL) { cfg_obj_detach(&bindkeys); } @@ -12466,9 +12452,8 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { * Parse the configuration in the NZF file. This may be called in * multiple views, so we reset the parser each time. */ - cfg_parser_reset(named_g_addparser); - result = cfg_parse_file(named_g_addparser, view->new_zone_file, - &cfg_type_addzoneconf, &nzcfg->nzf_config); + result = cfg_parse_file(nzcfg->mctx, view->new_zone_file, + &cfg_type_addzoneconf, 0, &nzcfg->nzf_config); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", @@ -12816,7 +12801,6 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { MDB_dbi dbi; MDB_val key, data; ns_dzarg_t dzarg; - cfg_parser_t *parser = NULL; UNUSED(nzcfg); @@ -12840,10 +12824,8 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { * config type, giving us a guarantee that valid configuration * will be written to DB. */ - CHECK(cfg_parser_create(nzcfg->mctx, &parser)); - result = cfg_parse_file(parser, view->new_zone_file, - &cfg_type_addzoneconf, &nzf_config); - cfg_parser_destroy(&parser); + result = cfg_parse_file(nzcfg->mctx, view->new_zone_file, + &cfg_type_addzoneconf, 0, &nzf_config); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", @@ -12973,7 +12955,6 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, dns_rdataclass_t rdclass; dns_view_t *view = NULL; const char *bn = NULL; - cfg_parser_t *parser = NULL; REQUIRE(viewp != NULL && *viewp == NULL); REQUIRE(zoneobjp != NULL && *zoneobjp == NULL); @@ -12998,10 +12979,8 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, */ isc_buffer_forward(&argbuf, 3); - CHECK(cfg_parser_create(server->mctx, &parser)); - CHECK(cfg_parse_buffer(parser, &argbuf, bn, 0, &cfg_type_addzoneconf, 0, - &zoneconf)); - cfg_parser_destroy(&parser); + CHECK(cfg_parse_buffer(server->mctx, &argbuf, bn, 0, + &cfg_type_addzoneconf, 0, &zoneconf)); CHECK(cfg_map_get(zoneconf, "zone", &zlist)); if (!cfg_obj_islist(zlist)) { @@ -13076,10 +13055,6 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, return ISC_R_SUCCESS; cleanup: - if (parser != NULL) { - cfg_parser_destroy(&parser); - } - if (zoneconf != NULL) { cfg_obj_detach(&zoneconf); } @@ -13091,13 +13066,12 @@ cleanup: } static isc_result_t -delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, +delete_zoneconf(dns_view_t *view, const cfg_obj_t *config, const dns_name_t *zname, nzfwriter_t nzfwriter) { isc_result_t result = ISC_R_NOTFOUND; const cfg_obj_t *zl = NULL; REQUIRE(view != NULL); - REQUIRE(pctx != NULL); REQUIRE(config != NULL); REQUIRE(zname != NULL); @@ -13126,7 +13100,6 @@ delete_zoneconf(dns_view_t *view, cfg_parser_t *pctx, const cfg_obj_t *config, e = UNCONST(elt); ISC_LIST_UNLINK(*list, e, link); cfg_obj_detach(&e->obj); - isc_mem_put(pctx->mctx, e, sizeof(*e)); result = ISC_R_SUCCESS; break; } @@ -13263,8 +13236,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, cfg_obj_attach(zoneconf, &cfg->nzf_config); } else { cfg_obj_t *z = UNCONST(zoneobj); - CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, - "zone")); + CHECK(cfg_parser_mapadd(cfg->nzf_config, z, "zone")); } cleanup_config = true; #endif /* HAVE_LMDB */ @@ -13313,8 +13285,7 @@ cleanup: (void)isc_stdio_close(fp); } if (result != ISC_R_SUCCESS && cleanup_config) { - tresult = delete_zoneconf(view, cfg->add_parser, - cfg->nzf_config, name, NULL); + tresult = delete_zoneconf(view, cfg->nzf_config, name, NULL); RUNTIME_CHECK(tresult == ISC_R_SUCCESS); } #else /* HAVE_LMDB */ @@ -13341,7 +13312,6 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, dns_zone_t *zone = NULL; const cfg_obj_t *voptions = NULL; bool added; - cfg_parser_t *parser = NULL; #ifndef HAVE_LMDB FILE *fp = NULL; cfg_obj_t *z; @@ -13448,7 +13418,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB /* Remove old zone from configuration (and NZF file if applicable) */ if (added) { - result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, + result = delete_zoneconf(view, cfg->nzf_config, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { @@ -13461,18 +13431,15 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #endif /* HAVE_LMDB */ if (!added) { - TCHECK(cfg_parser_create(cfg->mctx, &parser)); if (cfg->vconfig == NULL) { - result = delete_zoneconf(view, parser, cfg->config, + result = delete_zoneconf(view, cfg->config, dns_zone_getorigin(zone), NULL); } else { voptions = cfg_tuple_get(cfg->vconfig, "options"); - result = delete_zoneconf(view, parser, voptions, - dns_zone_getorigin(zone), - NULL); + result = delete_zoneconf( + view, voptions, dns_zone_getorigin(zone), NULL); } - cfg_parser_destroy(&parser); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "former zone configuration " @@ -13520,7 +13487,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB /* Store the new zone configuration; also in NZF if applicable */ z = UNCONST(zoneobj); - CHECK(cfg_parser_mapadd(cfg->add_parser, cfg->nzf_config, z, "zone")); + CHECK(cfg_parser_mapadd(cfg->nzf_config, z, "zone")); #endif /* HAVE_LMDB */ if (added) { @@ -13695,7 +13662,6 @@ rmzone(void *arg) { dns_db_t *dbp = NULL; bool added; isc_result_t result; - cfg_parser_t *parser = NULL; #ifdef HAVE_LMDB MDB_txn *txn = NULL; MDB_dbi dbi; @@ -13746,7 +13712,7 @@ rmzone(void *arg) { } UNLOCK(&view->new_zone_lock); #else /* ifdef HAVE_LMDB */ - result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, + result = delete_zoneconf(view, cfg->nzf_config, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { @@ -13759,24 +13725,17 @@ rmzone(void *arg) { } if (!added && cfg != NULL) { - result = cfg_parser_create(cfg->mctx, &parser); - INSIST(result == ISC_R_SUCCESS); /* colin: this is just a - shortcut until the - initialization function of - the parser can't fails */ - if (cfg->vconfig != NULL) { const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, "options"); - result = delete_zoneconf(view, parser, voptions, - dns_zone_getorigin(zone), - NULL); + result = delete_zoneconf( + view, voptions, dns_zone_getorigin(zone), NULL); } else { - result = delete_zoneconf(view, parser, cfg->config, + result = delete_zoneconf(view, cfg->config, dns_zone_getorigin(zone), NULL); } - cfg_parser_destroy(&parser); + if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 585dc80b91d..4ceff564661 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -555,7 +555,6 @@ failure: */ static isc_result_t read_sessionkey(isc_mem_t *mctx) { - cfg_parser_t *pctx = NULL; cfg_obj_t *sessionkey = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *secretobj = NULL; @@ -570,12 +569,7 @@ read_sessionkey(isc_mem_t *mctx) { return ISC_R_FILENOTFOUND; } - result = cfg_parser_create(mctx, &pctx); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - - result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, + result = cfg_parse_file(mctx, keyfile, &cfg_type_sessionkey, 0, &sessionkey); if (result != ISC_R_SUCCESS) { goto cleanup; @@ -602,11 +596,8 @@ read_sessionkey(isc_mem_t *mctx) { setup_keystr(); cleanup: - if (pctx != NULL) { - if (sessionkey != NULL) { - cfg_obj_detach(&sessionkey); - } - cfg_parser_destroy(&pctx); + if (sessionkey != NULL) { + cfg_obj_detach(&sessionkey); } if (keystr != NULL) { diff --git a/bin/plugins/filter-a.c b/bin/plugins/filter-a.c index 5d1cf06e524..2d98b706921 100644 --- a/bin/plugins/filter-a.c +++ b/bin/plugins/filter-a.c @@ -274,16 +274,13 @@ parse_parameters(filter_instance_t *inst, const char *parameters, const void *cfg, const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx, void *aclctx) { isc_result_t result = ISC_R_SUCCESS; - cfg_parser_t *parser = NULL; cfg_obj_t *param_obj = NULL; const cfg_obj_t *obj = NULL; isc_buffer_t b; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line, &cfg_type_parameters, 0, ¶m_obj)); CHECK(parse_filter_a_on(param_obj, "filter-a-on-v6", &inst->v6_a)); @@ -302,9 +299,6 @@ cleanup: if (param_obj != NULL) { cfg_obj_detach(¶m_obj); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } return result; } @@ -368,15 +362,12 @@ plugin_check(const char *parameters, const void *cfg, const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx, void *aclctx, const ns_pluginctx_t *ctx ISC_ATTR_UNUSED) { isc_result_t result = ISC_R_SUCCESS; - cfg_parser_t *parser = NULL; cfg_obj_t *param_obj = NULL; isc_buffer_t b; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line, &cfg_type_parameters, 0, ¶m_obj)); CHECK(check_syntax(param_obj, cfg, mctx, aclctx)); @@ -385,9 +376,6 @@ cleanup: if (param_obj != NULL) { cfg_obj_detach(¶m_obj); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } return result; } diff --git a/bin/plugins/filter-aaaa.c b/bin/plugins/filter-aaaa.c index ad2ef52f3ac..dad917464cd 100644 --- a/bin/plugins/filter-aaaa.c +++ b/bin/plugins/filter-aaaa.c @@ -275,16 +275,13 @@ parse_parameters(filter_instance_t *inst, const char *parameters, const void *cfg, const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx, void *aclctx) { isc_result_t result = ISC_R_SUCCESS; - cfg_parser_t *parser = NULL; cfg_obj_t *param_obj = NULL; const cfg_obj_t *obj = NULL; isc_buffer_t b; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line, &cfg_type_parameters, 0, ¶m_obj)); CHECK(parse_filter_aaaa_on(param_obj, "filter-aaaa-on-v4", @@ -305,9 +302,6 @@ cleanup: if (param_obj != NULL) { cfg_obj_detach(¶m_obj); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } return result; } @@ -372,15 +366,12 @@ plugin_check(const char *parameters, const void *cfg, const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx, void *aclctx, const ns_pluginctx_t *ctx ISC_ATTR_UNUSED) { isc_result_t result = ISC_R_SUCCESS; - cfg_parser_t *parser = NULL; cfg_obj_t *param_obj = NULL; isc_buffer_t b; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfg_file, cfg_line, + CHECK(cfg_parse_buffer(mctx, &b, cfg_file, cfg_line, &cfg_type_parameters, 0, ¶m_obj)); CHECK(check_syntax(param_obj, cfg, mctx, aclctx)); @@ -389,9 +380,6 @@ cleanup: if (param_obj != NULL) { cfg_obj_detach(¶m_obj); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } return result; } diff --git a/bin/plugins/synthrecord.c b/bin/plugins/synthrecord.c index 5c5f34bf892..1fab2a3a374 100644 --- a/bin/plugins/synthrecord.c +++ b/bin/plugins/synthrecord.c @@ -573,16 +573,13 @@ synthrecord_parseconfig(synthrecord_t *inst, const char *parameters, const dns_name_t *zname) { isc_result_t result; isc_mem_t *mctx = inst->mctx; - cfg_parser_t *parser = NULL; cfg_obj_t *synthrecordcfg = NULL; isc_buffer_t b; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfgfile, cfgline, + CHECK(cfg_parse_buffer(mctx, &b, cfgfile, cfgline, &synthrecord_cfgparams, 0, &synthrecordcfg)); synthrecord_setconfigmode(inst, zname); @@ -596,10 +593,6 @@ cleanup: cfg_obj_detach(&synthrecordcfg); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } - return result; } diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 3204e30a636..46d0aa0c97c 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -535,8 +535,7 @@ rndc_start(void *arg) { } static void -parse_config(isc_mem_t *mctx, const char *keyname, cfg_parser_t **pctxp, - cfg_obj_t **configp) { +parse_config(isc_mem_t *mctx, const char *keyname, cfg_obj_t **configp) { isc_result_t result; const char *conffile = admin_conffile; const cfg_obj_t *addresses = NULL; @@ -577,12 +576,10 @@ parse_config(isc_mem_t *mctx, const char *keyname, cfg_parser_t **pctxp, admin_keyfile, admin_conffile); } - DO("create parser", cfg_parser_create(mctx, pctxp)); - /* * The parser will output its own errors, so DO() is not used. */ - result = cfg_parse_file(*pctxp, conffile, conftype, &config); + result = cfg_parse_file(mctx, conffile, conftype, 0, &config); if (result != ISC_R_SUCCESS) { fatal("could not load rndc configuration"); } @@ -809,7 +806,6 @@ int main(int argc, char **argv) { bool show_final_mem = false; isc_logconfig_t *logconfig = NULL; - cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const char *keyname = NULL; struct in_addr in; @@ -963,7 +959,7 @@ main(int argc, char **argv) { ISC_LOG_PRINTTAG | ISC_LOG_PRINTLEVEL, ISC_LOGCATEGORY_DEFAULT, ISC_LOGMODULE_DEFAULT); - parse_config(isc_g_mctx, keyname, &pctx, &config); + parse_config(isc_g_mctx, keyname, &config); isc_buffer_allocate(isc_g_mctx, &databuf, 2048); @@ -1000,7 +996,6 @@ main(int argc, char **argv) { isccc_ccmsg_invalidate(&rndc_ccmsg); cfg_obj_detach(&config); - cfg_parser_destroy(&pctx); isc_mem_put(isc_g_mctx, args, argslen); diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index efb781188b8..aec7b136396 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -522,6 +522,7 @@ n=$((n + 1)) echo_i "check that named-checkconf -l prints out the zone list ($n)" ret=0 $CHECKCONF -l good.conf \ + | grep -v "working directory is" \ | grep -v "is deprecated" \ | grep -v "is not implemented" \ | grep -v "is not recommended" \ diff --git a/bin/tests/system/hooks/driver/test-syncplugin.c b/bin/tests/system/hooks/driver/test-syncplugin.c index 09856fd2ccf..620829c8cc4 100644 --- a/bin/tests/system/hooks/driver/test-syncplugin.c +++ b/bin/tests/system/hooks/driver/test-syncplugin.c @@ -116,7 +116,6 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile, ns_hooktable_t *hooktable, const ns_pluginctx_t *ctx, void **instp) { isc_result_t result; - cfg_parser_t *parser = NULL; cfg_obj_t *syncplugincfg = NULL; const cfg_obj_t *obj = NULL; isc_buffer_t b; @@ -135,12 +134,10 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile, *inst = (syncplugin_t){ .mctx = mctx }; *instp = inst; - CHECK(cfg_parser_create(mctx, &parser)); - isc_buffer_constinit(&b, parameters, strlen(parameters)); isc_buffer_add(&b, strlen(parameters)); - CHECK(cfg_parse_buffer(parser, &b, cfgfile, cfgline, + CHECK(cfg_parse_buffer(mctx, &b, cfgfile, cfgline, &syncplugin__cfgparams, 0, &syncplugincfg)); CHECK(syncplugin__parse_rcode(syncplugincfg, &inst->rcode)); @@ -220,10 +217,6 @@ cleanup: cfg_obj_detach(&syncplugincfg); } - if (parser != NULL) { - cfg_parser_destroy(&parser); - } - return result; } diff --git a/doc/misc/cfg_test.c b/doc/misc/cfg_test.c index 60b28bc1593..f29600c2aa7 100644 --- a/doc/misc/cfg_test.c +++ b/doc/misc/cfg_test.c @@ -52,7 +52,6 @@ int main(int argc, char **argv) { isc_result_t result; isc_mem_t *mctx = NULL; - cfg_parser_t *pctx = NULL; cfg_obj_t *cfg = NULL; cfg_type_t *type = NULL; bool grammar = false; @@ -134,9 +133,7 @@ main(int argc, char **argv) { if (type == NULL || filename == NULL) { usage(); } - RUNTIME_CHECK(cfg_parser_create(mctx, &pctx) == ISC_R_SUCCESS); - - result = cfg_parse_file(pctx, filename, type, &cfg); + result = cfg_parse_file(mctx, filename, type, 0, &cfg); fprintf(stderr, "read config: %s\n", isc_result_totext(result)); @@ -147,8 +144,6 @@ main(int argc, char **argv) { cfg_print(cfg, output, NULL); cfg_obj_detach(&cfg); - - cfg_parser_destroy(&pctx); } if (memstats) { diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h index 8e861655a50..b403fa7b28a 100644 --- a/lib/isccfg/include/isccfg/cfg.h +++ b/lib/isccfg/include/isccfg/cfg.h @@ -113,25 +113,12 @@ cfg_parser_setflags(cfg_parser_t *pctx, unsigned int flags, bool turn_on); *\li "pctx" is not NULL. */ -void -cfg_parser_setcallback(cfg_parser_t *pctx, cfg_parsecallback_t callback, - void *arg); -/*%< - * Make the parser call 'callback' whenever it encounters - * a configuration clause with the callback attribute, - * passing it the clause name, the clause value, - * and 'arg' as arguments. - * - * To restore the default of not invoking callbacks, pass - * callback==NULL and arg==NULL. - */ - isc_result_t -cfg_parse_file(cfg_parser_t *pctx, const char *file, const cfg_type_t *type, - cfg_obj_t **ret); +cfg_parse_file(isc_mem_t *mctx, const char *file, const cfg_type_t *type, + unsigned int flags, cfg_obj_t **ret); isc_result_t -cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file, +cfg_parse_buffer(isc_mem_t *mctx, isc_buffer_t *buffer, const char *file, unsigned int line, const cfg_type_t *type, unsigned int flags, cfg_obj_t **ret); /*%< @@ -152,8 +139,9 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file, * Returns an error if the file or buffer does not parse correctly. * * Requires: - *\li "filename" is valid. - *\li "mem" is valid. + *\li "file" is valid. + *\li "buffer" is valid. + *\li "mctx" is valid. *\li "type" is valid. *\li "cfg" is non-NULL and "*cfg" is NULL. *\li "flags" be one or more of CFG_PCTX_NODEPRECATED or zero. @@ -165,8 +153,7 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file, */ isc_result_t -cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj, - const char *clause); +cfg_parser_mapadd(cfg_obj_t *mapobj, cfg_obj_t *obj, const char *clause); /*%< * Add the object 'obj' to the specified clause in mapbody 'mapobj'. * Used for adding new zones. @@ -174,7 +161,6 @@ cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj, * Require: * \li 'obj' is a valid cfg_obj_t. * \li 'mapobj' is a valid cfg_obj_t of type map. - * \li 'pctx' is a valid cfg_parser_t. */ void diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h index c06fedefb29..8e84e31a37d 100644 --- a/lib/isccfg/include/isccfg/grammar.h +++ b/lib/isccfg/include/isccfg/grammar.h @@ -47,11 +47,8 @@ enum { /*% Clause is obsolete (logs a warning, but is not a fatal error) */ CFG_CLAUSEFLAG_OBSOLETE = 1 << 3, - /*% - * Clause needs to be interpreted during parsing by calling a - * callback function, like the "directory" option. - */ - CFG_CLAUSEFLAG_CALLBACK = 1 << 4, + /*% Clause indicates it must change the current directory */ + CFG_CLAUSEFLAG_CHDIR = 1 << 4, /*% Clause that is only used in testing. */ CFG_CLAUSEFLAG_TESTONLY = 1 << 5, @@ -266,9 +263,6 @@ struct cfg_parser { /*%< Reference counter */ isc_refcount_t references; - - cfg_parsecallback_t callback; - void *callbackarg; }; /* Parser context flags */ @@ -438,7 +432,8 @@ void cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type); isc_result_t -cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp); +cfg_create_list(isc_mem_t *mctx, cfg_obj_t *file, size_t line, + const cfg_type_t *type, cfg_obj_t **objp); isc_result_t cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype, diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index ce30d4b948c..d13fd830f86 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1232,7 +1232,7 @@ static cfg_clausedef_t options_clauses[] = { { "coresize", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "datasize", NULL, CFG_CLAUSEFLAG_ANCIENT }, { "deallocate-on-exit", NULL, CFG_CLAUSEFLAG_ANCIENT }, - { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CALLBACK }, + { "directory", &cfg_type_qstring, CFG_CLAUSEFLAG_CHDIR }, { "dnsrps-library", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE }, #ifdef HAVE_DNSTAP { "dnstap-output", &cfg_type_dnstapoutput, CFG_CLAUSEFLAG_OPTIONAL }, diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 822ccc83a20..b2667a2629c 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -114,7 +115,7 @@ static void free_list(cfg_obj_t *obj); static isc_result_t -create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp); +create_listelt(isc_mem_t *mctx, cfg_listelt_t **eltp); static isc_result_t create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type, @@ -542,8 +543,6 @@ cfg_parser_create(isc_mem_t *mctx, cfg_parser_t **ret) { pctx->open_files = NULL; pctx->closed_files = NULL; pctx->line = 0; - pctx->callback = NULL; - pctx->callbackarg = NULL; pctx->token.type = isc_tokentype_unknown; pctx->flags = 0; pctx->buf_name = NULL; @@ -563,8 +562,12 @@ cfg_parser_create(isc_mem_t *mctx, cfg_parser_t **ret) { ISC_LEXCOMMENT_CPLUSPLUS | ISC_LEXCOMMENT_SHELL); - CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files)); - CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files)); + CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, &cfg_type_filelist, + &pctx->open_files)); + CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, &cfg_type_filelist, + &pctx->closed_files)); *ret = pctx; return ISC_R_SUCCESS; @@ -604,7 +607,7 @@ parser_openfile(cfg_parser_t *pctx, const char *filename) { } CHECK(create_string(pctx, filename, &cfg_type_qstring, &stringobj)); - CHECK(create_listelt(pctx, &elt)); + CHECK(create_listelt(pctx->mctx, &elt)); elt->obj = stringobj; ISC_LIST_APPEND(pctx->open_files->value.list, elt, link); @@ -614,15 +617,6 @@ cleanup: return result; } -void -cfg_parser_setcallback(cfg_parser_t *pctx, cfg_parsecallback_t callback, - void *arg) { - REQUIRE(pctx != NULL); - - pctx->callback = callback; - pctx->callbackarg = arg; -} - void cfg_parser_reset(cfg_parser_t *pctx) { REQUIRE(pctx != NULL); @@ -674,16 +668,25 @@ cleanup: return result; } +#define REQUIRE_PCTX_FLAGS(flags) \ + REQUIRE((flags & ~(CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | \ + CFG_PCTX_NOEXPERIMENTAL)) == 0) + isc_result_t -cfg_parse_file(cfg_parser_t *pctx, const char *filename, const cfg_type_t *type, - cfg_obj_t **ret) { +cfg_parse_file(isc_mem_t *mctx, const char *filename, const cfg_type_t *type, + unsigned int flags, cfg_obj_t **ret) { isc_result_t result; cfg_listelt_t *elt; + cfg_parser_t *pctx = NULL; - REQUIRE(pctx != NULL); + REQUIRE(mctx != NULL); REQUIRE(filename != NULL); REQUIRE(type != NULL); REQUIRE(ret != NULL && *ret == NULL); + REQUIRE_PCTX_FLAGS(flags); + + CHECK(cfg_parser_create(mctx, &pctx)); + pctx->flags = flags; CHECK(parser_openfile(pctx, filename)); @@ -696,22 +699,27 @@ cfg_parse_file(cfg_parser_t *pctx, const char *filename, const cfg_type_t *type, ISC_LIST_APPEND(pctx->closed_files->value.list, elt, link); cleanup: + if (pctx != NULL) { + cfg_parser_destroy(&pctx); + } + return result; } isc_result_t -cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file, +cfg_parse_buffer(isc_mem_t *mctx, isc_buffer_t *buffer, const char *file, unsigned int line, const cfg_type_t *type, unsigned int flags, cfg_obj_t **ret) { isc_result_t result; + cfg_parser_t *pctx = NULL; - REQUIRE(pctx != NULL); + REQUIRE(mctx != NULL); REQUIRE(type != NULL); REQUIRE(buffer != NULL); REQUIRE(ret != NULL && *ret == NULL); - REQUIRE((flags & ~(CFG_PCTX_NODEPRECATED | CFG_PCTX_NOOBSOLETE | - CFG_PCTX_NOEXPERIMENTAL)) == 0); + REQUIRE_PCTX_FLAGS(flags); + CHECK(cfg_parser_create(mctx, &pctx)); CHECK(isc_lex_openbuffer(pctx->lexer, buffer)); pctx->buf_name = file; @@ -725,6 +733,10 @@ cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer, const char *file, pctx->buf_name = NULL; cleanup: + if (pctx != NULL) { + cfg_parser_destroy(&pctx); + } + return result; } @@ -1945,25 +1957,25 @@ cfg_type_t cfg_type_boolean = { "boolean", cfg_parse_boolean, */ isc_result_t -cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) { +cfg_create_list(isc_mem_t *mctx, cfg_obj_t *file, size_t line, + const cfg_type_t *type, cfg_obj_t **obj) { isc_result_t result; - REQUIRE(pctx != NULL); + REQUIRE(mctx != NULL); REQUIRE(type != NULL); REQUIRE(obj != NULL && *obj == NULL); - CHECK(cfg_create_obj(pctx->mctx, cfg_parser_currentfile(pctx), - pctx->line, type, obj)); + CHECK(cfg_create_obj(mctx, file, line, type, obj)); ISC_LIST_INIT((*obj)->value.list); cleanup: return result; } static isc_result_t -create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) { +create_listelt(isc_mem_t *mctx, cfg_listelt_t **eltp) { cfg_listelt_t *elt; - elt = isc_mem_get(pctx->mctx, sizeof(*elt)); + elt = isc_mem_get(mctx, sizeof(*elt)); elt->obj = NULL; ISC_LINK_INIT(elt, link); *eltp = elt; @@ -1996,7 +2008,7 @@ cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype, REQUIRE(elttype != NULL); REQUIRE(ret != NULL && *ret == NULL); - CHECK(create_listelt(pctx, &elt)); + CHECK(create_listelt(pctx->mctx, &elt)); result = cfg_parse_obj(pctx, elttype, &value); if (result != ISC_R_SUCCESS) { @@ -2024,7 +2036,8 @@ 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(cfg_create_list(pctx, listtype, &listobj)); + CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, listtype, &listobj)); for (;;) { CHECK(cfg_peektoken(pctx, 0)); @@ -2119,7 +2132,8 @@ cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype, listof = listtype->of; - CHECK(cfg_create_list(pctx, listtype, &listobj)); + CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, listtype, &listobj)); for (;;) { cfg_listelt_t *elt = NULL; @@ -2386,8 +2400,9 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { /* Multivalued clause */ cfg_obj_t *listobj = NULL; - CHECK(cfg_create_list(pctx, &cfg_type_implicitlist, - &listobj)); + CHECK(cfg_create_list( + pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, &cfg_type_implicitlist, &listobj)); symval.as_pointer = listobj; result = isc_symtab_define_and_return( obj->value.map.symtab, clause->name, @@ -2406,12 +2421,12 @@ cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { ISC_LIST_APPEND(listobj->value.list, elt, link); } else { /* Single-valued clause */ - bool callback = ((clause->flags & - CFG_CLAUSEFLAG_CALLBACK) != 0); + bool chdir = ((clause->flags & CFG_CLAUSEFLAG_CHDIR) != + 0); - result = parse_symtab_elt( - pctx, clause->name, clause->type, - obj->value.map.symtab, callback); + result = parse_symtab_elt(pctx, clause->name, + clause->type, + obj->value.map.symtab, chdir); if (result == ISC_R_EXISTS) { cfg_parser_error(pctx, CFG_LOG_NEAR, "'%s' redefined", @@ -2437,17 +2452,60 @@ cleanup: return result; } +static isc_result_t +change_directory(const char *clausename, const cfg_obj_t *obj) { + isc_result_t result; + const char *directory; + + REQUIRE(strcasecmp("directory", clausename) == 0); + + UNUSED(clausename); + + /* + * Change directory. + */ + directory = cfg_obj_asstring(obj); + + if (!isc_file_ischdiridempotent(directory)) { + cfg_obj_log(obj, ISC_LOG_WARNING, + "option 'directory' contains relative path '%s'", + directory); + } + + if (!isc_file_isdirwritable(directory)) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "directory '%s' is not writable", directory); + return ISC_R_NOPERM; + } + + result = isc_dir_chdir(directory); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(obj, ISC_LOG_ERROR, + "change directory to '%s' failed: %s", directory, + isc_result_totext(result)); + return result; + } + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == cwd) { + cfg_obj_log(obj, ISC_LOG_INFO, + "the working directory is now '%s'", cwd); + } + + return ISC_R_SUCCESS; +} + static isc_result_t parse_symtab_elt(cfg_parser_t *pctx, const char *name, cfg_type_t *elttype, - isc_symtab_t *symtab, bool callback) { + isc_symtab_t *symtab, bool chdir) { isc_result_t result; cfg_obj_t *obj = NULL; isc_symvalue_t symval; CHECK(cfg_parse_obj(pctx, elttype, &obj)); - if (callback && pctx->callback != NULL) { - CHECK(pctx->callback(name, obj, pctx->callbackarg)); + if (chdir) { + CHECK(change_directory(name, obj)); } symval.as_pointer = obj; @@ -2857,7 +2915,8 @@ parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { isc_result_t result; int braces = 0; - CHECK(cfg_create_list(pctx, type, &listobj)); + CHECK(cfg_create_list(pctx->mctx, cfg_parser_currentfile(pctx), + pctx->line, type, &listobj)); for (;;) { cfg_listelt_t *elt = NULL; @@ -3868,17 +3927,15 @@ cfg_print_grammar(const cfg_type_t *type, unsigned int flags, } isc_result_t -cfg_parser_mapadd(cfg_parser_t *pctx, cfg_obj_t *mapobj, cfg_obj_t *obj, - const char *clausename) { +cfg_parser_mapadd(cfg_obj_t *mapobj, cfg_obj_t *obj, const char *clausename) { isc_result_t result = ISC_R_SUCCESS; - const cfg_map_t *map; + const cfg_map_t *map = NULL; isc_symvalue_t symval; cfg_obj_t *destobj = NULL; cfg_listelt_t *elt = NULL; - const cfg_clausedef_t *const *clauseset; - const cfg_clausedef_t *clause; + const cfg_clausedef_t *const *clauseset = NULL; + const cfg_clausedef_t *clause = NULL; - REQUIRE(pctx != NULL); REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map); REQUIRE(obj != NULL); REQUIRE(clausename != NULL); @@ -3903,9 +3960,10 @@ breakout: &symval); if (result == ISC_R_NOTFOUND) { if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) { - CHECK(cfg_create_list(pctx, &cfg_type_implicitlist, + CHECK(cfg_create_list(mapobj->mctx, obj->file, + obj->line, &cfg_type_implicitlist, &destobj)); - CHECK(create_listelt(pctx, &elt)); + CHECK(create_listelt(mapobj->mctx, &elt)); cfg_obj_attach(obj, &elt->obj); ISC_LIST_APPEND(destobj->value.list, elt, link); symval.as_pointer = destobj; @@ -3923,7 +3981,7 @@ breakout: INSIST(result == ISC_R_SUCCESS); if (destobj2->type == &cfg_type_implicitlist) { - CHECK(create_listelt(pctx, &elt)); + CHECK(create_listelt(mapobj->mctx, &elt)); cfg_obj_attach(obj, &elt->obj); ISC_LIST_APPEND(destobj2->value.list, elt, link); } else { @@ -3936,7 +3994,7 @@ breakout: cleanup: if (elt != NULL) { - free_listelt(pctx->mctx, elt); + free_listelt(mapobj->mctx, elt); } CLEANUP_OBJ(destobj); diff --git a/tests/isccfg/duration_test.c b/tests/isccfg/duration_test.c index 4454933a1cd..a9cb1fd021d 100644 --- a/tests/isccfg/duration_test.c +++ b/tests/isccfg/duration_test.c @@ -120,7 +120,6 @@ ISC_RUN_TEST_IMPL(duration) { "T99999999999H99999999999M99999999999S" }, }; isc_buffer_t buf1; - cfg_parser_t *p1 = NULL; cfg_obj_t *c1 = NULL; bool must_fail = false; @@ -144,14 +143,10 @@ ISC_RUN_TEST_IMPL(duration) { isc_buffer_add(&buf1, strlen(conf) - 1); /* Parse with default line numbering */ - result = cfg_parser_create(isc_g_mctx, &p1); - assert_int_equal(result, ISC_R_SUCCESS); - - result = cfg_parse_buffer(p1, &buf1, "text1", 0, + result = cfg_parse_buffer(isc_g_mctx, &buf1, "text1", 0, &cfg_type_namedconf, 0, &c1); if (must_fail) { assert_int_equal(result, DNS_R_BADTTL); - cfg_parser_destroy(&p1); continue; } assert_int_equal(result, ISC_R_SUCCESS); @@ -193,7 +188,6 @@ ISC_RUN_TEST_IMPL(duration) { } cfg_obj_detach(&c1); - cfg_parser_destroy(&p1); } } diff --git a/tests/isccfg/grammar_test.c b/tests/isccfg/grammar_test.c index ac06a7e49af..88e4f00160e 100644 --- a/tests/isccfg/grammar_test.c +++ b/tests/isccfg/grammar_test.c @@ -124,16 +124,12 @@ static void test__query_source_print(const char *config, const char *expected) { isc_result_t result; isc_buffer_t buffer; - cfg_parser_t *parser = NULL; cfg_obj_t *output_conf = NULL; - result = cfg_parser_create(mctx, &parser); - assert_int_equal(result, ISC_R_SUCCESS); - isc_buffer_constinit(&buffer, config, strlen(config)); isc_buffer_add(&buffer, strlen(config)); - result = cfg_parse_buffer(parser, &buffer, "text1", 0, + result = cfg_parse_buffer(isc_g_mctx, &buffer, "text1", 0, &cfg_type_namedconf, 0, &output_conf); assert_int_equal(result, ISC_R_SUCCESS); assert_non_null(output_conf); @@ -144,9 +140,7 @@ test__query_source_print(const char *config, const char *expected) { output_conf->type->print(&pctx, output_conf); assert_text(expected); - cfg_obj_detach(parser, &output_conf); - cfg_parser_reset(parser); - cfg_parser_destroy(&parser); + cfg_obj_detach(&output_conf); } ISC_RUN_TEST_IMPL(query_source_print_none) { diff --git a/tests/isccfg/meson.build b/tests/isccfg/meson.build index 16ca023f861..419986f595b 100644 --- a/tests/isccfg/meson.build +++ b/tests/isccfg/meson.build @@ -11,6 +11,7 @@ foreach unit : [ 'duration', + 'grammar', 'parser', ] test_bin = executable( diff --git a/tests/isccfg/parser_test.c b/tests/isccfg/parser_test.c index 8ace4ea4f40..a08bf2abe66 100644 --- a/tests/isccfg/parser_test.c +++ b/tests/isccfg/parser_test.c @@ -60,7 +60,6 @@ append(void *arg, const char *str, int len) { ISC_RUN_TEST_IMPL(addzoneconf) { isc_result_t result; isc_buffer_t b; - cfg_parser_t *p = NULL; const char *tests[] = { "zone \"test4.baz\" { type primary; file \"e.db\"; };", "zone \"test/.baz\" { type primary; file \"e.db\"; };", @@ -73,9 +72,6 @@ ISC_RUN_TEST_IMPL(addzoneconf) { char buf[1024]; /* Parse with default line numbering */ - result = cfg_parser_create(isc_g_mctx, &p); - assert_int_equal(result, ISC_R_SUCCESS); - for (size_t i = 0; i < ARRAY_SIZE(tests); i++) { cfg_obj_t *conf = NULL; const cfg_obj_t *obj = NULL, *zlist = NULL; @@ -83,7 +79,7 @@ ISC_RUN_TEST_IMPL(addzoneconf) { isc_buffer_constinit(&b, tests[i], strlen(tests[i])); isc_buffer_add(&b, strlen(tests[i])); - result = cfg_parse_buffer(p, &b, "text1", 0, + result = cfg_parse_buffer(isc_g_mctx, &b, "text1", 0, &cfg_type_namedconf, 0, &conf); assert_int_equal(result, ISC_R_SUCCESS); @@ -103,49 +99,77 @@ ISC_RUN_TEST_IMPL(addzoneconf) { assert_string_equal(tests[i], buf); cfg_obj_detach(&conf); - cfg_parser_reset(p); } - - cfg_parser_destroy(&p); } /* test cfg_parse_buffer() */ ISC_RUN_TEST_IMPL(parse_buffer) { isc_result_t result; - unsigned char text[] = "options\n{\nrecursion yes;\n};\n"; - isc_buffer_t buf1, buf2; - cfg_parser_t *p1 = NULL, *p2 = NULL; - cfg_obj_t *c1 = NULL, *c2 = NULL; - - isc_buffer_init(&buf1, &text[0], sizeof(text) - 1); - isc_buffer_add(&buf1, sizeof(text) - 1); - - /* Parse with default line numbering */ - result = cfg_parser_create(isc_g_mctx, &p1); - assert_int_equal(result, ISC_R_SUCCESS); - - result = cfg_parse_buffer(p1, &buf1, "text1", 0, &cfg_type_namedconf, 0, - &c1); - assert_int_equal(result, ISC_R_SUCCESS); - assert_int_equal(p1->line, 5); - - isc_buffer_init(&buf2, &text[0], sizeof(text) - 1); - isc_buffer_add(&buf2, sizeof(text) - 1); - - /* Parse with changed line number */ - result = cfg_parser_create(isc_g_mctx, &p2); - assert_int_equal(result, ISC_R_SUCCESS); - - result = cfg_parse_buffer(p2, &buf2, "text2", 100, &cfg_type_namedconf, - 0, &c2); - assert_int_equal(result, ISC_R_SUCCESS); - assert_int_equal(p2->line, 104); - - cfg_obj_detach(&c1); - cfg_obj_detach(&c2); - - cfg_parser_destroy(&p1); - cfg_parser_destroy(&p2); + int fresult; + unsigned char text[] = "options\n{\nidonotexists yes;\n};\n"; + char logfilebuf[512]; + size_t logfilelen; + isc_buffer_t buf; + cfg_obj_t *c = NULL; + + /* + * Redirect parser errors into a specific file for checking the output + * later. + */ + constexpr char logfilename[] = "./cfglog.out"; + FILE *logfile = fopen(logfilename, "w+"); + assert_non_null(logfile); + + isc_logdestination_t *logdest = ISC_LOGDESTINATION_FILE(logfile); + isc_logconfig_t *logconfig = isc_logconfig_get(); + isc_log_createandusechannel(logconfig, "default_stderr", + ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, + logdest, 0, ISC_LOGCATEGORY_DEFAULT, + ISC_LOGMODULE_DEFAULT); + + /* Parse with default line numbering. */ + isc_buffer_init(&buf, &text[0], sizeof(text) - 1); + isc_buffer_add(&buf, sizeof(text) - 1); + result = cfg_parse_buffer(isc_g_mctx, &buf, "text1", 0, + &cfg_type_namedconf, 0, &c); + assert_int_equal(result, ISC_R_FAILURE); + assert_null(c); + + /* Parse with changed line number. */ + isc_buffer_first(&buf); + result = cfg_parse_buffer(isc_g_mctx, &buf, "text2", 100, + &cfg_type_namedconf, 0, &c); + assert_int_equal(result, ISC_R_FAILURE); + assert_null(c); + + /* Parse with changed line number and no name. */ + isc_buffer_first(&buf); + result = cfg_parse_buffer(isc_g_mctx, &buf, NULL, 100, + &cfg_type_namedconf, 0, &c); + assert_int_equal(result, ISC_R_FAILURE); + assert_null(c); + + /* Check log values (and, specifically, line numbers). */ + logfilelen = ftell(logfile); + assert_in_range(logfilelen, 0, sizeof(logfilebuf)); + + fresult = fseek(logfile, 0, SEEK_SET); + assert_int_equal(fresult, 0); + + fresult = fread(logfilebuf, 1, logfilelen, logfile); + assert_int_equal(fresult, logfilelen); + + logfilebuf[logfilelen] = 0; + + assert_non_null( + strstr(logfilebuf, "text1:3: unknown option 'idonotexists'")); + assert_non_null( + strstr(logfilebuf, "text2:102: unknown option 'idonotexists'")); + assert_non_null( + strstr(logfilebuf, "none:102: unknown option 'idonotexists'")); + + fclose(logfile); + remove(logfilename); } /* test cfg_map_firstclause() */