]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
make fr_cond_tokenize() take CONF_SECTION we're parsing
authorAlan T. DeKok <aland@freeradius.org>
Tue, 10 Sep 2019 20:13:50 +0000 (16:13 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 10 Sep 2019 20:30:19 +0000 (16:30 -0400)
which ends up being easier than the alternative.  That way
instead of passing a bunch of things around, we can just pass
a CONF_SECTION

src/bin/unit_test_attribute.c
src/lib/server/cf_file.c
src/lib/server/cf_util.c
src/lib/server/cond.h
src/lib/server/cond_tokenize.c

index 81eaa7c845ee1c6ebd45cde0f01b91473dd443f2..304c9be103840486948002f075bb4aea0b77c6f0 100644 (file)
@@ -73,6 +73,8 @@ static ssize_t xlat_test(UNUSED TALLOC_CTX *ctx, UNUSED char **out, UNUSED size_
 static char proto_name_prev[128];
 static dl_t            *dl;
 static dl_loader_t     *dl_loader;
+static const char      *process_filename;
+static int             process_lineno;
 
 /** Concatenate error stack
  */
@@ -539,31 +541,33 @@ static void parse_condition(fr_dict_t const *dict, char const *input, char *outp
        ssize_t dec_len;
        char const *error = NULL;
        fr_cond_t *cond;
-       CONF_SECTION *this;
+       CONF_SECTION *cs;
 
-       this = cf_section_alloc(NULL, NULL, "if", "condition");
-       if (!this) {
+       cs = cf_section_alloc(NULL, NULL, "if", "condition");
+       if (!cs) {
                snprintf(output, outlen, "ERROR out of memory");
                return;
        }
+       cf_filename_set(cs, process_filename);
+       cf_lineno_set(cs, process_lineno);
 
-       dec_len = fr_cond_tokenize(NULL, &cond, &error, dict, this, input, NULL, 0);
-       talloc_free(this);
+       dec_len = fr_cond_tokenize(cs, &cond, &error, dict, input);
        if (dec_len <= 0) {
+               talloc_free(cs);
                snprintf(output, outlen, "ERROR offset %d %s", (int) -dec_len, error);
                return;
        }
 
        input += dec_len;
        if (*input != '\0') {
-               talloc_free(cond);
+               talloc_free(cs);
                snprintf(output, outlen, "ERROR offset %d 'Too much text'", (int) dec_len);
                return;
        }
 
        cond_snprint(output, outlen, cond);
 
-       talloc_free(cond);
+       talloc_free(cs);
 }
 
 static void parse_xlat(fr_dict_t const *dict, char const *input, char *output, size_t outlen)
@@ -864,6 +868,7 @@ do { \
        lineno = 0;
        *output = '\0';
        data_len = 0;
+       process_filename = filename;
 
        while (fgets(buffer, sizeof(buffer), fp) != NULL) {
                char                    *p = strchr(buffer, '\n'), *q;
@@ -894,6 +899,7 @@ do { \
                fr_skip_whitespace(p);
                if (!*p) continue;
 
+               process_lineno = lineno;
                DEBUG2("%s[%d]: %s\n", filename, lineno, buffer);
 
                strlcpy(input, p, sizeof(input));
index d2febf883062dd01b2f9954a4cef383f685f9530..5650b0c64f63363e1d97a8cf0e976d782447088c 100644 (file)
@@ -1052,11 +1052,21 @@ static CONF_SECTION *process_if(CONF_SECTION *this, char const **ptr_p, char *bu
        cd = cf_data_find_in_parent(this, fr_dict_t **, "dictionary");
        if (cd) dict = *((fr_dict_t **)cf_data_value(cd));
 
+       /*
+        *      fr_cond_tokenize needs the current section, so we create it first.
+        */
+       css = cf_section_alloc(this, this, buff[1], buff[2]);
+       if (!css) {
+               ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno);
+               return NULL;
+       }
+       css->item.filename = filename;
+       css->item.lineno = *lineno;
+
        /*
         *      Skip (...) to find the {
         */
-       slen = fr_cond_tokenize(this, &cond, &error, dict,
-                               this, ptr, filename, *lineno);
+       slen = fr_cond_tokenize(css, &cond, &error, dict, ptr);
        if (slen < 0) {
                char *spaces, *text;
 
@@ -1069,7 +1079,7 @@ static CONF_SECTION *process_if(CONF_SECTION *this, char const **ptr_p, char *bu
 
                talloc_free(spaces);
                talloc_free(text);
-               talloc_free(cond);
+               talloc_free(css);
                return NULL;
        }
 
@@ -1079,7 +1089,7 @@ static CONF_SECTION *process_if(CONF_SECTION *this, char const **ptr_p, char *bu
         *      into.
         */
        if ((size_t) slen >= (talloc_array_length(buff[2]) - 1)) {
-               talloc_free(cond);
+               talloc_free(css);
                ERROR("%s[%d]: Condition is too large after \"%s\"", filename, *lineno, buff[1]);
                return NULL;
        }
@@ -1097,20 +1107,15 @@ static CONF_SECTION *process_if(CONF_SECTION *this, char const **ptr_p, char *bu
 
        if (*ptr != '{') {
                ERROR("%s[%d]: Expected '{' instead of %s", filename, *lineno, ptr);
-               talloc_free(cond);
+               talloc_free(css);
                return NULL;
        }
        ptr++;
 
-       css = cf_section_alloc(this, this, buff[1], buff[2]);
-       if (!css) {
-               ERROR("%s[%d]: Failed allocating memory for section", filename, *lineno);
-               talloc_free(cond);
-               return NULL;
-       }
-       css->item.filename = filename;
-       css->item.lineno = *lineno;
-
+       /*
+        *      Now that the CONF_SECTION and condition are OK, add
+        *      the condition to the CONF_SECTION.
+        */
        cf_data_add(css, cond, NULL, false);
        *ptr_p = ptr;
        return css;
index 1626518a31febafd5cd6f5967a6cbd9291e44d90..21f44dc7f946587f63a156e4ac1c16155f49d074 100644 (file)
@@ -742,6 +742,8 @@ CONF_SECTION *_cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent,
        cs->item.type = CONF_ITEM_SECTION;
        cs->item.parent = cf_section_to_item(parent);
        fr_cursor_init(&cs->item.cursor, &cs->item.child);
+       if (filename) cf_filename_set(cs, filename);
+       if (lineno) cf_lineno_set(cs, lineno);
 
        MEM(cs->name1 = talloc_typed_strdup(cs, name1));
        if (name2) {
@@ -750,9 +752,6 @@ CONF_SECTION *_cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent,
        }
        talloc_set_destructor(cs, _cf_section_free);
 
-       if (filename) cf_filename_set(cs, filename);
-       if (lineno) cf_lineno_set(cs, lineno);
-
        if (parent) {
                CONF_DATA const *cd;
                CONF_PARSER *rule;
index 0f2293d17539c83cabbb3bded9a7d55526dc8afc..ac7060fc05a30ff09910c64204c2bb7941f44e64 100644 (file)
@@ -89,10 +89,8 @@ struct fr_cond_t {
        fr_cond_t               *next;
 };
 
-ssize_t fr_cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **head, char const **error,
-                        fr_dict_t const *dict,
-                        CONF_SECTION *parent, char const *start,
-                        char const *filename, int lineno) CC_HINT(nonnull(1,2,3,4,5));
+ssize_t fr_cond_tokenize(CONF_SECTION *cs, fr_cond_t **head, char const **error,
+                        fr_dict_t const *dict, char const *start) CC_HINT(nonnull);
 size_t cond_snprint(char *buffer, size_t bufsize, fr_cond_t const *c);
 
 bool fr_cond_walk(fr_cond_t *head, bool (*callback)(fr_cond_t *cond, void *uctx), void *uctx);
index 3edfad0e90e456f2d2b7f7cd8ba031d876b2185f..139dd6ea31e36c47123ab1bee723e12b239f2b89 100644 (file)
@@ -575,10 +575,11 @@ static ssize_t cond_check_attrs(fr_cond_t *c, char const *start,
 static ssize_t cond_preparse(TALLOC_CTX *ctx, char const **out, size_t *outlen, char const *start,
                             FR_TOKEN *type, char const **error,
                             fr_dict_attr_t const **castda, bool require_regex,
-                            CONF_SECTION *parent, char const *filename, int lineno)
+                            CONF_SECTION *cs)
 {
        ssize_t slen, my_slen;
        char *p, *expanded;
+       int lineno;
        char buffer[8192];
 
        /*
@@ -596,7 +597,9 @@ static ssize_t cond_preparse(TALLOC_CTX *ctx, char const **out, size_t *outlen,
                return slen;
        }
 
-       if (!cf_expand_variables(filename, &lineno, parent, buffer, sizeof(buffer), start, slen, NULL)) {
+       lineno = cf_lineno(cs);
+       if (!cf_expand_variables(cf_filename(cs), &lineno, cf_item_to_section(cf_parent(cs)),
+                                buffer, sizeof(buffer), start, slen, NULL)) {
                *error = "Failed expanding configuration variable";
                return -1;
        }       
@@ -628,22 +631,21 @@ static ssize_t cond_preparse(TALLOC_CTX *ctx, char const **out, size_t *outlen,
 
 /** Tokenize a conditional check
  *
- *  @param[in] ctx     for talloc
+ *  @param[in] ctx     talloc ctx
+ *  @param[in] cs      our configuration section
  *  @param[out] pcond  pointer to the returned condition structure
  *  @param[out] error  the parse error (if any)
- *  @param[in] parent  the parent CONF_SECTION
  *  @param[in] start   the start of the string to process.  Should be "(..."
  *  @param[in] brace   look for a closing brace (how many deep we are)
  *  @param[in] rules   for attribute parsing
- * @param[in] filename filename we read the condition from
- * @param[in] lineno   line where we read the condition from
  *  @return
  *     - Length of the string skipped.
  *     - < 0 (the offset to the offending error) on error.
  */
-static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **error,
-                            CONF_SECTION *parent, char const *start, int brace,
-                            vp_tmpl_rules_t const *rules, char const *filename, int lineno)
+static ssize_t cond_tokenize(TALLOC_CTX *ctx, CONF_SECTION *cs,
+                            fr_cond_t **pcond, char const **error,
+                            char const *start, int brace,
+                            vp_tmpl_rules_t const *rules)
 {
        ssize_t                 slen, tlen;
        char const              *p = start;
@@ -699,8 +701,8 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
                 *      brackets.  Go recurse to get more.
                 */
                c->type = COND_TYPE_CHILD;
-               c->ci = cf_section_to_item(parent);
-               slen = cond_tokenize(c, &c->data.child, error, parent, p, brace + 1, rules, filename, lineno);
+               c->ci = cf_section_to_item(cs);
+               slen = cond_tokenize(c, cs, &c->data.child, error, p, brace + 1, rules);
                if (slen <= 0) return_SLEN;
 
                if (!c->data.child) {
@@ -722,7 +724,7 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
        /*
         *      Grab the LHS
         */
-       slen = cond_preparse(c, &lhs, &lhs_len, p, &lhs_type, error, &c->cast, false, parent, filename, lineno);
+       slen = cond_preparse(c, &lhs, &lhs_len, p, &lhs_type, error, &c->cast, false, cs);
        if (slen <= 0) {
                return_SLEN;
        }
@@ -786,7 +788,7 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
                }
 
                c->type = COND_TYPE_EXISTS;
-               c->ci = cf_section_to_item(parent);
+               c->ci = cf_section_to_item(cs);
 
                tlen = tmpl_afrom_str(c, &c->data.vpt,
                                      lhs, lhs_len, lhs_type, &parse_rules, true);
@@ -813,7 +815,7 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
                 *      The next thing should now be a comparison operator.
                 */
                c->type = COND_TYPE_MAP;
-               c->ci = cf_section_to_item(parent);
+               c->ci = cf_section_to_item(cs);
 
                switch (*p) {
                default:
@@ -902,7 +904,7 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
                        return_P("Expected text after operator");
                }
 
-               slen = cond_preparse(c, &rhs, &rhs_len, p, &rhs_type, error, NULL, regex, parent, filename, lineno);
+               slen = cond_preparse(c, &rhs, &rhs_len, p, &rhs_type, error, NULL, regex, cs);
                if (slen <= 0) {
                        return_SLEN;
                }
@@ -1039,9 +1041,9 @@ static ssize_t cond_tokenize(TALLOC_CTX *ctx, fr_cond_t **pcond, char const **er
 #endif
 
                /*
-                *      Save the parent for later.
+                *      Save the current config section for later.
                 */
-               c->data.map->ci = cf_section_to_item(parent);
+               c->data.map->ci = cf_section_to_item(cs);
 
                /*
                 *      We cannot compare lists to anything.
@@ -1132,7 +1134,7 @@ closing_brace:
        /*
         *      May still be looking for a closing brace.
         */
-       slen = cond_tokenize(c, &c->next, error, parent, p, brace, rules, filename, lineno);
+       slen = cond_tokenize(c, cs, &c->next, error, p, brace, rules);
        if (slen <= 0) {
        return_slen:
                talloc_free(c);
@@ -1575,26 +1577,20 @@ done:
 
 /** Tokenize a conditional check
  *
- * @param[in] ctx      for talloc
+ * @param[in] cs       current CONF_SECTION and talloc ctx
  * @param[out] head    the parsed condition structure
  * @param[out] error   the parse error (if any)
  * @param[in] dict     dictionary to resolve attributes in.
- * @param[in] parent   the parent CONF_SECTION
  * @param[in] start    the start of the string to process.  Should be "(..."
- * @param[in] filename filename we read the condition from
- * @param[in] lineno   line where we read the condition from
  * @return
  *     - Length of the string skipped.
  *     - < 0 (the offset to the offending error) on error.
  */
-ssize_t fr_cond_tokenize(TALLOC_CTX *ctx,
+ssize_t fr_cond_tokenize(CONF_SECTION *cs,
                         fr_cond_t **head, char const **error,
-                        fr_dict_t const *dict,
-                        CONF_SECTION *parent, char const *start,
-                        char const *filename, int lineno)
+                        fr_dict_t const *dict, char const *start)
 {
-       return cond_tokenize(ctx, head, error, parent, start, 0, &(vp_tmpl_rules_t){ .dict_def = dict },
-                            filename, lineno);
+       return cond_tokenize(cs, cs, head, error, start, 0, &(vp_tmpl_rules_t){ .dict_def = dict });
 }
 
 /*