* Right now, the only accepted syntax is :
* <subject> [<value>...]
*/
-struct acl_expr *parse_acl_expr(const char **args);
+struct acl_expr *parse_acl_expr(const char **args, char **err);
/* Purge everything in the acl <acl>, then return <acl>. */
struct acl *prune_acl(struct acl *acl);
*
* args syntax: <aclname> <acl_expr>
*/
-struct acl *parse_acl(const char **args, struct list *known_acl);
+struct acl *parse_acl(const char **args, struct list *known_acl, char **err);
/* Purge everything in the acl_cond <cond>, then return <cond>. */
struct acl_cond *prune_acl_cond(struct acl_cond *cond);
* known ACLs passed in <known_acl>. The new condition is returned (or NULL in
* case of low memory). Supports multiple conditions separated by "or".
*/
-struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol);
+struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol, char **err);
/* Builds an ACL condition starting at the if/unless keyword. The complete
* condition is returned. NULL is returned in case of error or if the first
* word is neither "if" nor "unless". It automatically sets the file name and
* the line number in the condition for better error reporting, and adds the
- * ACL requirements to the proxy's acl_requires.
+ * ACL requirements to the proxy's acl_requires. If <err> is not NULL, it will
+ * be set to an error message upon errors, that the caller will have to free.
*/
-struct acl_cond *build_acl_cond(const char *file, int line, struct proxy *px, const char **args);
+struct acl_cond *build_acl_cond(const char *file, int line, struct proxy *px, const char **args, char **err);
/* Execute condition <cond> and return either ACL_PAT_FAIL, ACL_PAT_MISS or
* ACL_PAT_PASS depending on the test results. This function only computes the
return ret;
}
-/* Parse an ACL expression starting at <args>[0], and return it.
+/* Parse an ACL expression starting at <args>[0], and return it. If <err> is
+ * not NULL, it will be filled with a pointer to an error message in case of
+ * error. This pointer must be freeable or NULL.
+ *
* Right now, the only accepted syntax is :
* <subject> [<value>...]
*/
-struct acl_expr *parse_acl_expr(const char **args)
+struct acl_expr *parse_acl_expr(const char **args, char **err)
{
__label__ out_return, out_free_expr, out_free_pattern;
struct acl_expr *expr;
const char *arg;
aclkw = find_acl_kw(args[0]);
- if (!aclkw || !aclkw->parse)
+ if (!aclkw || !aclkw->parse) {
+ if (err)
+ memprintf(err, "unknown ACL keyword '%s'", *args);
goto out_return;
+ }
expr = (struct acl_expr *)calloc(1, sizeof(*expr));
- if (!expr)
+ if (!expr) {
+ if (err)
+ memprintf(err, "out of memory when parsing ACL expression");
goto out_return;
+ }
expr->kw = aclkw;
aclkw->use_cnt++;
/* there are 0 or more arguments in the form "subject(arg[,arg]*)" */
arg++;
end = strchr(arg, ')');
- if (!end)
+ if (!end) {
+ if (err)
+ memprintf(err, "missing closing ')' after arguments to ACL keyword '%s'", aclkw->kw);
goto out_free_expr;
+ }
/* Parse the arguments. Note that currently we have no way to
* report parsing errors, hence the NULL in the error pointers.
* missing.
*/
nbargs = make_arg_list(arg, end - arg, aclkw->arg_mask, &expr->args,
- NULL, NULL, NULL);
- if (nbargs < 0)
+ err, NULL, NULL);
+ if (nbargs < 0) {
+ /* note that make_arg_list will have set <err> here */
+ if (err)
+ memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
goto out_free_expr;
+ }
- if (aclkw->val_args && !aclkw->val_args(expr->args, NULL))
- goto out_free_expr; /* invalid keyword argument */
+ if (aclkw->val_args && !aclkw->val_args(expr->args, err)) {
+ /* invalid keyword argument, error must have been
+ * set by val_args().
+ */
+ if (err)
+ memprintf(err, "in argument to '%s', %s", aclkw->kw, *err);
+ goto out_free_expr;
+ }
}
else if (ARGM(aclkw->arg_mask) == 1) {
int type = (aclkw->arg_mask >> 4) & 15;
* an empty one so that acl_find_targets() resolves it as
* the current one later.
*/
- if (type != ARGT_FE && type != ARGT_BE && type != ARGT_TAB)
+ if (type != ARGT_FE && type != ARGT_BE && type != ARGT_TAB) {
+ if (err)
+ memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->arg_mask));
goto out_free_expr;
+ }
/* Build an arg list containing the type as an empty string
* and the usual STOP.
}
else if (ARGM(aclkw->arg_mask)) {
/* there were some mandatory arguments */
+ if (err)
+ memprintf(err, "ACL keyword '%s' expects %d arguments", aclkw->kw, ARGM(aclkw->arg_mask));
goto out_free_expr;
}
}
else {
if (arg) {
/* no argument expected */
+ if (err)
+ memprintf(err, "ACL keyword '%s' takes no argument", aclkw->kw);
goto out_free_expr;
}
}
if ((*args)[1] == 'i')
patflags |= ACL_PAT_F_IGNORE_CASE;
else if ((*args)[1] == 'f') {
- if (!acl_read_patterns_from_file(aclkw, expr, args[1], patflags | ACL_PAT_F_FROM_FILE))
+ if (!acl_read_patterns_from_file(aclkw, expr, args[1], patflags | ACL_PAT_F_FROM_FILE)) {
+ if (err)
+ memprintf(err, "failed to load some ACL patterns from file '%s'", args[1]);
goto out_free_expr;
+ }
args++;
}
else if ((*args)[1] == '-') {
while (**args) {
int ret;
pattern = (struct acl_pattern *)calloc(1, sizeof(*pattern));
- if (!pattern)
+ if (!pattern) {
+ if (err)
+ memprintf(err, "out of memory when parsing ACL pattern");
goto out_free_expr;
+ }
pattern->flags = patflags;
ret = aclkw->parse(args, pattern, &opaque);
- if (!ret)
+ if (!ret) {
+ if (err)
+ memprintf(err, "failed to parse some ACL patterns");
goto out_free_pattern;
+ }
LIST_ADDQ(&expr->patterns, &pattern->list);
args += ret;
}
/* Parse an ACL with the name starting at <args>[0], and with a list of already
* known ACLs in <acl>. If the ACL was not in the list, it will be added.
* A pointer to that ACL is returned. If the ACL has an empty name, then it's
- * an anonymous one and it won't be merged with any other one.
+ * an anonymous one and it won't be merged with any other one. If <err> is not
+ * NULL, it will be filled with an appropriate error. This pointer must be
+ * freeable or NULL.
*
* args syntax: <aclname> <acl_expr>
*/
-struct acl *parse_acl(const char **args, struct list *known_acl)
+struct acl *parse_acl(const char **args, struct list *known_acl, char **err)
{
__label__ out_return, out_free_acl_expr, out_free_name;
struct acl *cur_acl;
struct acl_expr *acl_expr;
char *name;
+ const char *pos;
- if (**args && invalid_char(*args))
+ if (**args && (pos = invalid_char(*args))) {
+ if (err)
+ memprintf(err, "invalid character in ACL name : '%c'", *pos);
goto out_return;
+ }
- acl_expr = parse_acl_expr(args + 1);
- if (!acl_expr)
+ acl_expr = parse_acl_expr(args + 1, err);
+ if (!acl_expr) {
+ /* parse_acl_expr will have filled <err> here */
goto out_return;
+ }
/* Check for args beginning with an opening parenthesis just after the
* subject, as this is almost certainly a typo. Right now we can only
if (!cur_acl) {
name = strdup(args[0]);
- if (!name)
+ if (!name) {
+ if (err)
+ memprintf(err, "out of memory when parsing ACL");
goto out_free_acl_expr;
+ }
cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
- if (cur_acl == NULL)
+ if (cur_acl == NULL) {
+ if (err)
+ memprintf(err, "out of memory when parsing ACL");
goto out_free_name;
+ }
LIST_INIT(&cur_acl->expr);
LIST_ADDQ(known_acl, &cur_acl->list);
/* Find a default ACL from the default_acl list, compile it and return it.
* If the ACL is not found, NULL is returned. In theory, it cannot fail,
* except when default ACLs are broken, in which case it will return NULL.
- * If <known_acl> is not NULL, the ACL will be queued at its tail.
+ * If <known_acl> is not NULL, the ACL will be queued at its tail. If <err> is
+ * not NULL, it will be filled with an error message if an error occurs. This
+ * pointer must be freeable or NULL.
*/
-struct acl *find_acl_default(const char *acl_name, struct list *known_acl)
+struct acl *find_acl_default(const char *acl_name, struct list *known_acl, char **err)
{
__label__ out_return, out_free_acl_expr, out_free_name;
struct acl *cur_acl;
break;
}
- if (default_acl_list[index].name == NULL)
+ if (default_acl_list[index].name == NULL) {
+ if (err)
+ memprintf(err, "no such ACL : '%s'", acl_name);
return NULL;
+ }
- acl_expr = parse_acl_expr((const char **)default_acl_list[index].expr);
- if (!acl_expr)
+ acl_expr = parse_acl_expr((const char **)default_acl_list[index].expr, err);
+ if (!acl_expr) {
+ /* parse_acl_expr must have filled err here */
goto out_return;
+ }
name = strdup(acl_name);
- if (!name)
+ if (!name) {
+ if (err)
+ memprintf(err, "out of memory when building default ACL '%s'", acl_name);
goto out_free_acl_expr;
+ }
+
cur_acl = (struct acl *)calloc(1, sizeof(*cur_acl));
- if (cur_acl == NULL)
+ if (cur_acl == NULL) {
+ if (err)
+ memprintf(err, "out of memory when building default ACL '%s'", acl_name);
goto out_free_name;
+ }
cur_acl->name = name;
cur_acl->requires |= acl_expr->kw->requires;
/* Parse an ACL condition starting at <args>[0], relying on a list of already
* known ACLs passed in <known_acl>. The new condition is returned (or NULL in
- * case of low memory). Supports multiple conditions separated by "or".
+ * case of low memory). Supports multiple conditions separated by "or". If
+ * <err> is not NULL, it will be filled with a pointer to an error message in
+ * case of error, that the caller is responsible for freeing. The initial
+ * location must either be freeable or NULL.
*/
-struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol)
+struct acl_cond *parse_acl_cond(const char **args, struct list *known_acl, int pol, char **err)
{
__label__ out_return, out_free_suite, out_free_term;
int arg, neg;
struct acl_cond *cond;
cond = (struct acl_cond *)calloc(1, sizeof(*cond));
- if (cond == NULL)
+ if (cond == NULL) {
+ if (err)
+ memprintf(err, "out of memory when parsing condition");
goto out_return;
+ }
LIST_INIT(&cond->list);
LIST_INIT(&cond->suites);
while (*args[arg_end] && strcmp(args[arg_end], "}") != 0)
arg_end++;
- if (!*args[arg_end])
+ if (!*args[arg_end]) {
+ if (err)
+ memprintf(err, "missing closing '}' in condition");
goto out_free_suite;
+ }
args_new = calloc(1, (arg_end - arg + 1) * sizeof(*args_new));
- if (!args_new)
+ if (!args_new) {
+ if (err)
+ memprintf(err, "out of memory when parsing condition");
goto out_free_suite;
+ }
args_new[0] = "";
memcpy(args_new + 1, args + arg + 1, (arg_end - arg) * sizeof(*args_new));
args_new[arg_end - arg] = "";
- cur_acl = parse_acl(args_new, known_acl);
+ cur_acl = parse_acl(args_new, known_acl, err);
free(args_new);
- if (!cur_acl)
+ if (!cur_acl) {
+ /* note that parse_acl() must have filled <err> here */
goto out_free_suite;
+ }
arg = arg_end;
}
else {
*/
cur_acl = find_acl_by_name(word, known_acl);
if (cur_acl == NULL) {
- cur_acl = find_acl_default(word, known_acl);
- if (cur_acl == NULL)
+ cur_acl = find_acl_default(word, known_acl, err);
+ if (cur_acl == NULL) {
+ /* note that find_acl_default() must have filled <err> here */
goto out_free_suite;
+ }
}
}
cur_term = (struct acl_term *)calloc(1, sizeof(*cur_term));
- if (cur_term == NULL)
+ if (cur_term == NULL) {
+ if (err)
+ memprintf(err, "out of memory when parsing condition");
goto out_free_suite;
+ }
cur_term->acl = cur_acl;
cur_term->neg = neg;
if (!cur_suite) {
cur_suite = (struct acl_term_suite *)calloc(1, sizeof(*cur_suite));
- if (cur_term == NULL)
+ if (cur_term == NULL) {
+ if (err)
+ memprintf(err, "out of memory when parsing condition");
goto out_free_term;
+ }
LIST_INIT(&cur_suite->terms);
LIST_ADDQ(&cond->suites, &cur_suite->list);
}
* condition is returned. NULL is returned in case of error or if the first
* word is neither "if" nor "unless". It automatically sets the file name and
* the line number in the condition for better error reporting, and adds the
- * ACL requirements to the proxy's acl_requires.
+ * ACL requirements to the proxy's acl_requires. If <err> is not NULL, it will
+ * be filled with a pointer to an error message in case of error, that the
+ * caller is responsible for freeing. The initial location must either be
+ * freeable or NULL.
*/
-struct acl_cond *build_acl_cond(const char *file, int line, struct proxy *px, const char **args)
+struct acl_cond *build_acl_cond(const char *file, int line, struct proxy *px, const char **args, char **err)
{
int pol = ACL_COND_NONE;
struct acl_cond *cond = NULL;
+ if (err)
+ *err = NULL;
+
if (!strcmp(*args, "if")) {
pol = ACL_COND_IF;
args++;
pol = ACL_COND_UNLESS;
args++;
}
- else
+ else {
+ if (err)
+ memprintf(err, "conditions must start with either 'if' or 'unless'");
return NULL;
+ }
- cond = parse_acl_cond(args, &px->acl, pol);
- if (!cond)
+ cond = parse_acl_cond(args, &px->acl, pol, err);
+ if (!cond) {
+ /* note that parse_acl_cond must have filled <err> here */
return NULL;
+ }
cond->file = file;
cond->line = line;
const char **cond_start)
{
regex_t *preg = NULL;
+ char *errmsg = NULL;
const char *err;
int err_code = 0;
struct acl_cond *cond = NULL;
if (cond_start &&
(strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
- if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
- file, line, cmd);
+ if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
+ file, line, cmd, errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto err;
}
curproxy->bind_proc = set;
}
else if (!strcmp(args[0], "acl")) { /* add an ACL */
+ char *errmsg = NULL;
+
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
err_code |= ERR_ALERT | ERR_FATAL;
}
- if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
- file, linenum, args[1]);
+ if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
+ file, linenum, args[1], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
}
else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
+ char *errmsg = NULL;
+
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
- file, linenum);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
+ file, linenum, errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
else if (strcmp(args[cur_arg], "if") == 0 ||
strcmp(args[cur_arg], "unless") == 0) {
- cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
+ char *errmsg = NULL;
+
+ cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
if (!cond) {
- Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
- file, linenum, args[0]);
+ Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
else if (!strcmp(args[0], "use_backend")) {
struct switching_rule *rule;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
- file, linenum);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
+ file, linenum, errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
else if (strcmp(args[0], "use-server") == 0) {
struct server_rule *rule;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
- file, linenum);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
+ file, linenum, errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if ((!strcmp(args[0], "force-persist")) ||
(!strcmp(args[0], "ignore-persist"))) {
struct persist_rule *rule;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
- file, linenum, args[0]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
struct sticking_rule *rule;
struct pattern_expr *expr;
int myidx = 0;
+ char *errmsg = NULL;
const char *name = NULL;
int flags;
}
if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
- Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
- file, linenum, args[0]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
free(expr);
goto out;
goto stats_error_parsing;
} else if (!strcmp(args[1], "admin")) {
struct stats_admin_rule *rule;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
- file, linenum, args[0], args[1]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
+ file, linenum, args[0], args[1], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
err_code |= ERR_WARN;
if (strcmp(args[1], "fail") == 0) {
+ char *errmsg = NULL;
+
/* add a condition to fail monitor requests */
if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
goto out;
}
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
- file, linenum, args[0], args[1]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
+ file, linenum, args[0], args[1], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
else if (!strcmp(args[0], "reqadd")) { /* add request header */
struct cond_wordlist *wl;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
}
if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
- file, linenum, args[0]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
}
else if (!strcmp(args[0], "rspadd")) { /* add response header */
struct cond_wordlist *wl;
+ char *errmsg = NULL;
if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
}
if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
- if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
- file, linenum, args[0]);
+ if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) {
struct acl_cond *cond;
+ char *errmsg = NULL;
- if ((cond = build_acl_cond(file, linenum, proxy, args+cur_arg)) == NULL) {
- Alert("parsing [%s:%d] : error detected while parsing an 'http-request %s' condition.\n",
- file, linenum, args[0]);
+ if ((cond = build_acl_cond(file, linenum, proxy, args+cur_arg, &errmsg)) == NULL) {
+ Alert("parsing [%s:%d] : error detected while parsing an 'http-request %s' condition : %s.\n",
+ file, linenum, args[0], errmsg);
+ free(errmsg);
return NULL;
}
rule->cond = cond;
}
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
- if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg)) == NULL) {
+ char *errmsg = NULL;
+
+ if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg, &errmsg)) == NULL) {
snprintf(err, errlen,
- "error detected in %s '%s' while parsing '%s' condition",
- proxy_type_str(curpx), curpx->id, args[arg]);
+ "error detected in %s '%s' while parsing '%s' condition : %s",
+ proxy_type_str(curpx), curpx->id, args[arg], errmsg);
+ free(errmsg);
return -1;
}
}
}
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
- if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg)) == NULL) {
+ char *errmsg = NULL;
+
+ if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg, &errmsg)) == NULL) {
snprintf(err, errlen,
- "error detected in %s '%s' while parsing '%s' condition",
- proxy_type_str(curpx), curpx->id, args[arg]);
+ "error detected in %s '%s' while parsing '%s' condition : %s",
+ proxy_type_str(curpx), curpx->id, args[arg], errmsg);
+ free(errmsg);
return -1;
}
}