diff --git a/Makefile b/Makefile index b4125e1c8..e41c4ff7f 100644 --- a/Makefile +++ b/Makefile @@ -903,7 +903,8 @@ else 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 \ diff --git a/include/common/cfgparse.h b/include/common/cfgparse.h index 6e35bc948..2ffcea0b0 100644 --- a/include/common/cfgparse.h +++ b/include/common/cfgparse.h @@ -36,6 +36,13 @@ #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 */ @@ -59,10 +66,35 @@ struct cfg_kw_list { 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); @@ -89,6 +121,7 @@ int too_many_args(int maxarg, char **args, char **msg, int *err_code); 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 does not have at least one of the diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c new file mode 100644 index 000000000..a00d96255 --- /dev/null +++ b/src/cfgparse-global.c @@ -0,0 +1,1123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * parse a line in a 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; +} + diff --git a/src/cfgparse.c b/src/cfgparse.c index c9d69bc92..05bd951a2 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -118,45 +117,13 @@ const char sslv3_client_hello_pkt[] = { "\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[] = { @@ -219,7 +186,7 @@ int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */ 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) }; @@ -688,7 +655,7 @@ int parse_process_number(const char *arg, unsigned long *proc, int *autoinc, cha * ('-'). Multiple CPU numbers or ranges may be specified. On success, it * returns 0. otherwise it returns 1 with an error message in . */ -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; @@ -726,1113 +693,6 @@ static unsigned long parse_cpu_set(const char **args, unsigned long *cpu_set, ch } #endif -/* - * parse a line in a 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);