From 02fb764681d145e4607c59280a48617013e886ac Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 25 Aug 2016 18:08:26 -0700 Subject: [PATCH] [master] pass source file and line to dyndb load function 4455. [cleanup] Allow dyndb modules to correctly log the filename and line number when processing configuration text from named.conf. [RT #43050] --- CHANGES | 4 ++ bin/named/server.c | 5 ++- bin/tests/system/dyndb/driver/driver.c | 8 ++++ bin/tests/system/dyndb/tests.sh | 5 +++ lib/dns/dyndb.c | 7 ++-- lib/dns/include/dns/dyndb.h | 9 ++++- lib/isc/include/isc/lex.h | 17 ++++++++ lib/isc/lex.c | 18 +++++++-- lib/isc/tests/lex_test.c | 55 ++++++++++++++++++++++++-- 9 files changed, 115 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 1714f98ffd..83ce423b65 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ --- 9.11.0rc1 released --- +4455. [cleanup] Allow dyndb modules to correctly log the filename + and line number when processing configuration text + from named.conf. [RT #43050] + 4454. [bug] 'rndc dnstap -reopen' had a race issue. [RT #43089] 4453. [bug] Prefetching of DS records failed to update their diff --git a/bin/named/server.c b/bin/named/server.c index 65ea5718d8..bb122fb9c9 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1410,8 +1410,9 @@ configure_dyndb(const cfg_obj_t *dyndb, isc_mem_t *mctx, obj = cfg_tuple_get(dyndb, "parameters"); if (obj != NULL) - result = dns_dyndb_load(library, name, - cfg_obj_asstring(obj), mctx, dctx); + result = dns_dyndb_load(library, name, cfg_obj_asstring(obj), + cfg_obj_file(obj), cfg_obj_line(obj), + mctx, dctx); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, diff --git a/bin/tests/system/dyndb/driver/driver.c b/bin/tests/system/dyndb/driver/driver.c index 785c6a8d7f..bef6acb654 100644 --- a/bin/tests/system/dyndb/driver/driver.c +++ b/bin/tests/system/dyndb/driver/driver.c @@ -51,11 +51,15 @@ dns_dyndb_version_t dyndb_version; * @param[in] parameters User-defined parameters from dyndb section as one * string. The example above will have * params = "param1 param2"; + * @param[in] file The name of the file from which the parameters + * were read. + * @param[in] line The line number from which the parameters were read. * @param[out] instp Pointer to instance-specific data * (for one dyndb section). */ isc_result_t dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters, + const char *file, unsigned long line, const dns_dyndbctx_t *dctx, void **instp) { isc_result_t result; @@ -90,6 +94,10 @@ dyndb_init(isc_mem_t *mctx, const char *name, const char *parameters, if (result != ISC_R_SUCCESS) goto cleanup; + log_write(ISC_LOG_DEBUG(9), + "loading params for dyndb '%s' from %s:%lu", + name, file, line); + /* Finally, create the instance. */ CHECK(new_sample_instance(mctx, name, argc, argv, dctx, &sample_inst)); diff --git a/bin/tests/system/dyndb/tests.sh b/bin/tests/system/dyndb/tests.sh index d40c57a9af..f9f7c29d65 100644 --- a/bin/tests/system/dyndb/tests.sh +++ b/bin/tests/system/dyndb/tests.sh @@ -124,6 +124,11 @@ status=`expr $status + $ret` test_del test4.ipv6.example.nil. AAAA || ret=1 status=`expr $status + $ret` +newtest "I:checking parameter logging" +grep "loading params for dyndb 'sample' from .*named.conf:33" ns1/named.run > /dev/null || ret=1 +grep "loading params for dyndb 'sample2' from .*named.conf:34" ns1/named.run > /dev/null || ret=1 +status=`expr $status + $ret` + echo "I:checking dyndb still works after reload" $RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 reload 2>&1 | sed 's/^/I:ns1 /' diff --git a/lib/dns/dyndb.c b/lib/dns/dyndb.c index f4f78c6a7e..a477508632 100644 --- a/lib/dns/dyndb.c +++ b/lib/dns/dyndb.c @@ -348,7 +348,8 @@ unload_library(dyndb_implementation_t **impp) isc_result_t dns_dyndb_load(const char *libname, const char *name, const char *parameters, - isc_mem_t *mctx, const dns_dyndbctx_t *dctx) + const char *file, unsigned long line, isc_mem_t *mctx, + const dns_dyndbctx_t *dctx) { isc_result_t result; dyndb_implementation_t *implementation = NULL; @@ -365,8 +366,8 @@ dns_dyndb_load(const char *libname, const char *name, const char *parameters, CHECK(ISC_R_EXISTS); CHECK(load_library(mctx, libname, name, &implementation)); - CHECK(implementation->register_func(mctx, name, parameters, dctx, - &implementation->inst)); + CHECK(implementation->register_func(mctx, name, parameters, file, line, + dctx, &implementation->inst)); APPEND(dyndb_implementations, implementation, link); result = ISC_R_SUCCESS; diff --git a/lib/dns/include/dns/dyndb.h b/lib/dns/include/dns/dyndb.h index 3ac24f200c..66e820b0e4 100644 --- a/lib/dns/include/dns/dyndb.h +++ b/lib/dns/include/dns/dyndb.h @@ -57,6 +57,8 @@ struct dns_dyndbctx { typedef isc_result_t dns_dyndb_register_t(isc_mem_t *mctx, const char *name, const char *parameters, + const char *file, + unsigned long line, const dns_dyndbctx_t *dctx, void **instp); /*% @@ -95,7 +97,8 @@ typedef int dns_dyndb_version_t(unsigned int *flags); isc_result_t dns_dyndb_load(const char *libname, const char *name, const char *parameters, - isc_mem_t *mctx, const dns_dyndbctx_t *dctx); + const char *file, unsigned long line, isc_mem_t *mctx, + const dns_dyndbctx_t *dctx); /*% * Load a dyndb module. * @@ -104,6 +107,10 @@ dns_dyndb_load(const char *libname, const char *name, const char *parameters, * the instance handle to a list of dyndb instances so it can be cleaned * up later. * + * 'file' and 'line' can be used to indicate the name of the file and + * the line number from which the parameters were taken, so that logged + * error messages, if any, will display the correct locations. + * * Returns: *\li #ISC_R_SUCCESS *\li #ISC_R_NOMEMORY diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h index 1480037782..bc4b653d1a 100644 --- a/lib/isc/include/isc/lex.h +++ b/lib/isc/include/isc/lex.h @@ -405,6 +405,23 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name); * \li #ISC_R_NOTFOUND - there are no sources. */ +isc_result_t +isc_lex_setsourceline(isc_lex_t *lex, unsigned long line); +/*%< + * Assigns a new line number to the input source. This can be used + * when parsing a buffer that's been excerpted from the middle a file, + * allowing logged messages to display the correct line number, + * rather than the line number within the buffer. + * + * Requires: + * + * \li 'lex' is a valid lexer. + * + * Returns: + * \li #ISC_R_SUCCESS + * \li #ISC_R_NOTFOUND - there are no sources. + */ + isc_boolean_t isc_lex_isfile(isc_lex_t *lex); /*%< diff --git a/lib/isc/lex.c b/lib/isc/lex.c index 9a37986142..0f8ca532e3 100644 --- a/lib/isc/lex.c +++ b/lib/isc/lex.c @@ -973,7 +973,6 @@ isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r) source->ignored; } - char * isc_lex_getsourcename(isc_lex_t *lex) { inputsource *source; @@ -1000,7 +999,6 @@ isc_lex_getsourceline(isc_lex_t *lex) { return (source->line); } - isc_result_t isc_lex_setsourcename(isc_lex_t *lex, const char *name) { inputsource *source; @@ -1010,7 +1008,7 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { source = HEAD(lex->sources); if (source == NULL) - return(ISC_R_NOTFOUND); + return (ISC_R_NOTFOUND); newname = isc_mem_strdup(lex->mctx, name); if (newname == NULL) return (ISC_R_NOMEMORY); @@ -1019,6 +1017,20 @@ isc_lex_setsourcename(isc_lex_t *lex, const char *name) { return (ISC_R_SUCCESS); } +isc_result_t +isc_lex_setsourceline(isc_lex_t *lex, unsigned long line) { + inputsource *source; + + REQUIRE(VALID_LEX(lex)); + source = HEAD(lex->sources); + + if (source == NULL) + return (ISC_R_NOTFOUND); + + source->line = line; + return (ISC_R_SUCCESS); +} + isc_boolean_t isc_lex_isfile(isc_lex_t *lex) { inputsource *source; diff --git a/lib/isc/tests/lex_test.c b/lib/isc/tests/lex_test.c index c9756088fd..3462a75388 100644 --- a/lib/isc/tests/lex_test.c +++ b/lib/isc/tests/lex_test.c @@ -20,11 +20,11 @@ #include #include -ATF_TC(lex); -ATF_TC_HEAD(lex, tc) { +ATF_TC(lex_0xff); +ATF_TC_HEAD(lex_0xff, tc) { atf_tc_set_md_var(tc, "descr", "check handling of 0xff"); } -ATF_TC_BODY(lex, tc) { +ATF_TC_BODY(lex_0xff, tc) { isc_mem_t *mctx = NULL; isc_result_t result; isc_lex_t *lex = NULL; @@ -51,11 +51,58 @@ ATF_TC_BODY(lex, tc) { ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); } +ATF_TC(lex_setline); +ATF_TC_HEAD(lex_setline, tc) { + atf_tc_set_md_var(tc, "descr", "check setting of source line"); +} +ATF_TC_BODY(lex_setline, tc) { + isc_mem_t *mctx = NULL; + isc_result_t result; + isc_lex_t *lex = NULL; + unsigned char text[] = "text\nto\nbe\nprocessed\nby\nlexer"; + isc_buffer_t buf; + isc_token_t token; + unsigned long line; + int i; + + UNUSED(tc); + + result = isc_mem_create(0, 0, &mctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_lex_create(mctx, 1024, &lex); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + isc_buffer_init(&buf, &text[0], sizeof(text)); + isc_buffer_add(&buf, sizeof(text)); + + result = isc_lex_openbuffer(lex, &buf); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + result = isc_lex_setsourceline(lex, 100); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + for (i = 0; i < 6; i++) { + result = isc_lex_gettoken(lex, 0, &token); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + line = isc_lex_getsourceline(lex); + ATF_REQUIRE_EQ(line, 100U + i); + } + + result = isc_lex_gettoken(lex, 0, &token); + ATF_REQUIRE_EQ(result, ISC_R_EOF); + + line = isc_lex_getsourceline(lex); + ATF_REQUIRE_EQ(line, 105U); +} + /* * Main */ ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, lex); + ATF_TP_ADD_TC(tp, lex_0xff); + ATF_TP_ADD_TC(tp, lex_setline); return (atf_no_error()); }