]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add lispy dynamic config parsing
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 13 Jun 2017 23:46:59 +0000 (19:46 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 13 Jun 2017 23:46:59 +0000 (19:46 -0400)
23 files changed:
src/include/cf_parse.h
src/include/cf_util.h
src/main/cf_parse.c
src/main/cf_util.c
src/main/client.c
src/main/command.c
src/main/dl.c
src/main/listen.c
src/main/mainconfig.c
src/main/modules.c
src/main/pool.c
src/main/radwho.c
src/main/realms.c
src/main/threads.c
src/main/tls/conf.c
src/modules/proto_detail/proto_detail.c
src/modules/proto_ldap_sync/proto_ldap_sync.c
src/modules/proto_radius/proto_radius.c
src/modules/rlm_cache/drivers/rlm_cache_redis/rlm_cache_redis.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_redis_ippool/rlm_redis_ippool_tool.c
src/modules/rlm_rest/rlm_rest.c

index f01d292d5bf1c0247f235ac1c369d9b522855350..19a42a63399f387d755cdf4a802b5d965f78c4a9 100644 (file)
@@ -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
index cf346f0a2e05a93c3177b96b55821cc0b7901354..6975b2f3ed7dce5822af38682e018d4184da65e3 100644 (file)
@@ -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);
index 7c38a2c939f59734175bfa93d3fe83337d0767fa..2d639191c180868eb4179fbdb96067c5a3eaf3ae 100644 (file)
@@ -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;
+}
index 382ab9529d01d4c360659296e07b8dd157155282..a0824e51b6cb8e63d1a506cc1285285db670fcc4 100644 (file)
@@ -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);
index 36c9d3895ba8f6919ea401450f7d33d7d5428d43..f71a3a3376bf6ffecf3809705bfcdd2cf1f43da8 100644 (file)
@@ -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);
index 26ca46071e951657cb738876d6c5a2c7f7e68ee3..4f473565b050e733b8a80c864f4615745ff3d4e2 100644 (file)
@@ -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
index e9dbef72a7cb1999606b81938ba08b17376c7aa3..603494a60c37f2c2901b2e7326cd0d74a52dbfd4 100644 (file)
@@ -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;
+               }
        }
 
        /*
index 45b2e1bce411af49661fa4110451f5c8a7369345..78605473163528fb2cd5317e49d27471ebec0714 100644 (file)
@@ -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))) {
index 472e8d3de6ae7facc3792b2a862e9dd610da1586..30046b574657c8f57deadaffba8571f13c45c762 100644 (file)
@@ -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
index 52166de30b7fafa9d4f3eecf854b7075c1b60c4c..20415a81b07ae6e346be8757e58d717ab2f3ccc7 100644 (file)
@@ -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.
index 103d740255b9f4a0e3581363f7a7bdd9358b923a..8baeb619c849f39b519bdb41abf2286cad843256 100644 (file)
@@ -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;
                }
index c35fe3cb3fccad0ecae812ff47b2ffdf599b0d04..cf0013e7544ee636673be13c525e029a851591cb 100644 (file)
@@ -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;
index 90c2506440abc50c1c21607fc72a05b813c631ee..6d381c1565e772b8970989966baed630e6f79807 100644 (file)
@@ -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;
                }
index e542d0203976fc823cee7c75ba1ff6299cc20765..2ab00b6a7293ce84e95ed47fe645bca0c696f599 100644 (file)
@@ -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.
index 7ed2649317c0133c592327510d70435e9aeaf585..2e6fd0e4d41bb90c0b841f1f8d4b5a1452b8590f 100644 (file)
@@ -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;
index d4b18bf1b35e5b844cfd8fa191f799e553f93017..ed50f4f027b6678a68e5c24a224c8902d3185b07 100644 (file)
@@ -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;
index 7a8f3bbda191138e746c70267e2b7afab738b894..839db20d7d75f506688301b63c86bd8e7dd383dc 100644 (file)
@@ -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);
index 247d7fe7cca4f26673f4e36d2ff77b8a58c8c782..76ceb551c7c52c0eb0f32b47cd208819d6865692 100644 (file)
@@ -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;
 }
 
index 228ef89ffc8da41814eee18d0bc9df5d12a6e3bd..fc5a4358a11bebb58b8390562929c4ee405f884f 100644 (file)
@@ -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);
 
index 6d1e9b72c704ac21b5061a5bfcfa55b5524c3a48..5b39a28290f1361c2d06d33d622d11b7cfd46c0b 100644 (file)
@@ -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;
index 5701f17ee7c2805f7b5d1bdb658f5856d62114d4..a2d853fe126f4394fc58bdbc041400558b70a495 100644 (file)
@@ -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.
index 5c7678ba6387f53553096e53ec74a5f66f6d715f..10364a2142b46f09160e878d5c13d67a96a5bd8d 100644 (file)
@@ -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;
index 303d415a2eced43d807a3c079fca990621b417e0..e42c70c503941ffaf190232eaccf0933bd518210 100644 (file)
@@ -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;
        }