MEDIUM: cfgparse: use the new error reporting framework for remaining cfg_keywords

All keywords registered using a cfg_kw_list now make use of the new error reporting
framework. This allows easier and more precise error reporting without having to
deal with complex buffer allocation issues.
This commit is contained in:
Willy Tarreau 2012-05-08 19:47:01 +02:00
parent a93c74be5c
commit 0a3dd74c9c
7 changed files with 194 additions and 199 deletions

View File

@ -1,23 +1,23 @@
/*
include/common/cfgparse.h
Configuration parsing functions.
Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation, version 2.1
exclusively.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
* include/common/cfgparse.h
* Configuration parsing functions.
*
* Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _COMMON_CFGPARSE_H
#define _COMMON_CFGPARSE_H
@ -43,8 +43,7 @@ struct cfg_keyword {
int section_type, /* current section CFG_{GLOBAL|LISTEN} */
struct proxy *curpx, /* current proxy (NULL in GLOBAL) */
struct proxy *defpx, /* default proxy (NULL in GLOBAL) */
char *err, /* error message buffer (do not add '\n') */
int errlen); /* error buffer size, '\0' included */
char **err); /* error or warning message output pointer */
};
/* A keyword list. It is a NULL-terminated array of keywords. It embeds a

View File

@ -46,7 +46,7 @@ void default_srv_error(struct session *s, struct stream_interface *si);
int parse_track_counters(char **args, int *arg,
int section_type, struct proxy *curpx,
struct track_ctr_prm *prm,
struct proxy *defpx, char *err, int errlen);
struct proxy *defpx, char **err);
/* Remove the refcount from the session to the tracked counters, and clear the
* pointer to ensure this is only performed once. The caller is responsible for

View File

@ -454,6 +454,7 @@ static int warnif_cond_requires_req(const struct acl_cond *cond, const char *fil
int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
{
int err_code = 0;
char *errmsg = NULL;
if (!strcmp(args[0], "global")) { /* new section */
/* no option, nothing special to do */
@ -1032,13 +1033,13 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
/* prepare error message just in case */
snprintf(trash, sizeof(trash),
"error near '%s' in '%s' section", args[0], "global");
rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
if (rc < 0) {
Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
}
else if (rc > 0) {
Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
err_code |= ERR_WARN;
goto out;
}
@ -1052,6 +1053,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
}
out:
free(errmsg);
return err_code;
}
@ -5249,14 +5251,14 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
/* prepare error message just in case */
snprintf(trash, sizeof(trash),
"error near '%s' in %s section", args[0], cursection);
rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
if (rc < 0) {
Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if (rc > 0) {
Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
err_code |= ERR_WARN;
goto out;
}

View File

@ -170,39 +170,38 @@ static struct proxy *alloc_stats_fe(const char *name)
}
/* This function parses a "stats" statement in the "global" section. It returns
* -1 if there is any error, otherwise zero. If it returns -1, it may write an
* error message into ther <err> buffer, for at most <errlen> bytes, trailing
* zero included. The trailing '\n' must not be written. The function must be
* called with <args> pointing to the first word after "stats".
* -1 if there is any error, otherwise zero. If it returns -1, it will write an
* error message into the <err> buffer which will be preallocated. The trailing
* '\n' must not be written. The function must be called with <args> pointing to
* the first word after "stats".
*/
static int stats_parse_global(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
args++;
if (!strcmp(args[0], "socket")) {
if (!strcmp(args[1], "socket")) {
struct sockaddr_un *su;
int cur_arg;
if (*args[1] == 0) {
snprintf(err, errlen, "'stats socket' in global section expects a path to a UNIX socket");
if (*args[2] == 0) {
memprintf(err, "'%s %s' in global section expects a path to a UNIX socket", args[0], args[1]);
return -1;
}
if (global.stats_sock.state != LI_NEW) {
snprintf(err, errlen, "'stats socket' already specified in global section");
memprintf(err, "'%s %s' already specified in global section", args[0], args[1]);
return -1;
}
su = str2sun(args[1]);
su = str2sun(args[2]);
if (!su) {
snprintf(err, errlen, "'stats socket' path would require truncation");
memprintf(err, "'%s %s' : path would require truncation", args[0], args[1]);
return -1;
}
memcpy(&global.stats_sock.addr, su, sizeof(struct sockaddr_un)); // guaranteed to fit
if (!global.stats_fe) {
if ((global.stats_fe = alloc_stats_fe("GLOBAL")) == NULL) {
snprintf(err, errlen, "out of memory");
memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
return -1;
}
}
@ -222,7 +221,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
global.stats_sock.next = global.stats_fe->listen;
global.stats_fe->listen = &global.stats_sock;
cur_arg = 2;
cur_arg = 3;
while (*args[cur_arg]) {
if (!strcmp(args[cur_arg], "uid")) {
global.stats_sock.perm.ux.uid = atol(args[cur_arg + 1]);
@ -240,8 +239,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
struct passwd *user;
user = getpwnam(args[cur_arg + 1]);
if (!user) {
snprintf(err, errlen, "unknown user '%s' in 'global' section ('stats user')",
args[cur_arg + 1]);
memprintf(err, "'%s %s' : unknown user '%s'", args[0], args[1], args[cur_arg + 1]);
return -1;
}
global.stats_sock.perm.ux.uid = user->pw_uid;
@ -251,8 +249,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
struct group *group;
group = getgrnam(args[cur_arg + 1]);
if (!group) {
snprintf(err, errlen, "unknown group '%s' in 'global' section ('stats group')",
args[cur_arg + 1]);
memprintf(err, "'%s %s' : unknown group '%s'", args[0], args[1], args[cur_arg + 1]);
return -1;
}
global.stats_sock.perm.ux.gid = group->gr_gid;
@ -266,13 +263,15 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
else if (!strcmp(args[cur_arg+1], "admin"))
global.stats_sock.perm.ux.level = ACCESS_LVL_ADMIN;
else {
snprintf(err, errlen, "'stats socket level' only supports 'user', 'operator', and 'admin'");
memprintf(err, "'%s %s' : '%s' only supports 'user', 'operator', and 'admin' (got '%s')",
args[0], args[1], args[cur_arg], args[cur_arg+1]);
return -1;
}
cur_arg += 2;
}
else {
snprintf(err, errlen, "'stats socket' only supports 'user', 'uid', 'group', 'gid', 'level', and 'mode'");
memprintf(err, "'%s %s' only supports 'user', 'uid', 'group', 'gid', 'level', and 'mode' (got '%s')",
args[0], args[1], args[cur_arg]);
return -1;
}
}
@ -280,45 +279,45 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
uxst_add_listener(&global.stats_sock);
global.maxsock++;
}
else if (!strcmp(args[0], "timeout")) {
else if (!strcmp(args[1], "timeout")) {
unsigned timeout;
const char *res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
const char *res = parse_time_err(args[2], &timeout, TIME_UNIT_MS);
if (res) {
snprintf(err, errlen, "unexpected character '%c' in 'stats timeout' in 'global' section", *res);
memprintf(err, "'%s %s' : unexpected character '%c'", args[0], args[1], *res);
return -1;
}
if (!timeout) {
snprintf(err, errlen, "a positive value is expected for 'stats timeout' in 'global section'");
memprintf(err, "'%s %s' expects a positive value", args[0], args[1]);
return -1;
}
if (!global.stats_fe) {
if ((global.stats_fe = alloc_stats_fe("GLOBAL")) == NULL) {
snprintf(err, errlen, "out of memory");
memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
return -1;
}
}
global.stats_fe->timeout.client = MS_TO_TICKS(timeout);
}
else if (!strcmp(args[0], "maxconn")) {
int maxconn = atol(args[1]);
else if (!strcmp(args[1], "maxconn")) {
int maxconn = atol(args[2]);
if (maxconn <= 0) {
snprintf(err, errlen, "a positive value is expected for 'stats maxconn' in 'global section'");
memprintf(err, "'%s %s' expects a positive value", args[0], args[1]);
return -1;
}
if (!global.stats_fe) {
if ((global.stats_fe = alloc_stats_fe("GLOBAL")) == NULL) {
snprintf(err, errlen, "out of memory");
memprintf(err, "'%s %s' : out of memory trying to allocate a frontend", args[0], args[1]);
return -1;
}
}
global.stats_fe->maxconn = maxconn;
}
else {
snprintf(err, errlen, "'stats' only supports 'socket', 'maxconn' and 'timeout' in 'global' section");
memprintf(err, "'%s' only supports 'socket', 'maxconn' and 'timeout' (got '%s')", args[0], args[1]);
return -1;
}
return 0;

View File

@ -936,11 +936,11 @@ int tcp_exec_req_rules(struct session *s)
/* Parse a tcp-response rule. Return a negative value in case of failure */
static int tcp_parse_response_rule(char **args, int arg, int section_type,
struct proxy *curpx, struct proxy *defpx,
struct tcp_rule *rule, char *err, int errlen)
struct tcp_rule *rule, char **err)
{
if (curpx == defpx || !(curpx->cap & PR_CAP_BE)) {
snprintf(err, errlen, "%s %s is only allowed in 'backend' sections",
args[0], args[1]);
memprintf(err, "%s %s is only allowed in 'backend' sections",
args[0], args[1]);
return -1;
}
@ -953,26 +953,23 @@ static int tcp_parse_response_rule(char **args, int arg, int section_type,
rule->action = TCP_ACT_REJECT;
}
else {
snprintf(err, errlen,
"'%s %s' expects 'accept' or 'reject' in %s '%s' (was '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]);
memprintf(err,
"'%s %s' expects 'accept' or 'reject' in %s '%s' (got '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]);
return -1;
}
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
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 : %s",
proxy_type_str(curpx), curpx->id, args[arg], errmsg);
free(errmsg);
if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg, err)) == NULL) {
memprintf(err,
"'%s %s %s' : error detected in %s '%s' while parsing '%s' condition : %s",
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg], *err);
return -1;
}
}
else if (*args[arg]) {
snprintf(err, errlen,
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
memprintf(err,
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (got '%s')",
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg]);
return -1;
}
@ -984,11 +981,11 @@ static int tcp_parse_response_rule(char **args, int arg, int section_type,
/* Parse a tcp-request rule. Return a negative value in case of failure */
static int tcp_parse_request_rule(char **args, int arg, int section_type,
struct proxy *curpx, struct proxy *defpx,
struct tcp_rule *rule, char *err, int errlen)
struct tcp_rule *rule, char **err)
{
if (curpx == defpx) {
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
args[0], args[1]);
memprintf(err, "%s %s is not allowed in 'defaults' sections",
args[0], args[1]);
return -1;
}
@ -1002,50 +999,55 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type,
}
else if (strcmp(args[arg], "track-sc1") == 0) {
int ret;
int kw = arg;
arg++;
ret = parse_track_counters(args, &arg, section_type, curpx,
&rule->act_prm.trk_ctr, defpx, err, errlen);
if (ret < 0) /* nb: warnings are not handled yet */
return -1;
&rule->act_prm.trk_ctr, defpx, err);
if (ret < 0) { /* nb: warnings are not handled yet */
memprintf(err,
"'%s %s %s' : %s in %s '%s'",
args[0], args[1], args[kw], *err, proxy_type_str(curpx), curpx->id);
return ret;
}
rule->action = TCP_ACT_TRK_SC1;
}
else if (strcmp(args[arg], "track-sc2") == 0) {
int ret;
int kw = arg;
arg++;
ret = parse_track_counters(args, &arg, section_type, curpx,
&rule->act_prm.trk_ctr, defpx, err, errlen);
if (ret < 0) /* nb: warnings are not handled yet */
return -1;
&rule->act_prm.trk_ctr, defpx, err);
if (ret < 0) { /* nb: warnings are not handled yet */
memprintf(err,
"'%s %s %s' : %s in %s '%s'",
args[0], args[1], args[kw], *err, proxy_type_str(curpx), curpx->id);
return ret;
}
rule->action = TCP_ACT_TRK_SC2;
}
else {
snprintf(err, errlen,
"'%s %s' expects 'accept', 'reject', 'track-sc1' "
"or 'track-sc2' in %s '%s' (was '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]);
memprintf(err,
"'%s %s' expects 'accept', 'reject', 'track-sc1' "
"or 'track-sc2' in %s '%s' (got '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]);
return -1;
}
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
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 : %s",
proxy_type_str(curpx), curpx->id, args[arg], errmsg);
free(errmsg);
if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg, err)) == NULL) {
memprintf(err,
"'%s %s %s' : error detected in %s '%s' while parsing '%s' condition : %s",
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg], *err);
return -1;
}
}
else if (*args[arg]) {
snprintf(err, errlen,
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
memprintf(err,
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (got '%s')",
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg]);
return -1;
}
@ -1056,41 +1058,39 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type,
* keyword.
*/
static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
const char *ptr = NULL;
unsigned int val;
int retlen;
int warn = 0;
int arg;
struct tcp_rule *rule;
if (!*args[1]) {
snprintf(err, errlen, "missing argument for '%s' in %s '%s'",
args[0], proxy_type_str(curpx), curpx->id);
memprintf(err, "missing argument for '%s' in %s '%s'",
args[0], proxy_type_str(curpx), curpx->id);
return -1;
}
if (strcmp(args[1], "inspect-delay") == 0) {
if (curpx == defpx || !(curpx->cap & PR_CAP_BE)) {
snprintf(err, errlen, "%s %s is only allowed in 'backend' sections",
args[0], args[1]);
memprintf(err, "%s %s is only allowed in 'backend' sections",
args[0], args[1]);
return -1;
}
if (!*args[2] || (ptr = parse_time_err(args[2], &val, TIME_UNIT_MS))) {
retlen = snprintf(err, errlen,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr && retlen < errlen)
retlen += snprintf(err + retlen, errlen - retlen,
" (unexpected character '%c')", *ptr);
memprintf(err,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr)
memprintf(err, "%s (unexpected character '%c')", *err, *ptr);
return -1;
}
if (curpx->tcp_rep.inspect_delay) {
snprintf(err, errlen, "ignoring %s %s (was already defined) in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
memprintf(err, "ignoring %s %s (was already defined) in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
return 1;
}
curpx->tcp_rep.inspect_delay = val;
@ -1103,7 +1103,7 @@ static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx,
if (strcmp(args[1], "content") == 0) {
arg++;
if (tcp_parse_response_rule(args, arg, section_type, curpx, defpx, rule, err, errlen) < 0)
if (tcp_parse_response_rule(args, arg, section_type, curpx, defpx, rule, err) < 0)
goto error;
if (rule->cond && (rule->cond->requires & ACL_USE_L6REQ_VOLATILE)) {
@ -1113,18 +1113,18 @@ static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx,
acl = cond_find_require(rule->cond, ACL_USE_L6REQ_VOLATILE);
name = acl ? acl->name : "(unknown)";
retlen = snprintf(err, errlen,
"acl '%s' involves some request-only criteria which will be ignored.",
name);
memprintf(err,
"acl '%s' involves some request-only criteria which will be ignored in '%s %s'",
name, args[0], args[1]);
warn++;
}
LIST_ADDQ(&curpx->tcp_rep.inspect_rules, &rule->list);
}
else {
retlen = snprintf(err, errlen,
"'%s' expects 'inspect-delay' or 'content' in %s '%s' (was '%s')",
args[0], proxy_type_str(curpx), curpx->id, args[1]);
memprintf(err,
"'%s' expects 'inspect-delay' or 'content' in %s '%s' (got '%s')",
args[0], proxy_type_str(curpx), curpx->id, args[1]);
goto error;
}
@ -1139,41 +1139,42 @@ static int tcp_parse_tcp_rep(char **args, int section_type, struct proxy *curpx,
* keyword.
*/
static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
const char *ptr = NULL;
unsigned int val;
int retlen;
int warn = 0;
int arg;
struct tcp_rule *rule;
if (!*args[1]) {
snprintf(err, errlen, "missing argument for '%s' in %s '%s'",
args[0], proxy_type_str(curpx), curpx->id);
if (curpx == defpx)
memprintf(err, "missing argument for '%s' in defaults section", args[0]);
else
memprintf(err, "missing argument for '%s' in %s '%s'",
args[0], proxy_type_str(curpx), curpx->id);
return -1;
}
if (!strcmp(args[1], "inspect-delay")) {
if (curpx == defpx) {
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
args[0], args[1]);
memprintf(err, "%s %s is not allowed in 'defaults' sections",
args[0], args[1]);
return -1;
}
if (!*args[2] || (ptr = parse_time_err(args[2], &val, TIME_UNIT_MS))) {
retlen = snprintf(err, errlen,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr && retlen < errlen)
retlen += snprintf(err+retlen, errlen - retlen,
" (unexpected character '%c')", *ptr);
memprintf(err,
"'%s %s' expects a positive delay in milliseconds, in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
if (ptr)
memprintf(err, "%s (unexpected character '%c')", *err, *ptr);
return -1;
}
if (curpx->tcp_req.inspect_delay) {
snprintf(err, errlen, "ignoring %s %s (was already defined) in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
memprintf(err, "ignoring %s %s (was already defined) in %s '%s'",
args[0], args[1], proxy_type_str(curpx), curpx->id);
return 1;
}
curpx->tcp_req.inspect_delay = val;
@ -1186,7 +1187,7 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
if (strcmp(args[1], "content") == 0) {
arg++;
if (tcp_parse_request_rule(args, arg, section_type, curpx, defpx, rule, err, errlen) < 0)
if (tcp_parse_request_rule(args, arg, section_type, curpx, defpx, rule, err) < 0)
goto error;
if (rule->cond && (rule->cond->requires & ACL_USE_RTR_ANY)) {
@ -1196,9 +1197,9 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
acl = cond_find_require(rule->cond, ACL_USE_RTR_ANY);
name = acl ? acl->name : "(unknown)";
retlen = snprintf(err, errlen,
"acl '%s' involves some response-only criteria which will be ignored.",
name);
memprintf(err,
"acl '%s' involves some response-only criteria which will be ignored in '%s %s'",
name, args[0], args[1]);
warn++;
}
LIST_ADDQ(&curpx->tcp_req.inspect_rules, &rule->list);
@ -1207,12 +1208,12 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
arg++;
if (!(curpx->cap & PR_CAP_FE)) {
snprintf(err, errlen, "%s %s is not allowed because %s %s is not a frontend",
args[0], args[1], proxy_type_str(curpx), curpx->id);
memprintf(err, "%s %s is not allowed because %s %s is not a frontend",
args[0], args[1], proxy_type_str(curpx), curpx->id);
goto error;
}
if (tcp_parse_request_rule(args, arg, section_type, curpx, defpx, rule, err, errlen) < 0)
if (tcp_parse_request_rule(args, arg, section_type, curpx, defpx, rule, err) < 0)
goto error;
if (rule->cond && (rule->cond->requires & (ACL_USE_RTR_ANY|ACL_USE_L6_ANY|ACL_USE_L7_ANY))) {
@ -1223,24 +1224,29 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
name = acl ? acl->name : "(unknown)";
if (acl->requires & (ACL_USE_L6_ANY|ACL_USE_L7_ANY)) {
retlen = snprintf(err, errlen,
"'%s %s' may not reference acl '%s' which makes use of "
"payload in %s '%s'. Please use '%s content' for this.",
args[0], args[1], name, proxy_type_str(curpx), curpx->id, args[0]);
memprintf(err,
"'%s %s' may not reference acl '%s' which makes use of "
"payload in %s '%s'. Please use '%s content' for this.",
args[0], args[1], name, proxy_type_str(curpx), curpx->id, args[0]);
goto error;
}
if (acl->requires & ACL_USE_RTR_ANY)
retlen = snprintf(err, errlen,
"acl '%s' involves some response-only criteria which will be ignored.",
name);
memprintf(err,
"acl '%s' involves some response-only criteria which will be ignored in '%s %s'",
name, args[0], args[1]);
warn++;
}
LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list);
}
else {
retlen = snprintf(err, errlen,
"'%s' expects 'inspect-delay', 'connection', or 'content' in %s '%s' (was '%s')",
args[0], proxy_type_str(curpx), curpx->id, args[1]);
if (curpx == defpx)
memprintf(err,
"'%s' expects 'inspect-delay', 'connection', or 'content' in defaults section (got '%s')",
args[0], args[1]);
else
memprintf(err,
"'%s' expects 'inspect-delay', 'connection', or 'content' in %s '%s' (got '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id);
goto error;
}

View File

@ -125,15 +125,15 @@ int get_backend_server(const char *bk_name, const char *sv_name,
/* This function parses a "timeout" statement in a proxy section. It returns
* -1 if there is any error, 1 for a warning, otherwise zero. If it does not
* return zero, it may write an error message into the <err> buffer, for at
* most <errlen> bytes, trailing zero included. The trailing '\n' must not
* be written. The function must be called with <args> pointing to the first
* command line word, with <proxy> pointing to the proxy being parsed, and
* <defpx> to the default proxy or NULL. As a special case for compatibility
* with older configs, it also accepts "{cli|srv|con}timeout" in args[0].
* return zero, it will write an error or warning message into a preallocated
* buffer returned at <err>. The trailing is not be written. The function must
* be called with <args> pointing to the first command line word, with <proxy>
* pointing to the proxy being parsed, and <defpx> to the default proxy or NULL.
* As a special case for compatibility with older configs, it also accepts
* "{cli|srv|con}timeout" in args[0].
*/
static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
unsigned timeout;
int retval, cap;
@ -184,32 +184,32 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
td = &defpx->timeout.queue;
cap = PR_CAP_BE;
} else {
snprintf(err, errlen,
"timeout '%s': must be 'client', 'server', 'connect', 'check', "
"'queue', 'http-keep-alive', 'http-request' or 'tarpit'",
args[0]);
memprintf(err,
"'timeout' supports 'client', 'server', 'connect', 'check', "
"'queue', 'http-keep-alive', 'http-request' or 'tarpit', (got '%s')",
args[0]);
return -1;
}
if (*args[1] == 0) {
snprintf(err, errlen, "%s timeout expects an integer value (in milliseconds)", name);
memprintf(err, "'timeout %s' expects an integer value (in milliseconds)", name);
return -1;
}
res = parse_time_err(args[1], &timeout, TIME_UNIT_MS);
if (res) {
snprintf(err, errlen, "unexpected character '%c' in %s timeout", *res, name);
memprintf(err, "unexpected character '%c' in 'timeout %s'", *res, name);
return -1;
}
if (!(proxy->cap & cap)) {
snprintf(err, errlen, "%s timeout will be ignored because %s '%s' has no %s capability",
name, proxy_type_str(proxy), proxy->id,
(cap & PR_CAP_BE) ? "backend" : "frontend");
memprintf(err, "'timeout %s' will be ignored because %s '%s' has no %s capability",
name, proxy_type_str(proxy), proxy->id,
(cap & PR_CAP_BE) ? "backend" : "frontend");
retval = 1;
}
else if (defpx && *tv != *td) {
snprintf(err, errlen, "overwriting %s timeout which was already specified", name);
memprintf(err, "overwriting 'timeout %s' which was already specified", name);
retval = 1;
}
@ -219,59 +219,51 @@ static int proxy_parse_timeout(char **args, int section, struct proxy *proxy,
/* This function parses a "rate-limit" statement in a proxy section. It returns
* -1 if there is any error, 1 for a warning, otherwise zero. If it does not
* return zero, it may write an error message into the <err> buffer, for at
* most <errlen> bytes, trailing zero included. The trailing '\n' must not
* be written. The function must be called with <args> pointing to the first
* command line word, with <proxy> pointing to the proxy being parsed, and
* <defpx> to the default proxy or NULL.
* return zero, it will write an error or warning message into a preallocated
* buffer returned at <err>. The function must be called with <args> pointing
* to the first command line word, with <proxy> pointing to the proxy being
* parsed, and <defpx> to the default proxy or NULL.
*/
static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
int retval, cap;
char *res, *name;
char *res;
unsigned int *tv = NULL;
unsigned int *td = NULL;
unsigned int val;
retval = 0;
/* simply skip "rate-limit" */
if (strcmp(args[0], "rate-limit") == 0)
args++;
name = args[0];
if (!strcmp(args[0], "sessions")) {
name = "sessions";
if (strcmp(args[1], "sessions") == 0) {
tv = &proxy->fe_sps_lim;
td = &defpx->fe_sps_lim;
cap = PR_CAP_FE;
} else {
snprintf(err, errlen,
"%s '%s': must be 'sessions'",
"rate-limit", args[0]);
}
else {
memprintf(err, "'%s' only supports 'sessions' (got '%s')", args[0], args[1]);
return -1;
}
if (*args[1] == 0) {
snprintf(err, errlen, "%s %s expects expects an integer value (in sessions/second)", "rate-limit", name);
if (*args[2] == 0) {
memprintf(err, "'%s %s' expects expects an integer value (in sessions/second)", args[0], args[1]);
return -1;
}
val = strtoul(args[1], &res, 0);
val = strtoul(args[2], &res, 0);
if (*res) {
snprintf(err, errlen, "%s %s: unexpected character '%c' in integer value '%s'", "rate-limit", name, *res, args[1]);
memprintf(err, "'%s %s' : unexpected character '%c' in integer value '%s'", args[0], args[1], *res, args[2]);
return -1;
}
if (!(proxy->cap & cap)) {
snprintf(err, errlen, "%s %s will be ignored because %s '%s' has no %s capability",
"rate-limit", name, proxy_type_str(proxy), proxy->id,
memprintf(err, "%s %s will be ignored because %s '%s' has no %s capability",
args[0], args[1], proxy_type_str(proxy), proxy->id,
(cap & PR_CAP_BE) ? "backend" : "frontend");
retval = 1;
}
else if (defpx && *tv != *td) {
snprintf(err, errlen, "overwriting %s %s which was already specified", "rate-limit", name);
memprintf(err, "overwriting %s %s which was already specified", args[0], args[1]);
retval = 1;
}

View File

@ -3385,10 +3385,9 @@ static struct acl_kw_list acl_kws = {{ },{
int parse_track_counters(char **args, int *arg,
int section_type, struct proxy *curpx,
struct track_ctr_prm *prm,
struct proxy *defpx, char *err, int errlen)
struct proxy *defpx, char **err)
{
int sample_type = 0;
char *kw = args[*arg - 1];
/* parse the arguments of "track-sc[12]" before the condition in the
* following form :
@ -3401,9 +3400,7 @@ int parse_track_counters(char **args, int *arg,
}
else if (strcmp(args[*arg], "table") == 0) {
if (!args[*arg + 1]) {
snprintf(err, errlen,
"missing table for %s in %s '%s'.",
kw, proxy_type_str(curpx), curpx->id);
memprintf(err, "missing table name");
return -1;
}
/* we copy the table name for now, it will be resolved later */
@ -3418,9 +3415,9 @@ int parse_track_counters(char **args, int *arg,
}
if (!sample_type) {
snprintf(err, errlen,
"%s key not specified in %s '%s' (found %s, only 'src' is supported).",
kw, proxy_type_str(curpx), curpx->id, quote_arg(args[*arg]));
memprintf(err,
"tracking key not specified (found %s, only 'src' is supported)",
quote_arg(args[*arg]));
return -1;
}