Expose fr_cond_t, but don't use it (yet)
authorAlan T. DeKok <aland@freeradius.org>
Thu, 18 Apr 2013 14:34:57 +0000 (10:34 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 19 Apr 2013 15:03:05 +0000 (11:03 -0400)
src/include/parser.h
src/main/conffile.c
src/main/modcall.c
src/main/parser.c
src/main/radattr.c

index 9e45620..97b5230 100644 (file)
@@ -28,7 +28,39 @@ RCSIDH(parser_h, "$Id$");
 extern "C" {
 #endif
 
-ssize_t fr_condition_tokenize(const char *start, const char **error);
+typedef struct fr_cond_t fr_cond_t;
+
+typedef enum cond_op_t {
+       COND_NONE = 0,
+       COND_TRUE,
+       COND_NOT = '!',
+       COND_AND = '&',
+       COND_OR = '|'
+} cond_op_t;
+
+
+/*
+ *     Allow for the following structures:
+ *
+ *     FOO                     no OP, RHS is NULL
+ *     FOO OP BAR
+ *     (COND)                  no LHS/RHS, child is COND, child OP is TRUE
+ *     (!(COND))               no LHS/RHS, child is COND, child OP is NOT
+ *     (COND1 OP COND2)        no LHS/RHS, next is COND2, next OP is OP
+ */
+struct fr_cond_t {
+       char            *lhs;
+       char            *rhs;
+       FR_TOKEN        op;
+       int             regex_i;
+
+       cond_op_t       next_op;
+       fr_cond_t       *next;
+       cond_op_t       child_op;
+       fr_cond_t       *child;
+};
+
+ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, const char *start, fr_cond_t **head, const char **error);
 
 /*
  *     In xlat.c for now
index 6b821aa..086414a 100644 (file)
@@ -1247,6 +1247,7 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
        int spaces = FALSE;
        char *cbuf = buf;
        size_t len;
+       fr_cond_t *cond = NULL;
 
        this = current;         /* add items here */
 
@@ -1579,7 +1580,7 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
                                if (!server) goto invalid_location;
                        }
                        
-                       slen = fr_condition_tokenize(ptr, &error);
+                       slen = fr_condition_tokenize(this, ptr, &cond, &error);
                        if (p) *p = '{';
 
                        if (slen < 0) {
@@ -1603,7 +1604,8 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
                        }
 
                        if ((size_t) slen >= (sizeof(buf2) - 1)) {
-                               ERROR("%s[%d]: Condition is too large after \"%s\"",
+                               talloc_free(cond);
+                               DEBUGE("%s[%d]: Condition is too large after \"%s\"",
                                       filename, *lineno, buf1);
                                return -1;
                        }
@@ -1614,7 +1616,8 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
                        t2 = T_BARE_WORD;
                        
                        if (gettoken(&ptr, buf3, sizeof(buf3)) != T_LCBRACE) {
-                               ERROR("%s[%d]: Expected '{'",
+                               talloc_free(cond);
+                               DEBUGE("%s[%d]: Expected '{'",
                                       filename, *lineno);
                                return -1;
                        }
@@ -1711,7 +1714,10 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
 
                case T_LCBRACE:
                section_alloc:
-                       if (seen_too_much(filename, *lineno, ptr)) return -1;
+                       if (seen_too_much(filename, *lineno, ptr)) {
+                               if (cond) talloc_free(cond);
+                               return -1;
+                       }
 
                        css = cf_section_alloc(this, buf1,
                                               t2 == T_LCBRACE ? NULL : buf2);
@@ -1724,6 +1730,11 @@ static int cf_section_read(const char *filename, int *lineno, FILE *fp,
                        css->item.filename = filename;
                        css->item.lineno = *lineno;
 
+                       if (cond) {
+                               cf_data_add_internal(css, "if", cond, NULL, FALSE);
+                               cond = NULL; /* eaten by the above line */
+                       }
+
                        /*
                         *      The current section is now the child section.
                         */
index c9855bb..9b500bf 100644 (file)
@@ -25,6 +25,7 @@ RCSID("$Id$")
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modpriv.h>
 #include <freeradius-devel/modcall.h>
+#include <freeradius-devel/parser.h>
 #include <freeradius-devel/rad_assert.h>
 
 
@@ -67,7 +68,8 @@ typedef struct {
        int grouptype;  /* after mc */
        modcallable *children;
        CONF_SECTION *cs;
-       value_pair_map_t *map;
+       value_pair_map_t *map;  /* update */
+       const fr_cond_t *cond;  /* if/elsif */
 } modgroup;
 
 typedef struct {
@@ -458,6 +460,10 @@ int modcall(int component, modcallable *c, REQUEST *request)
                if ((child->type == MOD_IF) || (child->type == MOD_ELSIF)) {
                        int condition = TRUE;
                        const char *p = child->name;
+                       modgroup *g;
+
+                       g = mod_callabletogroup(child);
+                       rad_assert(g->cond != NULL);
 
                        RDEBUG2("%.*s? %s %s",
                               stack.pointer + 1, modcall_spaces,
@@ -1683,9 +1689,6 @@ static modcallable *do_compile_modsingle(modcallable *parent,
                                         int grouptype,
                                         const char **modname)
 {
-#ifdef WITH_UNLANG
-       int result;
-#endif
        const char *modrefname;
        modsingle *single;
        modcallable *csingle;
@@ -1759,6 +1762,8 @@ static modcallable *do_compile_modsingle(modcallable *parent,
 
 #ifdef WITH_UNLANG
                } else  if (strcmp(modrefname, "if") == 0) {
+                       modgroup *g;
+
                        if (!cf_section_name2(cs)) {
                                cf_log_err(ci, "'if' without condition.");
                                return NULL;
@@ -1770,17 +1775,17 @@ static modcallable *do_compile_modsingle(modcallable *parent,
                                                     grouptype);
                        if (!csingle) return NULL;
                        csingle->type = MOD_IF;
-
-                       if (!radius_evaluate_condition(NULL, 0, 0, modname,
-                                                      FALSE, &result)) {
-                               modcallable_free(&csingle);
-                               return NULL;
-                       }
                        *modname = name2;
 
+                       g = mod_callabletogroup(csingle);
+                       g->cond = cf_data_find(g->cs, "if");
+                       rad_assert(g->cond != NULL);
+
                        return csingle;
 
                } else  if (strcmp(modrefname, "elsif") == 0) {
+                       modgroup *g;
+
                        if (parent &&
                            ((parent->type == MOD_LOAD_BALANCE) ||
                             (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
@@ -1799,14 +1804,12 @@ static modcallable *do_compile_modsingle(modcallable *parent,
                                                     grouptype);
                        if (!csingle) return NULL;
                        csingle->type = MOD_ELSIF;
-
-                       if (!radius_evaluate_condition(NULL, 0, 0, modname,
-                                                      FALSE, &result)) {
-                               modcallable_free(&csingle);
-                               return NULL;
-                       }
                        *modname = name2;
 
+                       g = mod_callabletogroup(csingle);
+                       g->cond = cf_data_find(g->cs, "if");
+                       rad_assert(g->cond != NULL);
+
                        return csingle;
 
                } else  if (strcmp(modrefname, "else") == 0) {
@@ -2176,6 +2179,7 @@ static modcallable *do_compile_modgroup(modcallable *parent,
        memset(g, 0, sizeof(*g));
        g->grouptype = grouptype;
        g->children = NULL;
+       g->cs = cs;
 
        c = mod_grouptocallable(g);
        c->parent = parent;
index a49ddb0..f52e561 100644 (file)
@@ -43,40 +43,8 @@ RCSID("$Id$")
 #endif
 #endif
 
-typedef enum cond_op_t {
-       COND_NONE = 0,
-       COND_TRUE,
-       COND_NOT = '!',
-       COND_AND = '&',
-       COND_OR = '|'
-} cond_op_t;
-
-
-typedef struct cond_t cond_t;
-
-/*
- *     Allow for the following structures:
- *
- *     FOO                     no OP, RHS is NULL
- *     FOO OP BAR
- *     (COND)                  no LHS/RHS, child is COND, child OP is TRUE
- *     (!(COND))               no LHS/RHS, child is COND, child OP is NOT
- *     (COND1 OP COND2)        no LHS/RHS, next is COND2, next OP is OP
- */
-struct cond_t {
-       char            *lhs;
-       char            *rhs;
-       FR_TOKEN        op;
-       int             regex_i;
-
-       cond_op_t       next_op;
-       cond_t          *next;
-       cond_op_t       child_op;
-       cond_t          *child;
-};
-
-DIAG_OFF(unused-function)
-static void cond_debug(const cond_t *c)
+W_UNUSEDDEC_OFF
+static void cond_debug(const fr_cond_t *c)
 {
 
 next:
@@ -233,15 +201,15 @@ static ssize_t condition_tokenize_word(TALLOC_CTX *ctx, const char *start, char
  *  @param[out] error the parse error (if any)
  *  @return length of the string skipped, or when negative, the offset to the offending error
  */
-static ssize_t condition_tokenize(TALLOC_CTX *ctx, const char *start, int brace, cond_t **pcond, const char **error)
+static ssize_t condition_tokenize(TALLOC_CTX *ctx, const char *start, int brace, fr_cond_t **pcond, const char **error)
 {
        ssize_t slen;
        const char *p = start;
-       cond_t *c;
+       fr_cond_t *c;
 
        COND_DEBUG("START %s", p);
 
-       c = talloc_zero(ctx, cond_t);
+       c = talloc_zero(ctx, fr_cond_t);
 
        rad_assert(c != NULL);
 
@@ -377,6 +345,14 @@ static ssize_t condition_tokenize(TALLOC_CTX *ctx, const char *start, int brace,
                                p += 2;
 
                                } else if (p[1] == '*') {
+                                       /*
+                                        *      FOO !* BAR
+                                        *
+                                        *      is really !(FOO)
+                                        *
+                                        *      FIXME: we should
+                                        *      really re-write it...
+                                        */
                                        c->op = T_OP_CMP_FALSE;
                                        p += 2;
 
@@ -553,25 +529,13 @@ done:
 
 /** Tokenize a conditional check
  *
+ *  @param[in] ctx for talloc
  *  @param[in] start the start of the string to process.  Should be "(..."
+ *  @param[out] head the parsed condition structure
  *  @param[out] error the parse error (if any)
  *  @return length of the string skipped, or when negative, the offset to the offending error
  */
-ssize_t fr_condition_tokenize(const char *start, const char **error)
+ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, const char *start, fr_cond_t **head, const char **error)
 {
-       ssize_t slen;
-       cond_t *c = NULL;
-
-       slen = condition_tokenize(NULL, start, FALSE, &c, error);
-       if (slen <= 0) return slen;
-
-       if (!c) {
-               COND_DEBUG("RETURN %d", __LINE__);
-               *error = "Empty condition is invalid";
-               return -1;
-       }
-
-       talloc_free(c);
-
-       return slen;
+       return condition_tokenize(ctx, start, FALSE, head, error);
 }
index 7c04631..bc6c94c 100644 (file)
@@ -542,13 +542,16 @@ static void parse_condition(const char *input, char *output, size_t outlen)
 {
        ssize_t slen;
        const char *error = NULL;
+       fr_cond_t *cond;
 
-       slen = fr_condition_tokenize(input, &error);
+       slen = fr_condition_tokenize(NULL, input, &cond, &error);
        if (slen <= 0) {
                snprintf(output, outlen, "ERROR offset %d '%s'", (int) -slen, error);
                return;
        }
 
+       talloc_free(cond);
+
        input += slen;
        if (*input != '\0') {
                snprintf(output, outlen, "ERROR offset %d 'Too much text'", (int) slen);