]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: cfgparse: use the new error reporting framework for remaining cfg_keywords
authorWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 17:47:01 +0000 (19:47 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 8 May 2012 19:28:17 +0000 (21:28 +0200)
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.

include/common/cfgparse.h
include/proto/session.h
src/cfgparse.c
src/dumpstats.c
src/proto_tcp.c
src/proxy.c
src/session.c

index b43f8998be0e48aae565b992b252d4f5f3609bc1..118d098de4583330b6b76b425cf24bd94b02906e 100644 (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
index fb2b6a6605668b9afac34faecf4fbbe1fadeb0ba..049fc931c61822b24f9002decaf01e7c139873e0 100644 (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
index 134794049ca465833ad1b1a636878a54a6a3ca88..5222652e1ca60e8fe58a865229c5d123a1f0ec0b 100644 (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 @@ stats_error_parsing:
                                        /* 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;
                                        }
index ae19db79682e3236270b8cdde4373d1d6ad00791..e22ca1ff25f553c8e6b4674fb8086e4dbb56298b 100644 (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;
index 80a7c66b3fddeee6b33a8232a647680b75de8a00..2acdf986bf92206a9e95742ab1583cbf4f657861 100644 (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;
        }
 
index bb9fe5733da5831276850592badbaa8e5df76856..9ae9889814cd8a066fea6d764c6ee75099948b83 100644 (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;
        }
 
index cd02da24d43dbd4ee3530f82d78555864db82521..feb0283205e2ec12ac82fbe3201a17c2a8663e0e 100644 (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;
        }