all: haproxy $(EXTRA)
endif
-OBJS = src/proto_http.o src/cfgparse.o src/server.o src/stream.o \
+OBJS = src/proto_http.o src/cfgparse.o src/cfgparse-global.o \
+ src/server.o src/stream.o \
src/flt_spoe.o src/stick_table.o src/stats.o src/mux_h2.o \
src/checks.o src/haproxy.o src/log.o src/dns.o src/peers.o \
src/standard.o src/sample.o src/cli.o src/stream_interface.o \
#define CFG_USERLIST 3
#define CFG_PEERS 4
+/* various keyword modifiers */
+enum kw_mod {
+ KWM_STD = 0, /* normal */
+ KWM_NO, /* "no" prefixed before the keyword */
+ KWM_DEF, /* "default" prefixed before the keyword */
+};
+
struct cfg_keyword {
int section; /* section type for this keyword */
const char *kw; /* the keyword itself */
struct cfg_keyword kw[VAR_ARRAY];
};
+/* permit to store configuration section */
+struct cfg_section {
+ struct list list;
+ char *section_name;
+ int (*section_parser)(const char *, int, char **, int);
+ int (*post_section_parser)();
+};
+
+/* store post configuration parsing */
+
+struct cfg_postparser {
+ struct list list;
+ char *name;
+ int (*func)();
+};
+
+/* some of the most common options which are also the easiest to handle */
+struct cfg_opt {
+ const char *name;
+ unsigned int val;
+ unsigned int cap;
+ unsigned int checks;
+ unsigned int mode;
+};
extern int cfg_maxpconn;
extern int cfg_maxconn;
extern char *cfg_scope;
+extern struct cfg_kw_list cfg_keywords;
int cfg_parse_global(const char *file, int linenum, char **args, int inv);
int cfg_parse_listen(const char *file, int linenum, char **args, int inv);
int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code);
int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code);
int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, char **err);
+unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err);
/*
* Sends a warning if proxy <proxy> does not have at least one of the
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <common/cfgparse.h>
+#include <proto/compression.h>
+
+/*
+ * parse a line in a <global> section. Returns the error code, 0 if OK, or
+ * any combination of :
+ * - ERR_ABORT: must abort ASAP
+ * - ERR_FATAL: we can continue parsing but not start the service
+ * - ERR_WARN: a warning has been emitted
+ * - ERR_ALERT: an alert has been emitted
+ * Only the two first ones can stop processing, the two others are just
+ * indicators.
+ */
+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 */
+ alertif_too_many_args(0, file, linenum, args, &err_code);
+ goto out;
+ }
+ else if (!strcmp(args[0], "daemon")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.mode |= MODE_DAEMON;
+ }
+ else if (!strcmp(args[0], "master-worker")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*args[1]) {
+ if (!strcmp(args[1], "no-exit-on-failure")) {
+ global.tune.options |= GTUNE_NOEXIT_ONFAILURE;
+ } else {
+ ha_alert("parsing [%s:%d] : '%s' only supports 'no-exit-on-failure' option.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ global.mode |= MODE_MWORKER;
+ }
+ else if (!strcmp(args[0], "debug")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.mode |= MODE_DEBUG;
+ }
+ else if (!strcmp(args[0], "noepoll")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_EPOLL;
+ }
+ else if (!strcmp(args[0], "nokqueue")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_KQUEUE;
+ }
+ else if (!strcmp(args[0], "nopoll")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_POLL;
+ }
+ else if (!strcmp(args[0], "nosplice")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_SPLICE;
+ }
+ else if (!strcmp(args[0], "nogetaddrinfo")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_GAI;
+ }
+ else if (!strcmp(args[0], "noreuseport")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.tune.options &= ~GTUNE_USE_REUSEPORT;
+ }
+ else if (!strcmp(args[0], "quiet")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.mode |= MODE_QUIET;
+ }
+ else if (!strcmp(args[0], "tune.runqueue-depth")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.runqueue_depth != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.runqueue_depth = atol(args[1]);
+
+ }
+ else if (!strcmp(args[0], "tune.maxpollevents")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.maxpollevents != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.maxpollevents = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.maxaccept")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.maxaccept != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.maxaccept = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.chksize")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.chksize = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.recv_enough")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.recv_enough = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.buffers.limit")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.buf_limit = atol(args[1]);
+ if (global.tune.buf_limit) {
+ if (global.tune.buf_limit < 3)
+ global.tune.buf_limit = 3;
+ if (global.tune.buf_limit <= global.tune.reserved_bufs)
+ global.tune.buf_limit = global.tune.reserved_bufs + 1;
+ }
+ }
+ else if (!strcmp(args[0], "tune.buffers.reserve")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.reserved_bufs = atol(args[1]);
+ if (global.tune.reserved_bufs < 2)
+ global.tune.reserved_bufs = 2;
+ if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
+ global.tune.buf_limit = global.tune.reserved_bufs + 1;
+ }
+ else if (!strcmp(args[0], "tune.bufsize")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.bufsize = atol(args[1]);
+ if (global.tune.bufsize <= 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "tune.maxrewrite")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.maxrewrite = atol(args[1]);
+ if (global.tune.maxrewrite < 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "tune.idletimer")) {
+ unsigned int idle;
+ const char *res;
+
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
+ if (res) {
+ ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
+ file, linenum, *res, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (idle > 65535) {
+ ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.idle_timer = idle;
+ }
+ else if (!strcmp(args[0], "tune.rcvbuf.client")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.client_rcvbuf != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.client_rcvbuf = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.rcvbuf.server")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.server_rcvbuf != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.server_rcvbuf = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.sndbuf.client")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.client_sndbuf != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.client_sndbuf = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.sndbuf.server")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.tune.server_sndbuf != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.server_sndbuf = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.pipesize")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.pipesize = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "tune.http.cookielen")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.cookie_len = atol(args[1]) + 1;
+ }
+ else if (!strcmp(args[0], "tune.http.logurilen")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.requri_len = atol(args[1]) + 1;
+ }
+ else if (!strcmp(args[0], "tune.http.maxhdr")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.tune.max_http_hdr = atoi(args[1]);
+ if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
+ ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "tune.comp.maxlevel")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*args[1]) {
+ global.tune.comp_maxlevel = atoi(args[1]);
+ if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
+ ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ } else {
+ ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "tune.pattern.cache-size")) {
+ if (*args[1]) {
+ global.tune.pattern_cache = atoi(args[1]);
+ if (global.tune.pattern_cache < 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ } else {
+ ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "uid")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.uid != 0) {
+ ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
+ ha_warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
+ err_code |= ERR_WARN;
+ goto out;
+ }
+
+ }
+ else if (!strcmp(args[0], "gid")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.gid != 0) {
+ ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
+ ha_warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
+ err_code |= ERR_WARN;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "external-check")) {
+ if (alertif_too_many_args(0, file, linenum, args, &err_code))
+ goto out;
+ global.external_check = 1;
+ }
+ /* user/group name handling */
+ else if (!strcmp(args[0], "user")) {
+ struct passwd *ha_user;
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.uid != 0) {
+ ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ errno = 0;
+ ha_user = getpwnam(args[1]);
+ if (ha_user != NULL) {
+ global.uid = (int)ha_user->pw_uid;
+ }
+ else {
+ ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ }
+ else if (!strcmp(args[0], "group")) {
+ struct group *ha_group;
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.gid != 0) {
+ ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ errno = 0;
+ ha_group = getgrnam(args[1]);
+ if (ha_group != NULL) {
+ global.gid = (int)ha_group->gr_gid;
+ }
+ else {
+ ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ }
+ /* end of user/group name handling*/
+ else if (!strcmp(args[0], "nbproc")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.nbproc = atol(args[1]);
+ if (global.nbproc < 1 || global.nbproc > LONGBITS) {
+ ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
+ file, linenum, args[0], LONGBITS, global.nbproc);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "nbthread")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.nbthread = parse_nbthread(args[1], &errmsg);
+ if (!global.nbthread) {
+ ha_alert("parsing [%s:%d] : '%s' %s.\n",
+ file, linenum, args[0], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "maxconn")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.maxconn != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.maxconn = atol(args[1]);
+#ifdef SYSTEM_MAXCONN
+ if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
+ ha_alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
+ global.maxconn = DEFAULT_MAXCONN;
+ err_code |= ERR_ALERT;
+ }
+#endif /* SYSTEM_MAXCONN */
+ }
+ else if (!strcmp(args[0], "ssl-server-verify")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ if (strcmp(args[1],"none") == 0)
+ global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
+ else if (strcmp(args[1],"required") == 0)
+ global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
+ else {
+ ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "maxconnrate")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.cps_lim != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.cps_lim = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "maxsessrate")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.sps_lim != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.sps_lim = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "maxsslrate")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.ssl_lim != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.ssl_lim = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "maxcomprate")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.comp_rate_lim = atoi(args[1]) * 1024;
+ }
+ else if (!strcmp(args[0], "maxpipes")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.maxpipes != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.maxpipes = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "maxzlibmem")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
+ }
+ else if (!strcmp(args[0], "maxcompcpuusage")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ compress_min_idle = 100 - atoi(args[1]);
+ if (compress_min_idle > 100) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+
+ else if (!strcmp(args[0], "ulimit-n")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.rlimit_nofile != 0) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.rlimit_nofile = atol(args[1]);
+ }
+ else if (!strcmp(args[0], "chroot")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.chroot != NULL) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.chroot = strdup(args[1]);
+ }
+ else if (!strcmp(args[0], "description")) {
+ int i, len=0;
+ char *d;
+
+ if (!*args[1]) {
+ ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ for (i = 1; *args[i]; i++)
+ len += strlen(args[i]) + 1;
+
+ if (global.desc)
+ free(global.desc);
+
+ global.desc = d = calloc(1, len);
+
+ d += snprintf(d, global.desc + len - d, "%s", args[1]);
+ for (i = 2; *args[i]; i++)
+ d += snprintf(d, global.desc + len - d, " %s", args[i]);
+ }
+ else if (!strcmp(args[0], "node")) {
+ int i;
+ char c;
+
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+
+ for (i=0; args[1][i]; i++) {
+ c = args[1][i];
+ if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
+ !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
+ break;
+ }
+
+ if (!i || args[1][i]) {
+ ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
+ " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (global.node)
+ free(global.node);
+
+ global.node = strdup(args[1]);
+ }
+ else if (!strcmp(args[0], "pidfile")) {
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.pidfile != NULL) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.pidfile = strdup(args[1]);
+ }
+ else if (!strcmp(args[0], "unix-bind")) {
+ int cur_arg = 1;
+ while (*(args[cur_arg])) {
+ if (!strcmp(args[cur_arg], "prefix")) {
+ if (global.unix_bind.prefix != NULL) {
+ ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
+ err_code |= ERR_ALERT;
+ cur_arg += 2;
+ continue;
+ }
+
+ if (*(args[cur_arg+1]) == 0) {
+ ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.unix_bind.prefix = strdup(args[cur_arg+1]);
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "mode")) {
+
+ global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "uid")) {
+
+ global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "gid")) {
+
+ global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "user")) {
+ struct passwd *user;
+
+ user = getpwnam(args[cur_arg + 1]);
+ if (!user) {
+ ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
+ file, linenum, args[0], args[cur_arg + 1 ]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ global.unix_bind.ux.uid = user->pw_uid;
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "group")) {
+ struct group *group;
+
+ group = getgrnam(args[cur_arg + 1]);
+ if (!group) {
+ ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
+ file, linenum, args[0], args[cur_arg + 1 ]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ global.unix_bind.ux.gid = group->gr_gid;
+ cur_arg += 2;
+ continue;
+ }
+
+ ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
+ if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
+ ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
+ char *name;
+
+ if (global.log_send_hostname != NULL) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+
+ if (*(args[1]))
+ name = args[1];
+ else
+ name = hostname;
+
+ free(global.log_send_hostname);
+ global.log_send_hostname = strdup(name);
+ }
+ else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
+ if (global.server_state_base != NULL) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+
+ if (!*(args[1])) {
+ ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+
+ global.server_state_base = strdup(args[1]);
+ }
+ else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
+ if (global.server_state_file != NULL) {
+ ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+
+ if (!*(args[1])) {
+ ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
+ err_code |= ERR_FATAL;
+ goto out;
+ }
+
+ global.server_state_file = strdup(args[1]);
+ }
+ else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ chunk_destroy(&global.log_tag);
+ chunk_initstr(&global.log_tag, strdup(args[1]));
+ }
+ else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (global.spread_checks != 0) {
+ ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
+ err_code |= ERR_ALERT;
+ goto out;
+ }
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ global.spread_checks = atol(args[1]);
+ if (global.spread_checks < 0 || global.spread_checks > 50) {
+ ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ }
+ else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
+ const char *err;
+ unsigned int val;
+
+ if (alertif_too_many_args(1, file, linenum, args, &err_code))
+ goto out;
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ err = parse_time_err(args[1], &val, TIME_UNIT_MS);
+ if (err) {
+ ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ global.max_spread_checks = val;
+ if (global.max_spread_checks < 0) {
+ ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ }
+ else if (strcmp(args[0], "cpu-map") == 0) {
+ /* map a process list to a CPU set */
+#ifdef USE_CPU_AFFINITY
+ char *slash;
+ unsigned long proc = 0, thread = 0, cpus;
+ int i, j, n, autoinc;
+
+ if (!*args[1] || !*args[2]) {
+ ha_alert("parsing [%s:%d] : %s expects a process number "
+ " ('all', 'odd', 'even', a number from 1 to %d or a range), "
+ " followed by a list of CPU ranges with numbers from 0 to %d.\n",
+ file, linenum, args[0], LONGBITS, LONGBITS - 1);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if ((slash = strchr(args[1], '/')) != NULL)
+ *slash = 0;
+
+ if (parse_process_number(args[1], &proc, &autoinc, &errmsg)) {
+ ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (slash) {
+ if (parse_process_number(slash+1, &thread, NULL, &errmsg)) {
+ ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ *slash = '/';
+
+ if (autoinc && atleast2(proc) && atleast2(thread)) {
+ ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
+ "a process range _AND_ a thread range\n",
+ file, linenum, args[0], args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+
+ if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
+ ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (autoinc &&
+ my_popcountl(proc) != my_popcountl(cpus) &&
+ my_popcountl(thread) != my_popcountl(cpus)) {
+ ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
+ "must have the same size to be automatically bound\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ for (i = n = 0; i < LONGBITS; i++) {
+ /* No mapping for this process */
+ if (!(proc & (1UL << i)))
+ continue;
+
+ /* Mapping at the process level */
+ if (!thread) {
+ if (!autoinc)
+ global.cpu_map.proc[i] = cpus;
+ else {
+ n += my_ffsl(cpus >> n);
+ global.cpu_map.proc[i] = (1UL << (n-1));
+ }
+ continue;
+ }
+
+ /* Mapping at the thread level */
+ for (j = 0; j < MAX_THREADS; j++) {
+ /* Np mapping for this thread */
+ if (!(thread & (1UL << j)))
+ continue;
+
+ if (!autoinc)
+ global.cpu_map.thread[i][j] = cpus;
+ else {
+ n += my_ffsl(cpus >> n);
+ global.cpu_map.thread[i][j] = (1UL << (n-1));
+ }
+ }
+ }
+#else
+ ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+#endif /* ! USE_CPU_AFFINITY */
+ }
+ else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
+ if (alertif_too_many_args(3, file, linenum, args, &err_code))
+ goto out;
+
+ if (*(args[2]) == 0) {
+ ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ /* "setenv" overwrites, "presetenv" only sets if not yet set */
+ if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
+ ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else if (!strcmp(args[0], "unsetenv")) {
+ int arg;
+
+ if (*(args[1]) == 0) {
+ ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ for (arg = 1; *args[arg]; arg++) {
+ if (unsetenv(args[arg]) != 0) {
+ ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ }
+ else if (!strcmp(args[0], "resetenv")) {
+ extern char **environ;
+ char **env = environ;
+
+ /* args contain variable names to keep, one per argument */
+ while (*env) {
+ int arg;
+
+ /* look for current variable in among all those we want to keep */
+ for (arg = 1; *args[arg]; arg++) {
+ if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
+ (*env)[strlen(args[arg])] == '=')
+ break;
+ }
+
+ /* delete this variable */
+ if (!*args[arg]) {
+ char *delim = strchr(*env, '=');
+
+ if (!delim || delim - *env >= trash.size) {
+ ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ memcpy(trash.area, *env, delim - *env);
+ trash.area[delim - *env] = 0;
+
+ if (unsetenv(trash.area) != 0) {
+ ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
+ else
+ env++;
+ }
+ }
+ else {
+ struct cfg_kw_list *kwl;
+ int index;
+ int rc;
+
+ list_for_each_entry(kwl, &cfg_keywords.list, list) {
+ for (index = 0; kwl->kw[index].kw != NULL; index++) {
+ if (kwl->kw[index].section != CFG_GLOBAL)
+ continue;
+ if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
+ rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
+ if (rc < 0) {
+ ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+ else if (rc > 0) {
+ ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
+ err_code |= ERR_WARN;
+ goto out;
+ }
+ goto out;
+ }
+ }
+ }
+
+ ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
+ err_code |= ERR_ALERT | ERR_FATAL;
+ }
+
+ out:
+ free(errmsg);
+ return err_code;
+}
+
#include <proto/backend.h>
#include <proto/channel.h>
#include <proto/checks.h>
-#include <proto/compression.h>
#include <proto/dns.h>
#include <proto/stats.h>
#include <proto/filters.h>
"\x00" /* Compression Type : 0x00 = NULL compression */
};
-/* various keyword modifiers */
-enum kw_mod {
- KWM_STD = 0, /* normal */
- KWM_NO, /* "no" prefixed before the keyword */
- KWM_DEF, /* "default" prefixed before the keyword */
-};
-
-/* permit to store configuration section */
-struct cfg_section {
- struct list list;
- char *section_name;
- int (*section_parser)(const char *, int, char **, int);
- int (*post_section_parser)();
-};
-
/* Used to chain configuration sections definitions. This list
* stores struct cfg_section
*/
struct list sections = LIST_HEAD_INIT(sections);
-/* store post configuration parsing */
-
-struct cfg_postparser {
- struct list list;
- char *name;
- int (*func)();
-};
-
struct list postparsers = LIST_HEAD_INIT(postparsers);
-/* some of the most common options which are also the easiest to handle */
-struct cfg_opt {
- const char *name;
- unsigned int val;
- unsigned int cap;
- unsigned int checks;
- unsigned int mode;
-};
-
/* proxy->options */
static const struct cfg_opt cfg_opts[] =
{
char *cfg_scope = NULL; /* the current scope during the configuration parsing */
/* List head of all known configuration keywords */
-static struct cfg_kw_list cfg_keywords = {
+struct cfg_kw_list cfg_keywords = {
.list = LIST_HEAD_INIT(cfg_keywords.list)
};
* ('-'). Multiple CPU numbers or ranges may be specified. On success, it
* returns 0. otherwise it returns 1 with an error message in <err>.
*/
-static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
+unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, char **err)
{
int cur_arg = 0;
}
#endif
-/*
- * parse a line in a <global> section. Returns the error code, 0 if OK, or
- * any combination of :
- * - ERR_ABORT: must abort ASAP
- * - ERR_FATAL: we can continue parsing but not start the service
- * - ERR_WARN: a warning has been emitted
- * - ERR_ALERT: an alert has been emitted
- * Only the two first ones can stop processing, the two others are just
- * indicators.
- */
-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 */
- alertif_too_many_args(0, file, linenum, args, &err_code);
- goto out;
- }
- else if (!strcmp(args[0], "daemon")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.mode |= MODE_DAEMON;
- }
- else if (!strcmp(args[0], "master-worker")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*args[1]) {
- if (!strcmp(args[1], "no-exit-on-failure")) {
- global.tune.options |= GTUNE_NOEXIT_ONFAILURE;
- } else {
- ha_alert("parsing [%s:%d] : '%s' only supports 'no-exit-on-failure' option.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- global.mode |= MODE_MWORKER;
- }
- else if (!strcmp(args[0], "debug")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.mode |= MODE_DEBUG;
- }
- else if (!strcmp(args[0], "noepoll")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_EPOLL;
- }
- else if (!strcmp(args[0], "nokqueue")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_KQUEUE;
- }
- else if (!strcmp(args[0], "nopoll")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_POLL;
- }
- else if (!strcmp(args[0], "nosplice")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_SPLICE;
- }
- else if (!strcmp(args[0], "nogetaddrinfo")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_GAI;
- }
- else if (!strcmp(args[0], "noreuseport")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.tune.options &= ~GTUNE_USE_REUSEPORT;
- }
- else if (!strcmp(args[0], "quiet")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.mode |= MODE_QUIET;
- }
- else if (!strcmp(args[0], "tune.runqueue-depth")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.runqueue_depth != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.runqueue_depth = atol(args[1]);
-
- }
- else if (!strcmp(args[0], "tune.maxpollevents")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.maxpollevents != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.maxpollevents = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.maxaccept")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.maxaccept != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.maxaccept = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.chksize")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.chksize = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.recv_enough")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.recv_enough = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.buffers.limit")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.buf_limit = atol(args[1]);
- if (global.tune.buf_limit) {
- if (global.tune.buf_limit < 3)
- global.tune.buf_limit = 3;
- if (global.tune.buf_limit <= global.tune.reserved_bufs)
- global.tune.buf_limit = global.tune.reserved_bufs + 1;
- }
- }
- else if (!strcmp(args[0], "tune.buffers.reserve")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.reserved_bufs = atol(args[1]);
- if (global.tune.reserved_bufs < 2)
- global.tune.reserved_bufs = 2;
- if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
- global.tune.buf_limit = global.tune.reserved_bufs + 1;
- }
- else if (!strcmp(args[0], "tune.bufsize")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.bufsize = atol(args[1]);
- if (global.tune.bufsize <= 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "tune.maxrewrite")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.maxrewrite = atol(args[1]);
- if (global.tune.maxrewrite < 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "tune.idletimer")) {
- unsigned int idle;
- const char *res;
-
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
- if (res) {
- ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
- file, linenum, *res, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- if (idle > 65535) {
- ha_alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.idle_timer = idle;
- }
- else if (!strcmp(args[0], "tune.rcvbuf.client")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.client_rcvbuf != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.client_rcvbuf = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.rcvbuf.server")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.server_rcvbuf != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.server_rcvbuf = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.sndbuf.client")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.client_sndbuf != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.client_sndbuf = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.sndbuf.server")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.tune.server_sndbuf != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.server_sndbuf = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.pipesize")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.pipesize = atol(args[1]);
- }
- else if (!strcmp(args[0], "tune.http.cookielen")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.cookie_len = atol(args[1]) + 1;
- }
- else if (!strcmp(args[0], "tune.http.logurilen")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.requri_len = atol(args[1]) + 1;
- }
- else if (!strcmp(args[0], "tune.http.maxhdr")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.tune.max_http_hdr = atoi(args[1]);
- if (global.tune.max_http_hdr < 1 || global.tune.max_http_hdr > 32767) {
- ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 32767\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "tune.comp.maxlevel")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*args[1]) {
- global.tune.comp_maxlevel = atoi(args[1]);
- if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
- ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- } else {
- ha_alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "tune.pattern.cache-size")) {
- if (*args[1]) {
- global.tune.pattern_cache = atoi(args[1]);
- if (global.tune.pattern_cache < 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- } else {
- ha_alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "uid")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.uid != 0) {
- ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
- ha_warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
- err_code |= ERR_WARN;
- goto out;
- }
-
- }
- else if (!strcmp(args[0], "gid")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.gid != 0) {
- ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
- ha_warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
- err_code |= ERR_WARN;
- goto out;
- }
- }
- else if (!strcmp(args[0], "external-check")) {
- if (alertif_too_many_args(0, file, linenum, args, &err_code))
- goto out;
- global.external_check = 1;
- }
- /* user/group name handling */
- else if (!strcmp(args[0], "user")) {
- struct passwd *ha_user;
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.uid != 0) {
- ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
- err_code |= ERR_ALERT;
- goto out;
- }
- errno = 0;
- ha_user = getpwnam(args[1]);
- if (ha_user != NULL) {
- global.uid = (int)ha_user->pw_uid;
- }
- else {
- ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- }
- else if (!strcmp(args[0], "group")) {
- struct group *ha_group;
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.gid != 0) {
- ha_alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
- err_code |= ERR_ALERT;
- goto out;
- }
- errno = 0;
- ha_group = getgrnam(args[1]);
- if (ha_group != NULL) {
- global.gid = (int)ha_group->gr_gid;
- }
- else {
- ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- }
- /* end of user/group name handling*/
- else if (!strcmp(args[0], "nbproc")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.nbproc = atol(args[1]);
- if (global.nbproc < 1 || global.nbproc > LONGBITS) {
- ha_alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
- file, linenum, args[0], LONGBITS, global.nbproc);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "nbthread")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.nbthread = parse_nbthread(args[1], &errmsg);
- if (!global.nbthread) {
- ha_alert("parsing [%s:%d] : '%s' %s.\n",
- file, linenum, args[0], errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "maxconn")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.maxconn != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.maxconn = atol(args[1]);
-#ifdef SYSTEM_MAXCONN
- if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
- ha_alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
- global.maxconn = DEFAULT_MAXCONN;
- err_code |= ERR_ALERT;
- }
-#endif /* SYSTEM_MAXCONN */
- }
- else if (!strcmp(args[0], "ssl-server-verify")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if (strcmp(args[1],"none") == 0)
- global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
- else if (strcmp(args[1],"required") == 0)
- global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
- else {
- ha_alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "maxconnrate")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.cps_lim != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.cps_lim = atol(args[1]);
- }
- else if (!strcmp(args[0], "maxsessrate")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.sps_lim != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.sps_lim = atol(args[1]);
- }
- else if (!strcmp(args[0], "maxsslrate")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.ssl_lim != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.ssl_lim = atol(args[1]);
- }
- else if (!strcmp(args[0], "maxcomprate")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.comp_rate_lim = atoi(args[1]) * 1024;
- }
- else if (!strcmp(args[0], "maxpipes")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.maxpipes != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.maxpipes = atol(args[1]);
- }
- else if (!strcmp(args[0], "maxzlibmem")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
- }
- else if (!strcmp(args[0], "maxcompcpuusage")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- compress_min_idle = 100 - atoi(args[1]);
- if (compress_min_idle > 100) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
-
- else if (!strcmp(args[0], "ulimit-n")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.rlimit_nofile != 0) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.rlimit_nofile = atol(args[1]);
- }
- else if (!strcmp(args[0], "chroot")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.chroot != NULL) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.chroot = strdup(args[1]);
- }
- else if (!strcmp(args[0], "description")) {
- int i, len=0;
- char *d;
-
- if (!*args[1]) {
- ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- for (i = 1; *args[i]; i++)
- len += strlen(args[i]) + 1;
-
- if (global.desc)
- free(global.desc);
-
- global.desc = d = calloc(1, len);
-
- d += snprintf(d, global.desc + len - d, "%s", args[1]);
- for (i = 2; *args[i]; i++)
- d += snprintf(d, global.desc + len - d, " %s", args[i]);
- }
- else if (!strcmp(args[0], "node")) {
- int i;
- char c;
-
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
-
- for (i=0; args[1][i]; i++) {
- c = args[1][i];
- if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
- !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
- break;
- }
-
- if (!i || args[1][i]) {
- ha_alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
- " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- if (global.node)
- free(global.node);
-
- global.node = strdup(args[1]);
- }
- else if (!strcmp(args[0], "pidfile")) {
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.pidfile != NULL) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.pidfile = strdup(args[1]);
- }
- else if (!strcmp(args[0], "unix-bind")) {
- int cur_arg = 1;
- while (*(args[cur_arg])) {
- if (!strcmp(args[cur_arg], "prefix")) {
- if (global.unix_bind.prefix != NULL) {
- ha_alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
- err_code |= ERR_ALERT;
- cur_arg += 2;
- continue;
- }
-
- if (*(args[cur_arg+1]) == 0) {
- ha_alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.unix_bind.prefix = strdup(args[cur_arg+1]);
- cur_arg += 2;
- continue;
- }
-
- if (!strcmp(args[cur_arg], "mode")) {
-
- global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
- cur_arg += 2;
- continue;
- }
-
- if (!strcmp(args[cur_arg], "uid")) {
-
- global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
- cur_arg += 2;
- continue;
- }
-
- if (!strcmp(args[cur_arg], "gid")) {
-
- global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
- cur_arg += 2;
- continue;
- }
-
- if (!strcmp(args[cur_arg], "user")) {
- struct passwd *user;
-
- user = getpwnam(args[cur_arg + 1]);
- if (!user) {
- ha_alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
- file, linenum, args[0], args[cur_arg + 1 ]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- global.unix_bind.ux.uid = user->pw_uid;
- cur_arg += 2;
- continue;
- }
-
- if (!strcmp(args[cur_arg], "group")) {
- struct group *group;
-
- group = getgrnam(args[cur_arg + 1]);
- if (!group) {
- ha_alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
- file, linenum, args[0], args[cur_arg + 1 ]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- global.unix_bind.ux.gid = group->gr_gid;
- cur_arg += 2;
- continue;
- }
-
- ha_alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
- if (!parse_logsrv(args, &global.logsrvs, (kwm == KWM_NO), &errmsg)) {
- ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
- char *name;
-
- if (global.log_send_hostname != NULL) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
-
- if (*(args[1]))
- name = args[1];
- else
- name = hostname;
-
- free(global.log_send_hostname);
- global.log_send_hostname = strdup(name);
- }
- else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
- if (global.server_state_base != NULL) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
-
- if (!*(args[1])) {
- ha_alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
- err_code |= ERR_FATAL;
- goto out;
- }
-
- global.server_state_base = strdup(args[1]);
- }
- else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
- if (global.server_state_file != NULL) {
- ha_alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT;
- goto out;
- }
-
- if (!*(args[1])) {
- ha_alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
- err_code |= ERR_FATAL;
- goto out;
- }
-
- global.server_state_file = strdup(args[1]);
- }
- else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- chunk_destroy(&global.log_tag);
- chunk_initstr(&global.log_tag, strdup(args[1]));
- }
- else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (global.spread_checks != 0) {
- ha_alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
- err_code |= ERR_ALERT;
- goto out;
- }
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- global.spread_checks = atol(args[1]);
- if (global.spread_checks < 0 || global.spread_checks > 50) {
- ha_alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- }
- else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
- const char *err;
- unsigned int val;
-
- if (alertif_too_many_args(1, file, linenum, args, &err_code))
- goto out;
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- err = parse_time_err(args[1], &val, TIME_UNIT_MS);
- if (err) {
- ha_alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- global.max_spread_checks = val;
- if (global.max_spread_checks < 0) {
- ha_alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- }
- else if (strcmp(args[0], "cpu-map") == 0) {
- /* map a process list to a CPU set */
-#ifdef USE_CPU_AFFINITY
- char *slash;
- unsigned long proc = 0, thread = 0, cpus;
- int i, j, n, autoinc;
-
- if (!*args[1] || !*args[2]) {
- ha_alert("parsing [%s:%d] : %s expects a process number "
- " ('all', 'odd', 'even', a number from 1 to %d or a range), "
- " followed by a list of CPU ranges with numbers from 0 to %d.\n",
- file, linenum, args[0], LONGBITS, LONGBITS - 1);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- if ((slash = strchr(args[1], '/')) != NULL)
- *slash = 0;
-
- if (parse_process_number(args[1], &proc, &autoinc, &errmsg)) {
- ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- if (slash) {
- if (parse_process_number(slash+1, &thread, NULL, &errmsg)) {
- ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- *slash = '/';
-
- if (autoinc && atleast2(proc) && atleast2(thread)) {
- ha_alert("parsing [%s:%d] : %s : '%s' : unable to automatically bind "
- "a process range _AND_ a thread range\n",
- file, linenum, args[0], args[1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
-
- if (parse_cpu_set((const char **)args+2, &cpus, &errmsg)) {
- ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- if (autoinc &&
- my_popcountl(proc) != my_popcountl(cpus) &&
- my_popcountl(thread) != my_popcountl(cpus)) {
- ha_alert("parsing [%s:%d] : %s : PROC/THREAD range and CPU sets "
- "must have the same size to be automatically bound\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- for (i = n = 0; i < LONGBITS; i++) {
- /* No mapping for this process */
- if (!(proc & (1UL << i)))
- continue;
-
- /* Mapping at the process level */
- if (!thread) {
- if (!autoinc)
- global.cpu_map.proc[i] = cpus;
- else {
- n += my_ffsl(cpus >> n);
- global.cpu_map.proc[i] = (1UL << (n-1));
- }
- continue;
- }
-
- /* Mapping at the thread level */
- for (j = 0; j < MAX_THREADS; j++) {
- /* Np mapping for this thread */
- if (!(thread & (1UL << j)))
- continue;
-
- if (!autoinc)
- global.cpu_map.thread[i][j] = cpus;
- else {
- n += my_ffsl(cpus >> n);
- global.cpu_map.thread[i][j] = (1UL << (n-1));
- }
- }
- }
-#else
- ha_alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n",
- file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
-#endif /* ! USE_CPU_AFFINITY */
- }
- else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
- if (alertif_too_many_args(3, file, linenum, args, &err_code))
- goto out;
-
- if (*(args[2]) == 0) {
- ha_alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- /* "setenv" overwrites, "presetenv" only sets if not yet set */
- if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
- ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else if (!strcmp(args[0], "unsetenv")) {
- int arg;
-
- if (*(args[1]) == 0) {
- ha_alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- for (arg = 1; *args[arg]; arg++) {
- if (unsetenv(args[arg]) != 0) {
- ha_alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- }
- else if (!strcmp(args[0], "resetenv")) {
- extern char **environ;
- char **env = environ;
-
- /* args contain variable names to keep, one per argument */
- while (*env) {
- int arg;
-
- /* look for current variable in among all those we want to keep */
- for (arg = 1; *args[arg]; arg++) {
- if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
- (*env)[strlen(args[arg])] == '=')
- break;
- }
-
- /* delete this variable */
- if (!*args[arg]) {
- char *delim = strchr(*env, '=');
-
- if (!delim || delim - *env >= trash.size) {
- ha_alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- memcpy(trash.area, *env, delim - *env);
- trash.area[delim - *env] = 0;
-
- if (unsetenv(trash.area) != 0) {
- ha_alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- else
- env++;
- }
- }
- else {
- struct cfg_kw_list *kwl;
- int index;
- int rc;
-
- list_for_each_entry(kwl, &cfg_keywords.list, list) {
- for (index = 0; kwl->kw[index].kw != NULL; index++) {
- if (kwl->kw[index].section != CFG_GLOBAL)
- continue;
- if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
- rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
- if (rc < 0) {
- ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
- err_code |= ERR_ALERT | ERR_FATAL;
- }
- else if (rc > 0) {
- ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
- err_code |= ERR_WARN;
- goto out;
- }
- goto out;
- }
- }
- }
-
- ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
- err_code |= ERR_ALERT | ERR_FATAL;
- }
-
- out:
- free(errmsg);
- return err_code;
-}
-
void init_default_instance()
{
init_new_proxy(&defproxy);