diff --git a/doc/configuration.txt b/doc/configuration.txt index 047376963f..fbaeef8716 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -490,7 +490,10 @@ details. The following list of keywords is supported. Most of them may only be used in a limited set of section types. Some of them are marked as "deprecated" because they are inherited from an old syntax which may be confusing or functionnally -limited, and there are new recommended keywords to replace them. +limited, and there are new recommended keywords to replace them. Keywords +listed with [no] can be optionally inverted using the "no" prefix, ex. "no +option contstats". This makes sense when the option has been enabled by default +and must be disabled for a specific instance. keyword defaults frontend listen backend @@ -523,31 +526,31 @@ mode X X X X monitor fail - X X - monitor-net X X X - monitor-uri X X X - -option abortonclose X - X X -option allbackups X - X X -option checkcache X - X X -option clitcpka X X X - -option contstats X X X - -option dontlognull X X X - -option forceclose X - X X +[no] option abortonclose X - X X +[no] option allbackups X - X X +[no] option checkcache X - X X +[no] option clitcpka X X X - +[no] option contstats X X X - +[no] option dontlognull X X X - +[no] option forceclose X - X X option forwardfor X X X X +[no] option http_proxy X X X X option httpchk X - X X -option httpclose X X X X +[no] option httpclose X X X X option httplog X X X X -option logasap X X X - -option nolinger X X X X -option http_proxy X X X X -option persist X - X X -option redispatch X - X X +[no] option logasap X X X - +[no] option nolinger X X X X +[no] option persist X - X X +[no] option redispatch X - X X option smtpchk X - X X -option srvtcpka X - X X +[no] option srvtcpka X - X X option ssl-hello-chk X - X X option tcpka X X X X option tcplog X X X X -option tcpsplice X X X X -option transparent X X X - -redisp X - X X -redispatch X - X X +[no] option tcpsplice X X X X +[no] option transparent X X X - +redisp X - X X (deprecated) +redispatch X - X X (deprecated) reqadd - X X X reqallow - X X X reqdel - X X X diff --git a/include/common/cfgparse.h b/include/common/cfgparse.h index e21c4c5fd4..bba18cfe1b 100644 --- a/include/common/cfgparse.h +++ b/include/common/cfgparse.h @@ -32,8 +32,8 @@ extern int cfg_maxpconn; extern int cfg_maxconn; -int cfg_parse_global(const char *file, int linenum, char **args); -int cfg_parse_listen(const char *file, int linenum, char **args); +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 readcfgfile(const char *file); diff --git a/src/cfgparse.c b/src/cfgparse.c index 9610cf4c3d..ae05da0aa4 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -90,29 +90,29 @@ static const struct { unsigned int checks; } cfg_opts[] = { -#ifdef TPROXY - { "transparent", PR_O_TRANSP, PR_CAP_FE }, -#endif - { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 }, - { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 }, - { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 }, - { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 }, - { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 }, - { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 }, - { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 }, { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 }, - { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 }, - { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 }, - { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 }, - { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 }, { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 }, + { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 }, + { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 }, + { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 }, + { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 }, + { "forceclose", PR_O_FORCE_CLO, PR_CAP_BE, 0 }, + { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 }, + { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 }, + { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 }, + { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 }, + { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 }, { "persist", PR_O_PERSIST, PR_CAP_BE, 0 }, - { "forceclose", PR_O_FORCE_CLO | PR_O_HTTP_CLOSE, PR_CAP_BE, 0 }, + { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 }, + { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 }, #ifdef CONFIG_HAP_TCPSPLICE - { "tcpsplice", PR_O_TCPSPLICE , PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM }, + { "tcpsplice", PR_O_TCPSPLICE, PR_CAP_BE|PR_CAP_FE, LSTCHK_TCPSPLICE|LSTCHK_NETADM }, +#endif +#ifdef TPROXY + { "transparent", PR_O_TRANSP, PR_CAP_FE, 0 }, #endif - { NULL, 0, 0 } + { NULL, 0, 0, 0 } }; @@ -261,7 +261,7 @@ int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char /* * parse a line in a section. Returns 0 if OK, -1 if error. */ -int cfg_parse_global(const char *file, int linenum, char **args) +int cfg_parse_global(const char *file, int linenum, char **args, int inv) { if (!strcmp(args[0], "global")) { /* new section */ @@ -516,7 +516,7 @@ static void init_default_instance() * Parse a line in a , , or section. * Returns 0 if OK, -1 if error. */ -int cfg_parse_listen(const char *file, int linenum, char **args) +int cfg_parse_listen(const char *file, int linenum, char **args, int inv) { static struct proxy *curproxy = NULL; struct server *newsrv = NULL; @@ -1145,8 +1145,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args) else if (!strcmp(args[0], "option")) { int optnum; - if (*(args[1]) == 0) { - Alert("parsing [%s:%d] : '%s' expects an option name.\n", file, linenum, args[0]); + if (*(args[1]) == '\0') { + Alert("parsing [%s:%d]: '%s' expects an option name.\n", + file, linenum, args[0]); return -1; } @@ -1154,12 +1155,22 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (!strcmp(args[1], cfg_opts[optnum].name)) { if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) return 0; - curproxy->options |= cfg_opts[optnum].val; - global.last_checks |= cfg_opts[optnum].checks; + + if (!inv) + curproxy->options |= cfg_opts[optnum].val; + else + curproxy->options &= ~cfg_opts[optnum].val; + return 0; } } + if (inv) { + Alert("parsing [%s:%d]: negation is not supported for option '%s'.\n", + file, linenum, args[1]); + return -1; + } + if (!strcmp(args[1], "httplog")) /* generate a complete HTTP log */ curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES; @@ -1287,6 +1298,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args) if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) return 0; + Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n", + file, linenum, args[0]); + /* enable reconnections to dispatch */ curproxy->options |= PR_O_REDISP; } @@ -2406,7 +2420,7 @@ int readcfgfile(const char *file) init_default_instance(); while (fgets(thisline, sizeof(thisline), f) != NULL) { - int arg; + int arg, inv = 0 ; char *end; char *args[MAX_LINE_ARGS + 1]; char *line = thisline; @@ -2502,6 +2516,17 @@ int readcfgfile(const char *file) args[arg] = line; } + if (!strcmp(args[0], "no")) { + inv = 1; + for (arg=0; *args[arg+1]; arg++) + args[arg] = args[arg+1]; // shift args after inversion + } + + if (inv && strcmp(args[0], "option")) { + Alert("parsing [%s:%d]: negation currently supported only for options.\n", file, linenum); + return -1; + } + if (!strcmp(args[0], "listen") || !strcmp(args[0], "frontend") || !strcmp(args[0], "backend") || @@ -2514,11 +2539,11 @@ int readcfgfile(const char *file) switch (confsect) { case CFG_LISTEN: - if (cfg_parse_listen(file, linenum, args) < 0) + if (cfg_parse_listen(file, linenum, args, inv) < 0) return -1; break; case CFG_GLOBAL: - if (cfg_parse_global(file, linenum, args) < 0) + if (cfg_parse_global(file, linenum, args, inv) < 0) return -1; break; default: @@ -2849,12 +2874,28 @@ int readcfgfile(const char *file) curproxy = curproxy->next; } + if (cfgerr > 0) { Alert("Errors found in configuration file, aborting.\n"); return -1; } - else - return 0; + + /* + * Recount currently required checks. + */ + + for (curproxy=proxy; curproxy; curproxy=curproxy->next) { + int optnum; + + for (optnum = 0; cfg_opts[optnum].name; optnum++) { + if (!(curproxy->options & cfg_opts[optnum].val)) + continue; + + global.last_checks |= cfg_opts[optnum].checks; + } + } + + return 0; } diff --git a/src/proto_http.c b/src/proto_http.c index 7d36b0a6be..f387d0b443 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1795,7 +1795,7 @@ int process_cli(struct session *t) } /* We might have to check for "Connection:" */ - if (((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE) && + if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) && !(t->flags & SN_CONN_CLOSED)) { char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx, delta, val; @@ -2005,7 +2005,7 @@ int process_cli(struct session *t) * Note that we do not need to add it in case of HTTP/1.0. */ if (!(t->flags & SN_CONN_CLOSED) && - ((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE)) { + ((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) { if ((unlikely(msg->sl.rq.v_l != 8) || unlikely(req->data[msg->som + msg->sl.rq.v + 7] != '0')) && unlikely(http_header_add_tail2(req, &txn->req, &txn->hdr_idx, @@ -2914,7 +2914,7 @@ int process_srv(struct session *t) } /* We might have to check for "Connection:" */ - if (((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE) && + if (((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO)) && !(t->flags & SN_CONN_CLOSED)) { char *cur_ptr, *cur_end, *cur_next; int cur_idx, old_idx, delta, val; @@ -3059,7 +3059,7 @@ int process_srv(struct session *t) * Note that we do not need to add it in case of HTTP/1.0. */ if (!(t->flags & SN_CONN_CLOSED) && - ((t->fe->options | t->be->options) & PR_O_HTTP_CLOSE)) { + ((t->fe->options | t->be->options) & (PR_O_HTTP_CLOSE|PR_O_FORCE_CLO))) { if ((unlikely(msg->sl.st.v_l != 8) || unlikely(req->data[msg->som + 7] != '0')) && unlikely(http_header_add_tail2(rep, &txn->rsp, &txn->hdr_idx,