From: Arran Cudbard-Bell Date: Tue, 13 Jun 2017 23:46:59 +0000 (-0400) Subject: Add lispy dynamic config parsing X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bc20056ee63d30db7103051f294f140994cf480;p=thirdparty%2Ffreeradius-server.git Add lispy dynamic config parsing --- diff --git a/src/include/cf_parse.h b/src/include/cf_parse.h index f01d292d5bf..19a42a63399 100644 --- a/src/include/cf_parse.h +++ b/src/include/cf_parse.h @@ -439,9 +439,18 @@ struct CONF_PARSER { */ int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, char const *name, unsigned int type, void *data, char const *dflt, FR_TOKEN dflt_quote); -int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER const *variables); -int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const *variables); +int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs); +int cf_section_parse_pass2(void *base, CONF_SECTION *cs); CONF_PARSER const *cf_section_parse_table(CONF_SECTION *cs); + +/* + * Runtime parse rules + */ +#define cf_section_rule_push(_cs, _rule) _cf_section_rule_push(_cs, _rule, __FILE__, __LINE__) +int _cf_section_rule_push(CONF_SECTION *cs, CONF_PARSER const *rule, char const *filename, int lineno); +#define cf_section_rules_push(_cs, _rule) _cf_section_rules_push(_cs, _rule, __FILE__, __LINE__) +int _cf_section_rules_push(CONF_SECTION *cs, CONF_PARSER const *rules, char const *filename, int lineno); + #ifdef __cplusplus } #endif diff --git a/src/include/cf_util.h b/src/include/cf_util.h index cf346f0a2e0..6975b2f3ed7 100644 --- a/src/include/cf_util.h +++ b/src/include/cf_util.h @@ -158,16 +158,16 @@ FR_TOKEN cf_pair_value_quote(CONF_PAIR const *pair); #define cf_data_find(_cf, _type, _name) _cf_data_find(CF_TO_ITEM(_cf), #_type, _name) CONF_DATA const *_cf_data_find(CONF_ITEM const *ci, char const *type, char const *name); -#define cf_data_find_next(_cf, _prev, _type, _name) _cf_data_find(CF_TO_ITEM(_cf), CF_TO_ITEM(_prev), #_type, _name) +#define cf_data_find_next(_cf, _prev, _type, _name) _cf_data_find_next(CF_TO_ITEM(_cf), CF_TO_ITEM(_prev), #_type, _name) CONF_DATA const *_cf_data_find_next(CONF_ITEM const *ci, CONF_ITEM const *prev, char const *type, char const *name); void *cf_data_value(CONF_DATA const *cd); -#define cf_data_add(_cf, _data, _name, _free) _cf_data_add(CF_TO_ITEM(_cf), _data, _name, _free) -CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool free); +#define cf_data_add(_cf, _data, _name, _free) _cf_data_add(CF_TO_ITEM(_cf), _data, _name, _free, __FILE__, __LINE__) +CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool free, char const *filename, int lineno); -#define cf_data_add_static(_cf, _data, _type, _name) _cf_data_add(CF_TO_ITEM(_cf), _data, #_type, _name) -CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name); +#define cf_data_add_static(_cf, _data, _type, _name) _cf_data_add_static(CF_TO_ITEM(_cf), _data, #_type, _name, __FILE__, __LINE__) +CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name, char const *filename, int lineno); #define cf_data_remove(_cf, _cd) _cf_data_remove(CF_TO_ITEM(_cf), _cd); void *_cf_data_remove(CONF_ITEM *ci, CONF_DATA const *_cd); diff --git a/src/main/cf_parse.c b/src/main/cf_parse.c index 7c38a2c939f..2d639191c18 100644 --- a/src/main/cf_parse.c +++ b/src/main/cf_parse.c @@ -709,66 +709,64 @@ int cf_pair_parse(TALLOC_CTX *ctx, CONF_SECTION *cs, * * @param cs The parent subsection. * @param base pointer or variable. - * @param variables that may have defaults in this config section. + * @param rule that may have defaults in this config section. + * @return + * - 0 on success. + * - -1 on failure. */ -static int cf_section_parse_init(CONF_SECTION *cs, void *base, CONF_PARSER const *variables) +static int cf_section_parse_init(CONF_SECTION *cs, void *base, CONF_PARSER const *rule) { - int i; - - for (i = 0; variables[i].name != NULL; i++) { - if ((FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION)) { - CONF_SECTION *subcs; + if ((FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION)) { + CONF_SECTION *subcs; - if (!variables[i].dflt) continue; - - subcs = cf_section_find(cs, variables[i].name, NULL); - if (!subcs && (variables[i].type & FR_TYPE_REQUIRED)) { - cf_log_err(cs, "Missing %s {} subsection", variables[i].name); - return -1; - } + if (!rule->dflt) return 0; - /* - * Set the is_set field for the subsection. - */ - if (variables[i].type & FR_TYPE_IS_SET) { - bool *is_set; + subcs = cf_section_find(cs, rule->name, NULL); + if (!subcs && (rule->type & FR_TYPE_REQUIRED)) { + cf_log_err(cs, "Missing %s {} subsection", rule->name); + return -1; + } - is_set = variables[i].data ? variables[i].is_set_ptr : - ((uint8_t *)base) + variables[i].is_set_offset; - if (is_set) *is_set = !!subcs; - } + /* + * Set the is_set field for the subsection. + */ + if (rule->type & FR_TYPE_IS_SET) { + bool *is_set; - /* - * If there's no subsection in the - * config, BUT the CONF_PARSER wants one, - * then create an empty one. This is so - * that we can track the strings, - * etc. allocated in the subsection. - */ - if (!subcs) { - subcs = cf_section_alloc(cs, variables[i].name, NULL); - if (!subcs) return -1; + is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset; + if (is_set) *is_set = !!subcs; + } - cf_item_add(cs, &(subcs->item)); - } + /* + * If there's no subsection in the + * config, BUT the CONF_PARSER wants one, + * then create an empty one. This is so + * that we can track the strings, + * etc. allocated in the subsection. + */ + if (!subcs) { + subcs = cf_section_alloc(cs, rule->name, NULL); + if (!subcs) return -1; - continue; + cf_item_add(cs, &(subcs->item)); } - if ((FR_BASE_TYPE(variables[i].type) != FR_TYPE_STRING) && - (variables[i].type != FR_TYPE_FILE_INPUT) && - (variables[i].type != FR_TYPE_FILE_OUTPUT)) { - continue; - } + return 0; + } - if (variables[i].data) { - *(char **) variables[i].data = NULL; - } else if (base) { - *(char **) (((char *)base) + variables[i].offset) = NULL; - } else { - continue; - } - } /* for all variables in the configuration section */ + if ((FR_BASE_TYPE(rule->type) != FR_TYPE_STRING) && + (rule->type != FR_TYPE_FILE_INPUT) && + (rule->type != FR_TYPE_FILE_OUTPUT)) { + return 0; + } + + if (rule->data) { + *(char **) rule->data = NULL; + } else if (base) { + *(char **) (((char *)base) + rule->offset) = NULL; + } else { + return 0; + } return 0; } @@ -813,7 +811,7 @@ static void cf_section_parse_warn(CONF_SECTION *cs) * @param[in] cs to parse. * @param[in] name of subsection to parse. * @param[in] type flags. - * @param[in] subcs_vars CONF_PARSER definitions for the subsection. + * @param[in] rules to push for subsections. * @param[in] subcs_size size of subsection structures to allocate. * @return * - 0 on success. @@ -821,10 +819,11 @@ static void cf_section_parse_warn(CONF_SECTION *cs) * - -2 if a deprecated #CONF_ITEM was found. */ static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, - char const *name, fr_type_t type, CONF_PARSER const *subcs_vars, size_t subcs_size) + char const *name, fr_type_t type, + CONF_PARSER const *rules, size_t subcs_size) { - CONF_SECTION *subcs; - int count, i, ret; + CONF_SECTION *subcs = NULL; + int count = 0, i, ret; uint8_t **array; rad_assert(type & FR_TYPE_SUBSECTION); @@ -838,18 +837,21 @@ static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, if (!(type & FR_TYPE_MULTI)) { uint8_t *buff; + if (cf_section_rules_push(subcs, rules) < 0) return -1; + /* * FIXME: We shouldn't allow nested structures like this. * Each subsection struct should be allocated separately so * we have a clean talloc hierarchy. */ - if (!subcs_size) return cf_section_parse(ctx, out, subcs, subcs_vars); + if (!subcs_size) return cf_section_parse(ctx, out, subcs); MEM(buff = talloc_array(ctx, uint8_t, subcs_size)); - ret = cf_section_parse(buff, buff, subcs, subcs_vars); + + ret = cf_section_parse(buff, buff, subcs); if (ret < 0) { talloc_free(buff); - return -1; + return ret; } *((uint8_t **)out) = buff; @@ -860,9 +862,7 @@ static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, /* * Handle the multi subsection case (which is harder) */ - for (subcs = cf_section_find(cs, name, NULL), count = 0; - subcs; - subcs = cf_section_find_next(cs, subcs, name, NULL), count++); + while ((subcs = cf_section_find_next(cs, subcs, name, NULL))) count++; /* * Allocate an array to hold the subsections @@ -884,7 +884,12 @@ static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, MEM(buff = talloc_zero_array(array, uint8_t, subcs_size)); array[i] = buff; - ret = cf_section_parse(buff, buff, subcs, subcs_vars); + if (cf_section_rules_push(subcs, rules) < 0) { + talloc_free(array); + return ret; + } + + ret = cf_section_parse(buff, buff, subcs); if (ret < 0) { talloc_free(array); return ret; @@ -902,28 +907,17 @@ static int cf_subsection_parse(TALLOC_CTX *ctx, void *out, CONF_SECTION *cs, * Usually the same as base, unless base is a nested struct. * @param[out] base pointer to a struct to fill with data. * @param[in] cs to parse. - * @param[in] variables mappings between struct fields and #CONF_ITEM s. * @return * - 0 on success. * - -1 on general error. * - -2 if a deprecated #CONF_ITEM was found. */ -int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER const *variables) +int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs) { int ret = 0; - int i; void *data; bool *is_set = NULL; - - /* - * Hack for partially parsed sections. - */ - if (!variables) { - cf_log_info(cs, "%.*s}", cs->depth, parse_spaces); - return 0; - } - - cs->variables = variables; /* this doesn't hurt anything */ + CONF_DATA const *rule_cd = NULL; if (!cs->name2) { cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces, cs->name1); @@ -931,29 +925,30 @@ int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces, cs->name1, cs->name2); } - /* - * Pre-allocate the config structure to hold default values - */ - if (cf_section_parse_init(cs, base, variables) < 0) return -1; + while ((rule_cd = cf_data_find_next(cs, rule_cd, CONF_PARSER, CF_IDENT_ANY))) { + CONF_PARSER *rule; + + rule = cf_data_value(rule_cd); + + /* + * Pre-allocate the config structure to hold default values + */ + if (cf_section_parse_init(cs, base, rule) < 0) return -1; - /* - * Handle the known configuration parameters. - */ - for (i = 0; variables[i].name != NULL; i++) { /* * Handle subsections specially */ - if (FR_BASE_TYPE(variables[i].type) == FR_TYPE_SUBSECTION) { - if (cf_subsection_parse(ctx, (uint8_t *)base + variables[i].offset, cs, - variables[i].name, variables[i].type, - variables[i].subcs, variables[i].subcs_size) < 0) goto finish; + if (FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION) { + if (cf_subsection_parse(ctx, (uint8_t *)base + rule->offset, cs, + rule->name, rule->type, + rule->subcs, rule->subcs_size) < 0) goto finish; continue; } /* else it's a CONF_PAIR */ - if (variables[i].data) { - data = variables[i].data; /* prefer this. */ + if (rule->data) { + data = rule->data; /* prefer this. */ } else if (base) { - data = ((uint8_t *)base) + variables[i].offset; + data = ((uint8_t *)base) + rule->offset; } else if (!rad_cond_assert(0)) { ret = -1; goto finish; @@ -963,16 +958,14 @@ int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER * Get pointer to where we need to write out * whether the pointer was set. */ - if (variables[i].type & FR_TYPE_IS_SET) { - is_set = variables[i].data ? variables[i].is_set_ptr : - ((uint8_t *)base) + variables[i].is_set_offset; + if (rule->type & FR_TYPE_IS_SET) { + is_set = rule->data ? rule->is_set_ptr : ((uint8_t *)base) + rule->is_set_offset; } /* * Parse the pair we found, or a default value. */ - ret = cf_pair_parse(ctx, cs, variables[i].name, variables[i].type, data, - variables[i].dflt, variables[i].quote); + ret = cf_pair_parse(ctx, cs, rule->name, rule->type, data, rule->dflt, rule->quote); switch (ret) { case 1: /* Used default (or not present) */ if (is_set) *is_set = false; @@ -987,30 +980,17 @@ int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs, CONF_PARSER goto finish; case -2: /* Deprecated CONF ITEM */ - if ((variables[i + 1].offset && (variables[i + 1].offset == variables[i].offset)) || - (variables[i + 1].data && (variables[i + 1].data == variables[i].data))) { - cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", variables[i].name, - variables[i + 1].name); + if (((rule + 1)->offset && ((rule + 1)->offset == rule->offset)) || + ((rule + 1)->data && ((rule + 1)->data == rule->data))) { + cf_log_err(&(cs->item), "Replace \"%s\" with \"%s\"", rule->name, + (rule + 1)->name); } goto finish; } - } /* for all variables in the configuration section */ - - /* - * Ensure we have a proper terminator, type so we catch - * missing terminators reliably - */ - rad_cond_assert(variables[i].type == conf_term.type); + } cs->base = base; - /* - * Hack for partially parsed sections. We don't print - * out the final "}", that will be printed out when the - * caller re-calls us with 'variable=NULL'. And, we don't warn about unused - */ - if (variables[i].offset == 1) return ret; - /* * Warn about items in the configuration which weren't * checked during parsing. @@ -1024,32 +1004,30 @@ finish: } /** Fixup xlat expansions and attributes - * - * @note Despite the name, this is really the second phase of #cf_pair_parse. * * @param[out] base start of structure to write #vp_tmpl_t s to. * @param[in] cs CONF_SECTION to fixup. - * @param[in] variables Array of CONF_PARSER structs to process. * @return * - 0 on success. * - -1 on failure (parse errors etc...). */ -int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const variables[]) +int cf_section_parse_pass2(void *base, CONF_SECTION *cs) { + CONF_DATA const *rule_cd = NULL; - int i; - - /* - * Handle the known configuration parameters. - */ - for (i = 0; variables[i].name != NULL; i++) { + while ((rule_cd = cf_data_find_next(cs, rule_cd, CONF_PARSER, CF_IDENT_ANY))) { bool attribute, multi, is_tmpl, is_xlat; CONF_PAIR *cp; + CONF_PARSER *rule; void *data; - char const *name = variables[i].name; - int type = variables[i].type; + char const *name; + int type; + + rule = cf_data_value(rule_cd); + name = rule->name; + type = rule->type; is_tmpl = (type & FR_TYPE_TMPL); is_xlat = (type & FR_TYPE_XLAT); attribute = (type & FR_TYPE_ATTRIBUTE); @@ -1074,24 +1052,22 @@ int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const varia size_t j, len; uint8_t **array; - array = (uint8_t **)((uint8_t *)base) + variables[i].offset; + array = (uint8_t **)((uint8_t *)base) + rule->offset; len = talloc_array_length(array); for (j = 0; j < len; j++) { - if (cf_section_parse_pass2(array[j], subcs, - (CONF_PARSER const *)variables[i].dflt) < 0) { + if (cf_section_parse_pass2(array[j], subcs) < 0) { return -1; } } continue; - } else if (variables[i].subcs_size) { - subcs_base = (*(uint8_t **)((uint8_t *)base) + variables[i].offset); + } else if (rule->subcs_size) { + subcs_base = (*(uint8_t **)((uint8_t *)base) + rule->offset); } else { - subcs_base = (uint8_t *)base + variables[i].offset; + subcs_base = (uint8_t *)base + rule->offset; } - if (cf_section_parse_pass2(subcs_base, subcs, - (CONF_PARSER const *)variables[i].dflt) < 0) return -1; + if (cf_section_parse_pass2(subcs_base, subcs) < 0) return -1; continue; } @@ -1106,8 +1082,8 @@ int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const varia /* * Figure out which data we need to fix. */ - data = variables[i].data; /* prefer this. */ - if (!data && base) data = ((char *)base) + variables[i].offset; + data = rule->data; /* prefer this. */ + if (!data && base) data = ((char *)base) + rule->offset; if (!data) continue; /* @@ -1118,7 +1094,7 @@ int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const varia * Ignore %{... in shared secrets. * They're never dynamically expanded. */ - if ((variables[i].type & FR_TYPE_SECRET) != 0) continue; + if ((rule->type & FR_TYPE_SECRET) != 0) continue; if (strstr(cp->value, "%{") != NULL) { cf_log_err(&cp->item, "Found dynamic expansion in string which " @@ -1239,14 +1215,72 @@ int cf_section_parse_pass2(void *base, CONF_SECTION *cs, CONF_PARSER const varia TALLOC_FREE(*out); *(vp_tmpl_t **)out = vpt; } - } /* for all variables in the configuration section */ + } return 0; } +/* + * Fixme? Swapout with an iterative API. + */ const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs) { if (!cs) return NULL; return cs->variables; } + +/** Add a single rule to a #CONF_SECTION + * + * @param[in] cs to add rules to. + * @param[in] rule to add. + * @return + * - 0 on success. + * - -1 if the rules added conflict. + */ +int _cf_section_rule_push(CONF_SECTION *cs, CONF_PARSER const *rule, char const *filename, int lineno) +{ + if (DEBUG_ENABLED4) { + cf_log_debug(cs, "Pushed parse rule to %s: %s %s", + cf_section_name1(cs), + rule->name, FR_BASE_TYPE(rule->type) & FR_TYPE_SUBSECTION ? "{}": ""); + } + + /* + * Qualifying with name prevents duplicate rules being added + * + * Fixme maybe?.. Can't have a section and pair with the same name. + */ + if (!_cf_data_add_static(CF_TO_ITEM(cs), rule, "CONF_PARSER", rule->name, filename, lineno)) { + cf_debug(cs); + return -1; + } + + return 0; +} + +/** Add an array of parse rules to a #CONF_SECTION + * + * @param[in] cs to add rules to. + * @param[in] rules to add. Last element should have NULL name field. + * @return + * - 0 on success. + * - -1 on failure. + */ +int _cf_section_rules_push(CONF_SECTION *cs, CONF_PARSER const *rules, char const *filename, int lineno) +{ + CONF_PARSER const *rule_p; + + for (rule_p = rules; rule_p->name; rule_p++) { + if (rule_p->type & FR_TYPE_DEPRECATED) continue; /* Skip deprecated */ + if (_cf_section_rule_push(cs, rule_p, filename, lineno) < 0) return -1; + } + + /* + * Ensure we have a proper terminator, type so we catch + * missing terminators reliably + */ + rad_cond_assert(rule_p->type == conf_term.type); + + return 0; +} diff --git a/src/main/cf_util.c b/src/main/cf_util.c index 382ab9529d0..a0824e51b6c 100644 --- a/src/main/cf_util.c +++ b/src/main/cf_util.c @@ -1347,13 +1347,17 @@ void *cf_data_value(CONF_DATA const *cd) * @param[in] data to add. * @param[in] name String identifier of the user data. * @param[in] do_free Function to free user data when the CONF_SECTION is freed. + * @param[in] filename Source file the #CONF_DATA was added in. + * @param[in] lineno the #CONF_DATA was added at. * @return * - #CONF_DATA - opaque handle to the stored data - on success. * - NULL error. */ -CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free) +CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, bool do_free, + char const *filename, int lineno) { CONF_DATA *cd; + CONF_DATA const *found; char const *type = NULL; if (!ci) return NULL; @@ -1363,8 +1367,10 @@ CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, /* * Already exists. Can't add it. */ - if (_cf_data_find(ci, type, name)) { - cf_log_err(ci, "Data of type %s with name %s already exists", type, name); + found = _cf_data_find(ci, type, name); + if (found) { + cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type, + name, found->item.filename, found->item.lineno); return NULL; } @@ -1374,6 +1380,8 @@ CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, return NULL; } cd->is_talloced = true; + cd->item.filename = filename; + cd->item.lineno = lineno; cf_item_add(ci, cd); @@ -1386,18 +1394,24 @@ CONF_DATA const *_cf_data_add(CONF_ITEM *ci, void const *data, char const *name, * @param[in] data to add. * @param[in] type identifier of the user data. * @param[in] name String identifier of the user data. + * @param[in] filename Source file the #CONF_DATA was added in. + * @param[in] lineno the #CONF_DATA was added at. * - #CONF_DATA - opaque handle to the stored data - on success. * - NULL error. */ -CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name) +CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const *type, char const *name, + char const *filename, int lineno) { CONF_DATA *cd; + CONF_DATA const *found; /* * Already exists. Can't add it. */ - if (_cf_data_find(ci, type, name)) { - cf_log_err(ci, "Data of type %s with name %s already exists", type, name); + found = _cf_data_find(ci, type, name); + if (found) { + cf_log_err(ci, "Data of type %s with name \"%s\" already exists. Existing data added %s[%i]", type, + name, found->item.filename, found->item.lineno); return NULL; } @@ -1407,6 +1421,8 @@ CONF_DATA const *_cf_data_add_static(CONF_ITEM *ci, void const *data, char const return NULL; } cd->is_talloced = false; + cd->item.filename = filename; + cd->item.lineno = lineno; cf_item_add(ci, cd); @@ -1587,7 +1603,7 @@ void _cf_log_info(CONF_ITEM const *ci, char const *fmt, ...) msg = talloc_vasprintf(NULL, fmt, ap); va_end(ap); - if (!ci || !ci->filename || !DEBUG_ENABLED3) { + if (!ci || !ci->filename || !DEBUG_ENABLED4) { INFO("%s", msg); } else { INFO("%s[%d]: %s", ci->filename, ci->lineno, msg); diff --git a/src/main/client.c b/src/main/client.c index 36c9d3895ba..f71a3a3376b 100644 --- a/src/main/client.c +++ b/src/main/client.c @@ -884,7 +884,9 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv c->cs = cs; memset(&cl_ipaddr, 0, sizeof(cl_ipaddr)); - if (cf_section_parse(c, c, cs, client_config) < 0) { + if (cf_section_rules_push(cs, client_config) < 0) return NULL; + + if (cf_section_parse(c, c, cs) < 0) { cf_log_err(cs, "Error parsing client section"); error: client_free(c); diff --git a/src/main/command.c b/src/main/command.c index 26ca46071e9..4f473565b05 100644 --- a/src/main/command.c +++ b/src/main/command.c @@ -3174,7 +3174,8 @@ static int command_socket_parse_unix(CONF_SECTION *cs, rad_listen_t *this) sock = this->data; talloc_set_destructor(sock, _command_socket_free); - if (cf_section_parse(sock, sock, cs, command_config) < 0) return -1; + if (cf_section_rules_push(cs, command_config) < 0) return -1; + if (cf_section_parse(sock, sock, cs) < 0) return -1; /* * Can't get uid or gid of connecting user, so can't do diff --git a/src/main/dl.c b/src/main/dl.c index e9dbef72a7c..603494a60c3 100644 --- a/src/main/dl.c +++ b/src/main/dl.c @@ -415,10 +415,14 @@ int dl_instance_data_alloc(void **data, TALLOC_CTX *ctx, dl_t const *module, CON } else { talloc_set_name(*data, "%s", module->common->inst_type); } - if (module->common->config && (cf_section_parse(*data, *data, cs, module->common->config) < 0)) { - cf_log_err(cs, "Invalid configuration for module \"%s\"", module->name); - talloc_free(*data); - return -1; + + if (module->common->config) { + if ((cf_section_rules_push(cs, module->common->config)) < 0 || + (cf_section_parse(*data, *data, cs) < 0)) { + cf_log_err(cs, "Invalid configuration for module \"%s\"", module->name); + talloc_free(*data); + return -1; + } } /* diff --git a/src/main/listen.c b/src/main/listen.c index 45b2e1bce41..78605473163 100644 --- a/src/main/listen.c +++ b/src/main/listen.c @@ -1395,13 +1395,16 @@ int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this) */ subcs = cf_section_find(cs, "performance", NULL); if (subcs) { - rcode = cf_section_parse(this, this, subcs, performance_config); + if (cf_section_rules_push(subcs, performance_config) < 0) return -1; + rcode = cf_section_parse(this, this, subcs); if (rcode < 0) return -1; } subcs = cf_section_find(cs, "limit", NULL); if (subcs) { - rcode = cf_section_parse(sock, sock, subcs, limit_config); + if (cf_section_rules_push(subcs, limit_config) < 0) return -1; + + rcode = cf_section_parse(sock, sock, subcs); if (rcode < 0) return -1; if (sock->max_rate && ((sock->max_rate < 10) || (sock->max_rate > 1000000))) { diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 472e8d3de6a..30046b57465 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -436,7 +436,13 @@ static int switch_users(CONF_SECTION *cs) */ if (rad_debug_lvl && (getuid() != 0)) return 1; - if (cf_section_parse(NULL, NULL, cs, bootstrap_config) < 0) { + if (cf_section_rules_push(cs, bootstrap_config) < 0) { + fprintf(stderr, "%s: Error: Failed pushing parse rules for user/group information.\n", + main_config.name); + return 0; + } + + if (cf_section_parse(NULL, NULL, cs) < 0) { fprintf(stderr, "%s: Error: Failed to parse user/group information.\n", main_config.name); return 0; @@ -800,7 +806,14 @@ do {\ * set it now. */ if (default_log.dst == L_DST_NULL) { - if (cf_section_parse(NULL, NULL, cs, startup_server_config) < 0) { + if (cf_section_rules_push(cs, startup_server_config) < 0) { + fprintf(stderr, "%s: Error: Failed pushing rules for log {} section.\n", + main_config.name); + cf_file_free(cs); + return -1; + } + + if (cf_section_parse(NULL, NULL, cs) < 0) { fprintf(stderr, "%s: Error: Failed to parse log{} section.\n", main_config.name); cf_file_free(cs); @@ -879,7 +892,8 @@ do {\ * This allows us to figure out where, relative to * radiusd.conf, the other configuration files exist. */ - if (cf_section_parse(NULL, NULL, cs, server_config) < 0) return -1; + if (cf_section_rules_push(cs, server_config) < 0) return -1; + if (cf_section_parse(NULL, NULL, cs) < 0) return -1; /* * We ignore colourization of output until after the diff --git a/src/main/modules.c b/src/main/modules.c index 52166de30b7..20415a81b07 100644 --- a/src/main/modules.c +++ b/src/main/modules.c @@ -653,10 +653,7 @@ static int _module_instantiate(void *instance, UNUSED void *ctx) * Now that ALL modules are instantiated, and ALL xlats * are defined, go compile the config items marked as XLAT. */ - if (inst->module->config && - (cf_section_parse_pass2(inst->data, inst->cs, inst->module->config) < 0)) { - return -1; - } + if (inst->module->config && (cf_section_parse_pass2(inst->data, inst->cs) < 0)) return -1; /* * Call the instantiate method, if any. diff --git a/src/main/pool.c b/src/main/pool.c index 103d740255b..8baeb619c84 100644 --- a/src/main/pool.c +++ b/src/main/pool.c @@ -1044,7 +1044,8 @@ fr_pool_t *fr_pool_init(TALLOC_CTX *ctx, memcpy(&mutable, &cs, sizeof(mutable)); - if (cf_section_parse(pool, pool, mutable, pool_config) < 0) { + if (cf_section_rules_push(mutable, pool_config) < 0) goto error; + if (cf_section_parse(pool, pool, mutable) < 0) { PERROR("Configuration parsing failed"); goto error; } diff --git a/src/main/radwho.c b/src/main/radwho.c index c35fe3cb3fc..cf0013e7544 100644 --- a/src/main/radwho.c +++ b/src/main/radwho.c @@ -345,7 +345,8 @@ int main(int argc, char **argv) exit(1); } - cf_section_parse(maincs, NULL, cs, module_config); + if (cf_section_rules_push(cs, module_config) < 0) exit(1); + cf_section_parse(maincs, NULL, cs); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; diff --git a/src/main/realms.c b/src/main/realms.c index 90c2506440a..6d381c1565e 100644 --- a/src/main/realms.c +++ b/src/main/realms.c @@ -623,7 +623,8 @@ home_server_t *home_server_afrom_cs(TALLOC_CTX *ctx, realm_config_t *rc, CONF_SE * Parse the configuration into the home server * struct. */ - if (cf_section_parse(home, home, cs, home_server_config) < 0) goto error; + if (cf_section_rules_push(cs, home_server_config) < 0) goto error; + if (cf_section_parse(home, home, cs) < 0) goto error; /* * It has an IP address, it must be a remote server. @@ -2123,7 +2124,8 @@ int realms_init(CONF_SECTION *config) #ifdef WITH_PROXY cs = cf_section_find(config, "proxy", NULL); if (cs) { - if (cf_section_parse(rc, rc, cs, proxy_config) < 0) { + if (cf_section_rules_push(cs, proxy_config) < 0) goto error; + if (cf_section_parse(rc, rc, cs) < 0) { ERROR("Failed parsing proxy section"); goto error; } diff --git a/src/main/threads.c b/src/main/threads.c index e542d020397..2ab00b6a729 100644 --- a/src/main/threads.c +++ b/src/main/threads.c @@ -787,7 +787,8 @@ int thread_pool_bootstrap(CONF_SECTION *cs, bool *spawn_workers) return 0; } - if (cf_section_parse(NULL, NULL, pool_cf, thread_config) < 0) return -1; + if (cf_section_rules_push(pool_cf, thread_config) < 0) return -1; + if (cf_section_parse(NULL, NULL, pool_cf) < 0) return -1; /* * Catch corner cases. diff --git a/src/main/tls/conf.c b/src/main/tls/conf.c index 7ed2649317c..2e6fd0e4d41 100644 --- a/src/main/tls/conf.c +++ b/src/main/tls/conf.c @@ -317,10 +317,12 @@ fr_tls_conf_t *tls_conf_parse_server(CONF_SECTION *cs) return conf; } + if (cf_section_rules_push(cs, tls_server_config) < 0) return NULL; + conf = tls_conf_alloc(cs); - if ((cf_section_parse(conf, conf, cs, tls_server_config) < 0) || - (cf_section_parse_pass2(conf, cs, tls_server_config) < 0)) { + if ((cf_section_parse(conf, conf, cs) < 0) || + (cf_section_parse_pass2(conf, cs) < 0)) { error: talloc_free(conf); return NULL; @@ -434,10 +436,12 @@ fr_tls_conf_t *tls_conf_parse_client(CONF_SECTION *cs) return conf; } + if (cf_section_rules_push(cs, tls_client_config) < 0) return NULL; + conf = tls_conf_alloc(cs); - if ((cf_section_parse(conf, conf, cs, tls_client_config) < 0) || - (cf_section_parse_pass2(conf, cs, tls_client_config) < 0)) { + if ((cf_section_parse(conf, conf, cs) < 0) || + (cf_section_parse_pass2(conf, cs) < 0)) { error: talloc_free(conf); return NULL; diff --git a/src/modules/proto_detail/proto_detail.c b/src/modules/proto_detail/proto_detail.c index d4b18bf1b35..ed50f4f027b 100644 --- a/src/modules/proto_detail/proto_detail.c +++ b/src/modules/proto_detail/proto_detail.c @@ -1037,7 +1037,9 @@ static int detail_parse(CONF_SECTION *cs, rad_listen_t *this) data = this->data; - rcode = cf_section_parse(data, data, cs, detail_config); + if (cf_section_rules_push(cs, detail_config) < 0) return -1; + + rcode = cf_section_parse(data, data, cs); if (rcode < 0) { cf_log_err(cs, "Failed parsing listen section"); return -1; diff --git a/src/modules/proto_ldap_sync/proto_ldap_sync.c b/src/modules/proto_ldap_sync/proto_ldap_sync.c index 7a8f3bbda19..839db20d7d7 100644 --- a/src/modules/proto_ldap_sync/proto_ldap_sync.c +++ b/src/modules/proto_ldap_sync/proto_ldap_sync.c @@ -1060,7 +1060,8 @@ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) return -1; } - ret = cf_section_parse(inst, inst, cs, module_config); + if (cf_section_rules_push(cs, module_config) < 0) return -1; + ret = cf_section_parse(inst, inst, cs); if (ret < 0) return ret; talloc_set_type(inst, proto_ldap_inst_t); diff --git a/src/modules/proto_radius/proto_radius.c b/src/modules/proto_radius/proto_radius.c index 247d7fe7cca..76ceb551c7c 100644 --- a/src/modules/proto_radius/proto_radius.c +++ b/src/modules/proto_radius/proto_radius.c @@ -301,8 +301,9 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION pr_config_t config; proto_radius_ctx_t *ctx; - if ((cf_section_parse(cs, &config, cs, mod_config) < 0) || - (cf_section_parse_pass2(&config, cs, mod_config) < 0)) { + if (cf_section_rules_push(cs, mod_config) < 0) return -1; + + if ((cf_section_parse(cs, &config, cs) < 0) || (cf_section_parse_pass2(&config, cs) < 0)) { cf_log_err(cs, "Failed parsing listen { ...}"); return -1; } @@ -343,11 +344,6 @@ static int open_listen(fr_schedule_t *handle, CONF_SECTION *server, CONF_SECTION return -1; } - /* - * Print out the final "}" for debugging. - */ - (void) cf_section_parse(cs, &config, cs, NULL); - return 0; } diff --git a/src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c b/src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c index 228ef89ffc8..fc5a4358a11 100644 --- a/src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c +++ b/src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c @@ -56,7 +56,8 @@ static int mod_instantiate(rlm_cache_config_t const *config, void *instance, CON buffer[0] = '\0'; - if (cf_section_parse(driver, driver, conf, driver_config) < 0) return -1; + if (cf_section_rules_push(conf, driver_config) < 0) return -1; + if (cf_section_parse(driver, driver, conf) < 0) return -1; snprintf(buffer, sizeof(buffer), "rlm_cache (%s)", config->name); diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index 6d1e9b72c70..5b39a28290f 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -1397,8 +1397,10 @@ static int parse_sub_section(rlm_ldap_t *inst, CONF_SECTION *parent, ldap_acct_s return 0; } + if (cf_section_rules_push(cs, acct_section_config) < 0) return -1; + *config = talloc_zero(inst, ldap_acct_section_t); - if (cf_section_parse(*config, *config, cs, acct_section_config) < 0) { + if (cf_section_parse(*config, *config, cs) < 0) { PERROR("rlm_ldap (%s) - Failed parsing configuration for section %s", inst->name, name); return -1; diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c index 5701f17ee7c..a2d853fe126 100644 --- a/src/modules/rlm_linelog/rlm_linelog.c +++ b/src/modules/rlm_linelog/rlm_linelog.c @@ -78,19 +78,19 @@ typedef struct linelog_net { /** linelog module instance */ typedef struct linelog_instance_t { - char const *name; //!< Module instance name. - fr_pool_t *pool; //!< Connection pool instance. + char const *name; //!< Module instance name. + fr_pool_t *pool; //!< Connection pool instance. - char const *delimiter; //!< Line termination string (usually \n). - size_t delimiter_len; //!< Length of line termination string. + char const *delimiter; //!< Line termination string (usually \n). + size_t delimiter_len; //!< Length of line termination string. - vp_tmpl_t *log_src; //!< Source of log messages. + vp_tmpl_t *log_src; //!< Source of log messages. - vp_tmpl_t *log_ref; //!< Path to a #CONF_PAIR (to use as the source of - ///< log messages). + vp_tmpl_t *log_ref; //!< Path to a #CONF_PAIR (to use as the source of + ///< log messages). linefr_log_dst_t log_dst; //!< Logging destination. - char const *log_dst_str; //!< Logging destination string. + char const *log_dst_str; //!< Logging destination string. struct { char const *facility; //!< Syslog facility string. diff --git a/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c b/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c index 5c7678ba638..10364a2142b 100644 --- a/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c +++ b/src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c @@ -1149,10 +1149,12 @@ static int driver_init(TALLOC_CTX *ctx, CONF_SECTION *conf, void **instance) *instance = NULL; + if (cf_section_rules_push(conf, redis_config) < 0) return -1; + this = talloc_zero(ctx, redis_driver_conf_t); if (!this) return -1; - ret = cf_section_parse(this, &this->conf, conf, redis_config); + ret = cf_section_parse(this, &this->conf, conf); if (ret < 0) { talloc_free(this); return -1; diff --git a/src/modules/rlm_rest/rlm_rest.c b/src/modules/rlm_rest/rlm_rest.c index 303d415a2ec..e42c70c5039 100644 --- a/src/modules/rlm_rest/rlm_rest.c +++ b/src/modules/rlm_rest/rlm_rest.c @@ -761,7 +761,8 @@ static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, CONF_PARSER return 0; } - if (cf_section_parse(inst, config, cs, config_items) < 0) { + if (cf_section_rules_push(cs, config_items) < 0) return -1; + if (cf_section_parse(inst, config, cs) < 0) { config->name = NULL; return -1; }